This is my first in the series of JavaScript library recommendation articles. I advocate for JavaScript because it is accessible and ubiquitous. In this article, I introduce a very atomic, renderer agnostic 2D drawing library that supports canvas
, svg
, and webgl
. I use it mostly as an animation library, because its ability to integrate with so many other libraries, such as Tween.js.
Two.js
Getting started
According to their official website:
Two.js is a two-dimensional drawing api geared towards modern web browsers. It is renderer agnostic enabling the same api to draw in multiple contexts:
svg
,canvas
, andwebgl
.
It's called two.js because of its tribute to the famous 3D rendering library three.js. Two.js has a very straightforward application programming interface (api), and it's the same for svg
, canvas
, and webgl
rendering contexts. So it is fairly easy to get started.
First, download the JavaScript file and include it in your project through <script src="./path/to/two.js"></script>
. Then, you are all set to go.
// get a container element to put your instance of two in it
var container = document.getElementById('two-container');
var two = new Two({
width: 300,
height: 300
}).appendTo(container);
// create some shapes with two's built-in methods
var circle = two.makeCircle(100,150,50);
var square = two.makeRectangle(200,150,50,50);
// you can then style your shapes in many ways
// two also accepts all valid css color attributes
circle.fill = '#abcdef';
circle.noStroke();
circle.opacity = 0.5;
square.noFill();
square.linewidth = 5;
square.stroke = 'orangered';
// then you need to tell two to render everything
two.update();
See this jsfiddle for live code.
Animate
To animate is not hard either. Two.js provides an animation loop. You will need to bind
the function called each frame to the two.update()
function every time it is called during the animation. It is fairly straightforward. Using the same code from above, we can add animation to it.
// you don't need to call update here because the animation loop will call it automatically
// two.update();
// and we add the following code
// bind a function to 'update'
two.bind('update',function(){
// this function is called every time two.update() executes
if (circle.translation.x >= 400){
circle.translation.x = -100;
}
circle.translation.x += 2;
square.rotation += 0.1;
}).play(); // don't forget to play the animation
See it live here.
We made the circle
to move horizontally in a repeated manner by changing circle.translation.x
. And we made the square
spin by changing square.rotation
. You can also animate shape.opacity
, shape.scale
, and even shape.fill
or shape.stroke
if you integrate other libraries to interpolate color values. I suggest using TinyColor for color interpolation.
Atomic
What I mean by atomic is that shapes in Two.js are manipulable to every single vertices
. Vertices
are essentially the atoms that make up the shapes. What this means is that it opens up doorways to a great many interesting animations that are not doable otherwise. Below, we add some animation to vertices on top of the code above.
// we need to prepare for vertices animation
// by storing original positions as their native property
square.vertices.forEach(function(vertice){
vertice.ox = vertice.x; // ox = original x
vertice.oy = vertice.y;
});
// bind a function to 'update'
two.bind('update',function(){
// this function is called every time two.update() executes
if (circle.translation.x >= 400){
circle.translation.x = -100;
}
circle.translation.x += 2;
//square.rotation += 0.1;
square.vertices.forEach(function(vertice){
// every vertice will animate from their original position
// to a random direction with a random distance
vertice.x = vertice.ox + (Math.random()-0.5)*4;
vertice.y = vertice.oy + (Math.random()-0.5)*4;
});
}).play(); // don't forget to play the animation
See it live here.
There are so many other things you can do with vertices
. Your imagination is the limit.
Renderer agnostic
Two.js also has a magical function which interpret svg
nodes and turn them into shapes in two
. The other good news is, even though these are svg
nodes, two.js can still renders these shapes in svg
, canvas
, or webgl
.
To do this, we use the two.interpret
function.
// get a container element to put your instance of two in it
var container = document.getElementById('two-container');
var two = new Two({
width: 300,
height: 300,
type: Two.Types.canvas // render in canvas
}).appendTo(container);
var svg = document.getElementById('svggg');
// interpret svg node
// it returns a Two.Group, a group of Two.Paths
// that make up the shape we see
var graphic = two.interpret(svg);
// anchors all vertices to the center position of the group
graphic.center();
// set attributes
graphic.translation.set(two.width/2,two.height/2);
graphic.scale = 0;
// bind a function to 'update'
two.bind('update',function(){
// this function is called every time two.update() executes
if (graphic.scale >= 0.5){
graphic.scale = 0;
}
graphic.scale += 0.001;
}).play(); // don't forget to play the animation
See it live here.
The only limitation right now is that this function is a little buggy. Sometimes vertices manipulation doesn't work, and sometimes the interpreted shape looks atrocious. But it is still a welcoming function that has a great potential. Considering two.js is in alpha right now, we can expect improvements on this function in the future.
Summing up
Two.js is a very interesting library to do animation with. It has a straightforward api, it is atomic, and it is renderer agnostic. It is also easily extensible. I have used this library with Tween.js, Howler.js and other libraries to create time-based motion graphics, and made this video entirely with web technologies. If you want to hear more about this, please comment below.
Please up and sub. Hope you enjoyed this article.
Side note
Here is the video I made with JavaScript.