The following is a guest post by Alex Young (@the_alexyoung). Alex has created a simple technique to “rotate” the subject of a photo simply by hiding and showing multiple stacked photographs taken at different angles. Enjoy!
Web designers and developers have always fascinated us with fun and engaging ways we interact with their websites. I love discovering new techniques that these designers/developers have come up with. One technique in particular that sparked my interest is something that I saw on Warby Parker’s website. They were able to create a cool effect where model follows the user’s mouse, showing off the different angles of the frames.
I’ve seen this technique mainly used for showing off sunglasses, but I’m interested to see what you guys can come up with for other real-world applications.
Before we begin, you will need a few things. Well, seven things to be exact. You are going to need seven photos of something taken at seven different angles.
HTML Setup
What we are setting up is a container called “faces”, then have created an area that we are going to use to display the photos – “face-area”. We also have a div
to hold each of the seven individual images.
<div id="faces">
<div id="face-area">
<div id="image-1" style="display: none;">
<img src="/images/look-left-3.jpg">
</div>
<div id="image-2" style="display: none;">
<img src="/images/look-left-2.jpg">
</div>
<div id="image-3" style="display: none;">
<img src="/images/look-left-1.jpg">
</div>
<div id="image-4" style="display: none;">
<img src="/images/look-center.jpg">
</div>
<div id="image-5" style="display: none;">
<img src="/images/look-right-1.jpg">
</div>
<div id="image-6" style="display: none;">
<img src="/images/look-right-2.jpg">
</div>
<div id="image-7" style="display: none;">
<img src="/images/look-right-3.jpg">
</div>
Now we’ll create a div
that is going to do exactly what the name implies. It is going to lay on top of the other div
. We can divide this div
into 7 small columns and divide them equally across it. These 7 columns will be used to listen for when the mouse is hovering over that specific one. Adding “data-number” to each div
will allow us to refer to each in jQuery later on.
<div id="the_faces_overlay">
<div class="the_faces" data-number="1"></div>
<div class="the_faces" data-number="2"> </div>
<div class="the_faces" data-number="3"></div>
<div class="the_faces" data-number="4"></div>
<div class="the_faces" data-number="5"></div>
<div class="the_faces" data-number="6"></div>
<div class="the_faces" data-number="7"></div>
</div>
</div><!-- END #face-area -->
</div> <!-- END #faces -->
CSS Setup
Most of the CSS is pretty self-explanatory. There is one thing I need to mention that is important, make sure that the 7 columns fit perfectly together across the span
of the div
.
body {
background: #333
}
#faces {
height: 333px;
width: 500px;
margin: 0 auto;
border: 8px solid white;
}
#face-area {
height: 500px;
width: 333px;
position: relative;
}
#the_faces_overlay {
position: absolute;
width: 500px;
top: 0;
left: 0;
}
#faces .the_faces {
height: 333px;
width: 14.2857143%;
float: left;
margin: 0;
padding: 0;
}
jQuery Setup
We need to listen for when each of the columns are hovered over. This is where those “data-numbers” come in handy. If we wanted to add more columns down the road we wouldn’t have to add any more JavaScript.
// Reveal the "center" image
var centerImage = $("#image-4").show();
// Bind hovers to each column
$(".the_faces").each(function() {
$(this).on("mouseover", function() {
$("#image-" + $(this).attr("data-number")).show();
}).on("mouseout",function() {
$("#image-" + $(this).attr("data-number")).hide();
});
});
// Reset center image
$("#face-area").on("mouseleave", function() {
centerImage.show();
}).on("mouseenter", function() {
centerImage.hide();
});
Tada!
Check out this Pen!
There you have it! Now you have your very own, head turning model. Use it to show off your very own products. There are tons of uses for this out there. Let me know what you come up with.
Editor’s note: this would be a fun demo to work on adding touch support, wouldn’t it? Follows a swipe or something.
Very nice Chris, loving the simple javascript to make everything work.
It would be cool if we could add some code to detect the center image.
Nice effect.
To simplify the HTML, the ID’s and inline styles could be applied to the images themselves rather than needing a div around each one. Those divs, I think, are unnecessary markup here.
I wonder if you could also do something clever like track the cursor position over the parent div, and work out which image to show based on which fraction of the image the mouse is over. Same principal as is on display here, but may again allow the removal of more empty divs that are really only there to aid the visual effect.
I knocked up my suggestion (sorry Chris, I use JSFiddle >.<)
http://jsfiddle.net/dilapper/BQjBm/
Effectively removes all the markup used for hover events, and works out the segment of the image the cursor is over and loads the corresponding image. My variable names are a little dubious, and part of me wonders whether there is a more succinct way of doing the maths, but it works nonetheless!
@Eduardo: CSS only pretty cool
@David: http://jsfiddle.net/jsdev/X2y9f/2/
cached jquery objects.., id attributes not needed if just sequential.. leveraged .eq()
Awesome.
I thought I would give this a go with a slightly different method:
http://codepen.io/JTParrett/pen/AlEgF
It work’s, but in Chrome 26 the image flashes every time it changes, which is pretty undesirable.
Indeed it did. I just added some simple image pre-loading. Any better?
Another approach. Finds the cursor position to apply to according background image: http://codepen.io/JTParrett/pen/bHqjp
The*
That’s better. Now you only need to preload the images using AJAX instead.
Cheers dude :D
I just did a couple of updates to the pen. Could you tell me if the loading seems better and tell me if I did it correctly? I’m fairly new to ajax stuff :P
i solved a similar problem some time ago.
would be great to hear your opinions (i’m no pro)
http://codepen.io/ahoiii/pen/yraze
The Touchswipe plugin (http://labs.rampinteractive.co.uk/touchSwipe/demos/) should very happily provide for a touch centric interface.
I might just play with this.
Neat effect. I haven’t spent much time on it, but it looks like it could probably be cleaned up a bit to use less markup. Also, the JavaScript can be a little more efficient and easier to read, and should use $.data to get the data attributes:
An alternative method to help prevent the “flickering” issue in some browsers is to use absolute positioning and z-index to show/hide the images:
http://codepen.io/anon/pen/IsBHG
Trade-off: This method would be best suited when using small light-weight images, as you need to wait for the images to load.
The only CSS approach:
http://jsfiddle.net/coma/BZajk/11/
That’s awesome man!
Like! Very nice. Semantic markup too. Of course, it probably won’t work in IE8 or below, or Opera, or Android browsers… but still, it’s a nice solution.
Nicely done.
Eduardo, yours is about 100 times better. The code in this demo teaches people to write non-reusable js with hardcoded IDs everywhere, while your approach is adaptable and more versatile, nice job.
Wow! thank you guys! that was my first comment here!
That’s a well deserved approval.
I was wondering while reading the post if this could be done with HTML & CSS only and sure enough Eduardo proves it can. Awesome Job!
This is awesome!, I would love to avoid JS where ever I can.
Thanks for Sharing.
Nice work Eduardo. Keep commenting! ;)
Flickers in Chrome but this works http://jsfiddle.net/coma/BZajk/11/
Loving this feedback! What are some other uses for this are there?
Also, thanks for all the improvements to this. Always looking for new and better ways to do things.
Not sure if this is a different use as such (it is a radical change), but the first thing that came to mind for me was replacing carousels with user guided swaps. In that case though I’d recommend making the “selection” divs obvious; labelled, and not obscuring the image. The advantage being it would remove carousel autoload frustrations.
Amazing effect…if we used a tranparent gif or png with the subject well placed and CSS3 transitions, we cud achieve a 3D like effect…neat trick!
As already discussed on Twitter, this can be vastly improved by using more semantic HTML and allow JS to do what it does best – calculate things for us – in this case the mouse position and see what image to show accordingly. I am working on a screencast explaining the main issues, but here is a plain vanilla demo that works with keyboard, mouse and on touch devices (tested on Android in Firefox and Chrome) http://vanillawebdiet.com/demos/imageswivel/index.html . The flickering issue is also gone, this was not only a preload problem but also far too many event handlers and DOM interaction whilst moving the mouse.
Writeup done: http://christianheilmann.com/2013/05/17/giving-image-swivel-the-vanilla-web-diet-treatment/
Thanks , but I can this would be implemented with pure html & css and no jquery needed.
Cool effect! Would be a great app for jewelry or sculpture gallery. Thanks!
Eduardo=Genius
props to you +1
I wonder if this could be made to work with CSS transitions to make it look smoother.
As promised to Alex, here is a long post and a 25 minute screencast explaining the performance and maintenance issues with the demo code and how to re-write this without any library dependency and having keyboard and touch support whilst being fully maintainable by changing the HTML: http://christianheilmann.com/2013/05/17/giving-image-swivel-the-vanilla-web-diet-treatment/
Clever stuff. I’ve seen similar things done before without jquery, using ordinary javascript functions that fire on the onmouseover event. I wonder how it’d look with double the number of images, for a smoother effect. Perhaps this could be better achieved using video footage rather than still-shots, from which individual jpeg frames could be extracted.