📜 ⬆️ ⬇️

Graphics2D.js - objects, interactivity, animation on canvas ... And nothing more

Good new Date (). GetTimeOfDay ();




HTML5 Canvas is indispensable when you need to draw something dynamically. But if we want to change something dynamically, we have to store the state of the elements and redraw if necessary.
If we want to react to events - we will have to catch the coordinates of the mouse and determine whether they are inside the desired shape.
Etc.

Frequent repetitive tasks. And so there are frameworks and libraries.
')
However, the case with Graphics2D.js is a bit different: I just wanted to draw. With object model, animation and events. And - nothing more.
But the most expandable: a lot of ideas, and everything can be taken out in plugins.

keyten.imtqy.com/Graphics2D


(Russian version of the site will be today or tomorrow)
So…

Getting started


Context:
var ctx = Graphics2D.id('mycanvas'); //   : var ctx = Graphics2D.query('canvas', 1); //  <canvas> //  var ctx = Graphics2D.query( document.getElementById('mycanvas') ); 


Let's draw ... well, for example, a small circle that will be animated when you hover the mouse:
 ctx.circle({ cx : 300, cy : 300, radius : 50, fill : '#f0a' }).mouseover(function(){ this.animate({ scale : 2, opacity : 0.5, }, 300); }).mouseout(function(){ this.animate({ scale : 0.5, opacity : 1 }, 300); }); 

jsfiddle.net/wzemyho6

And now ... let them be 100:
 for(var i = 0; i < 100; i++){ ctx.circle({ cx : Math.floor(Math.random() * 700), cy : Math.floor(Math.random() * 400), radius : 10, fill : 'rgb(' + [Math.floor(Math.random() * 255), Math.floor(Math.random() * 255), Math.floor(Math.random() * 255)].join(',') + ')' }).mouseover(function(){ this.animate({ radius : 20, opacity : 0.5, }, 300); }).mouseout(function(){ this.animate({ radius : 10, opacity : 1 }, 300); }); } 

jsfiddle.net/9v63govv/4
What is surprising is a good performance: the animation begins to significantly slow down at 2-3 thousand.
UPD. With the introduction of requestAnimationFrame (thank you very much Gerh ), the situation has greatly improved

Objects


Built-in drawable objects 6: rect, circle, path, image, text and textblock.
All shapes are inherited from the inner class Shape, which contains most of the methods that modify the object (transformations, animation, events, fill, stroke, transparency ...).
The difference between text and textblock: the second is able to transfer lines (automatically and manually through \ n), the coordinates of the block are specified as coordinates, not inscriptions.
In the path object, the curves are quadratic and cubic Beziers, elliptic ... everything that the canvas allows. And in addition, everything is expandable: for example, one of the plugins adds drawing Catmull-Rom.

We can create any object by specifying the parameters in order or in the object (the latter allows additional parameters:

 ctx.circle(150, 150, 70, 'red', '2px black'); // fill, stroke ctx.circle({ cx : 150, cy : 150, radius : 70, fill : 'red', stroke : '5px dot red 0.5 round', opacity : 0.5 //     }); 

In any object we can specify the fill and stroke at the same time, and the latter allows several parameters at once.

But the gradient:

 var rect = ctx.rect(100, 100, 200, 200, { colors : ['red', 'green', 'blue'], from : 'top', to : 'bottom' }); 

You can also create a gradient with a separate ctx.gradient object and fill it with several shapes at once. And then any change in the gradient will be reflected in all the shapes.
And the inline gradient is also an instance of the gradient class, for example, we change one of the colors:

 rect.fill().color(0, 'yellow'); 


Paths are drawn in one of three options:
 ctx.path("M10,10 L200,200 Z", null, "2px blue"); ctx.path([ [10,10], [200,200], [400,100,450,150] ]); ctx.path([ { name : 'moveTo', arguments:[10,10] }, { name : 'lineTo', arguments:[200,200] }, { name : 'closePath' } ]); 


Objects without fill and stroke are not drawn, but can react to events (this should be enabled by the function path.events(true) ... so it will be in a couple of days).

The string format is not SVG , although it supports its full syntax (omitting spaces before minuses, omitting repeated functions, etc.). Supports only the functions M, L, C, Q and Z (absolute coordinates only) - moveTo, lineTo, bezier, quadratic and closePath.

The other day there will be a plugin that adds full support for SVG paths :)

You can handle individual waypoints:
 path.point(0).name; // -> moveTo path.point(0).set('x', 20); path.before(1, 'L20,20 L30,50'); 


Native context


We can create a function that draws on a native context (for example, to optimize some kind of slow functionality) and add it to the redraw:

 ctx.push({ draw : function(ctx){ ctx.fillRect(200, 200, 10, 10); } }); 


With a strong desire, you can also add event handling (just add the isPointIn function) ... Or even inherit from Graphics2D.Shape (getting a bunch of functions to change styles and transform) ...
However, this is a separate topic, which I will tell you about, if desired.

In addition, most shapes and their methods are able to take CSS values, for example:
ctx.rect("10pt", "10pt", "2em", "2em", "blue")

This is a functionality in the sense of which I am still not sure (it will be interesting to see your comments on this topic).

Plugins


As I mentioned, Graphics2D is quite extensible, here are some already existing plugins:
- Sprite - just sprites and sprite animation.
- ImageAnim - animation, when different frames in different files.
- CatmullRom - drawing Catmull-Rom curves (within the Path object).
Others are planned (advanced event handling, support for SVG paths ...) - as I said, there are a lot of ideas, and everything will go into plugins.

keyten.imtqy.com/Graphics2D


(Russian version of the site will be today or tomorrow)
Github: github.com/keyten/Graphics2D .
License: MIT / LGPL.

Some demos: Bezier , Gradients , Transformations , Textblock .

That's all, interesting to hear your feedback.

And also: Many thanks to TheShock for a lot of help.

Source: https://habr.com/ru/post/239261/


All Articles