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

    Good new Date (). GetTimeOfDay ();




    HTML5 Canvas is indispensable when you need to dynamically draw something. But if we want to change something dynamically, we will have to store the state of the elements and redraw if necessary.
    If we want to respond 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. This is how frameworks and libraries appear.

    However, the case with Graphics2D.js is slightly different: I just wanted to draw. With an object model, animation, and events. And - nothing more.
    But as extensible as possible: there are a lot of ideas, and everything can be put into plugins.

    keyten.github.io/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); // второй 
    // или
    var ctx = Graphics2D.query( document.getElementById('mycanvas') );
    


    Let's draw ... well, for example, a small circle that will be animated on hover:
    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 there be 100 of them:
    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 its good performance: the animation starts to slow down noticeably, it starts at 2-3 thousand.
    UPD With the introduction of requestAnimationFrame (thank you very much Gerh ) the situation has greatly improved

    The objects


    There are 6 built-in drawn objects: rect, circle, path, image, text and textblock.
    All shapes are inherited from the inner Shape class, which contains most of the methods that modify the object (transformations, animation, events, fill, stroke, transparency ...).
    The difference between text and textblock: the second can wrap lines (automatically and manually through \ n), the coordinates are the coordinates of the block, not the inscription.
    In the path object, there are curves — quadratic and cubic beziers, elliptical ... anything canvas allows. And in addition, everything is extensible: for example, one of the plugins adds Catmull-Rom drawing.

    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.

    And here is 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.
    Yes, and the inline gradient is also an instance of the gradient class, for example, 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 a fill and stroke are not drawn, but can respond to events (this must be enabled by the function path.events(true)... it will be so in a couple of days).

    The string format is not SVG , although it supports its full syntax (skipping spaces before minuses, skipping repeating functions, etc.). It supports only the functions M, L, C, Q and Z (only absolute coordinates) - 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 path points:
    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);
    	}
    });
    


    If you wish, you can also add event processing (just add the isPointIn function) ... Or even inherit from Graphics2D.Shape (getting a bunch of functions for changing styles and transformations) ...
    However, this is a separate topic, which I will tell you about, if desired, by the habrachitateli.

    In addition, most figures and their methods can accept CSS values, for example:
    ctx.rect("10pt", "10pt", "2em", "2em", "blue")

    This is 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 already mentioned, Graphics2D is quite extensible, here are some existing plugins:
    - Sprite - simple 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 processing, support for SVG paths ...) - as I said, there are a lot of ideas, and everything will go to plugins.

    keyten.github.io/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, it's interesting to hear your feedback.

    And one more thing : many thanks to TheShock for a lot of help.

    Also popular now: