First we get the current time in milliseconds using Date.now(). First we need to update the CSS to put a background image in the container:
Since the background image will be scrolling, it must be wider than the image container. By tying the animation progress to the position of the user’s face, we can create the illusion that the user is ‘looking around’ the object. Words: Matt Campbell
Matt Campbell is an expert in HTML5, JavaScript and LAMP. First, download the js file and reference it in your head tag:
This will expose a global htracker object, which we’ll use later. The HTML and CSS code should look something like this:
Tracking the images in code
We need a very basic structure in the code to track and fade the images. This would replace the animate() function we were using before. In the update function, the first opacity line instructs the middle image to fade in between 33% and 66% of the animation. This is necessary because before the animation is at 66% progress, the final image would calculate progress — 0.66 as a negative number (for instance, -0.66) – it’s better to just keep it at in that case, since that image is not supposed to be fading yet. Modern web users have embraced video, but developers often find video integration problematic owing to cross-device/platform limitations (most mobile browsers do not support autoplay for inline video) and fewer opportunities to infuse playback with user interactivity. In fact the bottom image is never faded at all – it is just what the user sees first. Next, we pass the resulting progress variable to our animation to update the fades of the images. Since sine waves are in the -1 to 1 range, we have to normalise the range using (1 + angle) * 0.5. In the previous animate() function, we can update this property directly after the shader.update(progress) call:
function animate() {
var angle = Math.sin(Date.now() * 0.002);
var progress = (1 + angle) * 0.5;
shader.update(progress);
/* Move the background image */
container.style.backgroundPosition = -50 + progress * 50 + ‘px 0’;
requestAnimationFrame(animate);
}
As the animation progresses, this will move the background 50 pixels. Image set-up
First you’ll need to create three images of the same object/scene with different lighting configurations. The headtrackr library needs both a video and a canvas element to work its magic. With some fairly simple methods, you can replicate video-like effects without needing to transcode large files or fight autoplay restrictions on mobile devices. If your browser doesn’t support this, it is possible to use setTimeout instead:
Animating other properties
Animating the opacity is already an interesting effect, but you can animate any CSS property in the same way. This guide will step through some simple techniques to create dynamic lighting effects by progressively adjusting the opacity of three image layers. Based on that progress variable we can fade the top images appropriately so that the middle image finishes its fade-in before the final image:
The clamp function here simply keeps progress within the bounds of and 0.33 (the max it will be divided by). We’ll also show some ways to enhance these animations with a few fun opportunities for user interactions. One cool addition is to add a background image that moves along with the progress variable. The final image starts fading at 66% and finishes at 99% (basically the end). This will delay the fading of that image until the animation progress is beyond 66% (the only time progress — 0.66 would be positive). By placing opacity-based animation layers in front of a background plane, a parallax effect helps ‘sell’ our illusion of lightingStacking the images
This boils down to the following code-level process:
Set up a div container element that has position:relative style. The absolute positioning will enable the images to stack on top of each other while the container’s relative style prevents the images from escaping to the top of the page. That event will tell us the x (horizontal) position of the user’s head, which we will simplify to the 0.1 range and pass on to the animation. We’ll capture the value of the user’s face from the webcam and adjust the light shading to mimic a real-world interaction – check out a demo. But in this case we didn’t need a new shiny library or browser update to solve a problem, just a few pre-existing, dependable techniques. As our animation progresses, the second and third images move to full opacity, gradually obscuring the layers behind themFinally we use requestAnimationFrame to call a function the next time the browser paints the window – this is usually synced to your monitor’s refresh rate. The code involved is neither new nor complex, although hopefully you will agree that the end result is pretty neat. Add each img inside the container with position: absolute. This structure can also keep track of the animation’s progress. Now after headtrackr finds your head, you should be able to move around in order to change the light shading animation. This would create a ‘parallax’ effect, adding even more depth to the scene (here’s an example). The resulting effect will look as smooth as video – check out the demo. Adding interactivity
Since the animation reacts to the value of the progress variable, we can choose to adjust that variable based on any input instead of just bouncing it with a sine formula. The headtrackr library fires this event any time it has an updated position for the user’s head. Our animation expects a range of to 1.