I’m currently writing a demo that will use a small repeated random animation for some elements; before getting to that, I though it might be helpful to look at ways in which that kind of random movement might be achieved, particularly with breaking web technologies.
For this example, I’m using the Web Animation API, a unified method of creating animations using the flexibility and power of JavaScript, without the traditional need for frameworks (JQuery, GreenSock), setTimeout
, or requestAnimationFrame()
. At this time, the API is supported at different levels in modern browsers: you’ll see the best results in the latest versions of Chrome and Firefox.
Markup & CSS
However random the motion, we usually want to limit the movement of the element to a particular container, be it the <body>
or another element:
<div id="container">
</div>
The CSS for this example is quite straightforward; the image to be inserted, target
, is given an absolute position so that it can be moved freely with JavaScript:
#container {
height:20vh;
width:100%;
}
#target {
position: absolute;
}
(In the demo I’ve also provided target
with a drop-shadow
filter)
The JavaScript
To start the script added to the bottom of the page, we need to identify the container:
var container = document.getElementById("container");
Because the image may take a moment to load (confusing or disrupting our script) I’ll load it via JavaScript and append it to the container element, using an onload
to guarantee that nothing starts until the image is loaded:
var target = document.createElement("img");
target.id = "target";
target.onload = function() {
floatHead();
}
target.src = "head.png";
container.appendChild(target);
The animation is created through three functions. The first creates a new random position (newX
and newY
) for the target
element, within the confines of the container
(less the width and height of the target
, so that the image does not move over the edge of the container
).
function makeNewPosition() {
var containerVspace = container.offsetHeight - target.offsetHeight,
containerHspace = container.offsetWidth - target.offsetWidth,
newX = Math.floor(Math.random() * containerVspace),
newY = Math.floor(Math.random() * containerHspace);
return [newX, newY];
}
The new position is returned as a simple array.
The next function calculates the speed of the motion, i.e. how long the target takes to get to its new location, measured in milliseconds. It is passed two arrays: prev
contains the original X
and Y
position of the target, and next
contains the location it is headed for.
function velocity(prev, next) {
var x = Math.abs(prev[1] - next[1]),
y = Math.abs(prev[0] - next[0]),
larger = x > y ? x : y,
speedModifier = 0.1,
speed = Math.ceil(larger / speedModifier);
return speed;
}
The final function moves the target
:
function floatHead() {
var newPos = makeNewPosition(),
oldTop = target.offsetTop,
oldLeft = target.offsetLeft,
target.animate([
{ top: oldTop+"px", left: oldLeft+"px" },
{ top: newPos[0]+"px", left: newPos[1]+"px" }
], {
duration: velocity([oldTop, oldLeft],newPos),
fill: "forwards"
}).onfinish = function() {
floatHead();
}
}
The whole thing is set in motion by calling the floatHead()
once the image is loaded.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/OyRORZ