Skip to main content

Animating objects in JavaScript

I needed a way to animate any property of an object in JavaScript (not necessarily even an element on the page). I did not find anything satisfactory (to me) online, so I decided to write my own. This is the result.

It's a simple animation class, loosely modeled on the Android animations API (in fact, the built-in animation interpolators are simple translations from the Android source code). It is very flexible, and supports animating any numeric property of any object. Animations run at 60 Hz to be fluid if UI elements are being animated.

Features:
  • Animate any numeric value
  • Start/stop, pause/resume/restart
  • Repeat - for a specified count or infinitely
  • Reverse animation on repeat.
  • Callbacks for start, stop, resume, end, repeat
  • Custom interpolators
  • NO dependencies
Download the code here (includes documentation for all methods).

A demo of the code is available here. It simply animates a box moving to the right, but demonstrates how the class is used. Prototype is used in the demo, but not required for the animation class itself.

This class will even work with discrete properties, as long as the animated property callback is written for that (example below).

Example Usage:

//make the y property of the coords object fall and bounce from 100 to 0 in 5 seconds
var coords = {x: 100, y: 100};
new Animation(coords, function(obj, val) { obj.y = val; }, 100, 0, 5000, Animation.Interpolators.Bounce()).start();

//animated a box moving 500px to the right in 1 second
//when the animation is over, set the animation reference to null
var anim = new Animation($("box"), function(obj, val) { obj.style.left = val + "px"; }, 0, 500, 1000, Animation.Interpolators.Accelerate(), {end: function() { anim = null; }});
anim.start();

//animate a continuously-blinking box
var anim = new Animation($("box"), function(obj, val) { obj.setOpacity(val); }, 0, 1, 500, Animation.Interpolators.AccelerateDecelerate());
anim.setRepeat(-1).setRepeatReverse(true);
anim.start();
//can do anim.stop() and anim.resume() to pause/resume the blinking

//animate through a set of discrete values
var colors = ["red", "yellow", "green", "blue", "black"];
var anim = new Animation($("box"), function(obj, val) {
    obj.style.background = colors[Math.floor(val) % colors.length];
}, 0, colors.length, 500 * colors.length, Animation.Interpolators.Linear()).setRepeat(-1).start();

I hope that this will become useful to people working with animations in JavaScript. Please leave feedback and suggestions on how to improve this, or any features that you would like to see.

Comments

Popular posts from this blog

Linux on XPS 15 9550/9560 with TB16 Dock [Update:3/29]

Finally got a laptop to replace my fat tower at work - Dell XPS 15 9560. I was allowed to choose which one I wanted and chose the XPS for its Linux support since Dell ships developer edition XPS's running Ubuntu so I figured Linux support would be better than other manufacturers. At first they got me the model with the 4K screen but my monitors are 2K and multi-dpi support in Linux is virtually non-existent and even hi-dpi support on its own is pretty terrible. So I got it exchanged for the model with the regular 1080p screen (which happened to also be the updated 9560 model), which works much better. I'm very glad to report that pretty much everything works, including the TB16 desktop dock, with just a bit of settings tweaking. This post is to help anybody considering getting this setup or looking for help getting things working. For now, I am running Kubuntu 16.04 with KDE Neon installed.

List of things I explicitly tested and work:
WiFi, BluetoothThunderbolt charging from T…

Drawing Dashed Lines on an HTML5 Canvas

The canvas element in HTML is great, but has one strange shortcoming: it cannot draw dashed lines (natively). However, dashed lines seem like a pretty common thing to draw, which only highlights the problem.

Looking around, I've noticed several solutions to this problem. Some use trig, and others use their own libraries that must be imported. So in the end, I decided to create my own method.

This code will add the function to all canvas elements, both those already on the page, and any that are dynamically added later.

Here is the code:
CanvasRenderingContext2D.prototype.dashedLine = function(x1, y1, x2, y2, dashLen) { if (dashLen == undefined) dashLen = 2; this.beginPath(); this.moveTo(x1, y1); var dX = x2 - x1; var dY = y2 - y1; var dashes = Math.floor(Math.sqrt(dX * dX + dY * dY) / dashLen); var dashX = dX / dashes; var dashY = dY / dashes; var q = 0; while (q++ < dashes) { x1 += dashX; y1 += dashY; this[q …

Listening for Window Resize events with Prototype

Recently, I came across an issue I had with full-screen (more specifically, full-viewport) canvas drawing. It all worked fine, except that the canvas dimensions must be specified in pixels, as opposed to percentages. This means you can't just set the canvas' width and height to "100%" and be done with it...

The dimensions were automatically set when the page loaded, but if the user resized the browser window after that, the canvas would stay the same size, and would be either too big or too small. Thus, the canvas must be resized every time the browser window is resized.

Prototype makes all of this easy. All that's necessary is to attach a listener to the onresize event of the window object, and then use document.viewport.getDimensions() to determine the new width and height.

Here's some sample code:

Event.observe(window, "resize", function() { var width = document.viewport.getWidth(); var height = document.viewport.getHeight(); var dims …