You can now do even more in JavaScript than you ever could in Flash. Google and the V8 team developed new technology that pressured all mainstream browsers to make JavaScript as efficient as it can be. The performance improvements, which are something like 100 times the speed of old JavaScript engines from pre-2008, have led to the development of new rendering standards like WebGL and Canvas. It’s now even typical for say, graphics demos on Pouet to be made in three.js alongside all the contributions for c64 and Amiga that have been made for years. These events helped prompt my own decision to just focus on web development rather than get further into iOS development, when I was trying that out in 2012.
So, this technology is just waiting to be used, but how do you actually put things together in a simple, organized way? Starting from scratch (because when I start anywhere else I don’t learn as much), you can set up a run loop to animate programs using setInterval():
setInterval(function() {
moveSomethingOnTheScreen();
}, 200);
Maybe you want your moveSomethingOnTheScreen
method to be a function of some
“time” value that’s incremented regularly. That way, you can control
the speed of the motion, and everything you want to animate will use
this single time value to determine where they should appear:
var time = 0;
setInterval(function() {
moveSomethingOnTheScreen(time);
time += 0.01;
}, 200);
The 200 I’m passing in to setInterval
means “run this every 200
milliseconds”. It’s kind of arbitrary… you can increase or decrease
it to whatever you want and see what happens. You can also let the
browser decide what this value should be with
requestAnimationFrame().
var time = 0;
function moveSomethingOnTheScreen() {
// move a DOM element or something
time += 0.01;
requestAnimationFrame(moveSomethingOnTheScreen);
};
requestAnimationFrame(moveSomethingOnTheScreen);
If you want to stop the animation, setInterval and
requestAnimationFrame both return an ID that you can call
clearInterval()
or cancelAnimationFrame()
on. Even when you’re using
comprehensive drawing frameworks like three.js or
Pixi.js, handling
the animation step with requestAnimationFrame()
is still the norm.
That’s all you need for animation—but what do you want to animate? You can hook this run loop up to any visualization that JavaScript can reach: graphs, math visualizations, 3D scenes, etc. Libraries like these don’t render HTML dom elements—that’s too limiting for graphics. Most of them render with Canvas or SVG.
The HTML <canvas>
element is fun to mess around with, and there’s a
lot you can do with just that. In fact, WebGL all happens through the
Canvas element, so whatever you want to do, you should learn the
basics of Canvas. Mozilla’s Canvas tutorial and API docs are
helpful. When using Canvas, keep in mind that the browser only thinks
of it as some arbitrary bitmap—a series of colored pixels: any
shapes you draw sort of slip out of your fingers and into the
bitmap. You can’t do var circle = canvasContext.arc();
and then move
that circle around because arc()
, along with all the drawing methods,
are void type and don’t return anything. This constraint is fun to
work around because anything is still possible with Canvas. But if you
need to treat parts of your graphics as objects because they’re
interactive, like responding to mouse movement, that’s where it
quickly gets too complicated because there’s too much to keep track
of, including UX subtleties that you shouldn’t be expected to
handle. In that case, I recommend using a Canvas-based framework like
Pixi.js.
I’ve been working on porting these astronomy visualizations originally developed at the University of Nebraska from Flash to JavaScript (astro-simulations). All this new web technology is well-suited for these kinds of things. I’m using React because from what I’ve seen, the code just becomes simpler and more reliable when you’re not manually manipulating DOM elements. React is a large library though—you can get a similar development experience by combining S.js with JSX.
So to show how you can actually use the animation example above,
here’s the animate function that runs in a loop to animate a three.js
scene. You can see how the sky color is dynamic: getSkyColor()
returns a blue color when the sun is above the horizon, and black when
it’s beneath it.
animate() {
this.sun.position.x = 50 * Math.cos(this.props.observerAngle);
this.sun.position.z = 50 * Math.sin(this.props.observerAngle);
this.sun.rotation.y = -this.props.observerAngle +
THREE.Math.degToRad(90);
this.skyMaterial.color.setHex(this.getSkyColor(this.props.observerAngle));
this.moon.position.x = 50 * Math.cos(this.props.moonObserverPos);
this.moon.position.z = 50 * Math.sin(this.props.moonObserverPos);
this.moon.rotation.y = -this.props.moonObserverPos + THREE.Math.degToRad(90);
this.renderScene();
this.frameId = requestAnimationFrame(this.animate);
}
From lunar-phase-simulator/HorizonView.jsx
The sun and moon move in a circular orbit created by passing in radian
values to sine and cosine functions. I don’t know the math offhand—I
just work through trial and error. The observerAngle
and
moonObserverPos
values are being passed in from the main React
component in main.jsx, and are controlled and incremented from there,
in their own animate loop:
animate() {
const me = this;
this.setState(prevState => ({
observerAngle: me.incrementAngle(prevState.observerAngle),
moonPhase: me.incrementMoonPhaseAngle(prevState.moonPhase),
moonObserverPos: me.getMoonObserverPos(
prevState.observerAngle, prevState.moonPhase)
}));
this.frameId = requestAnimationFrame(this.animate);
}
From lunar-phase-simulator/main.jsx
So, through methodical organization and trial and error, you can build these pieces up to make any sort of visualization as a function of a few pieces of core data, tied together in sync.
Here’s my Lunar Phase Simulator that’s still in progress. The animation basics are in place—at the moment I need to fix some problems with the mouse interactions.
![Lunar phase simulator screeshot](/img/assets/lunar-phase-simulator.png)
Screenshot of Lunar Phase Simulator; it is still in progress
Printed from: https://compiled.ctl.columbia.edu/articles/how-to-animate-graphical-javascript-programs/