⬆️ ⬇️

GraphicsJS - Graphic JavaScript Library





Translation of the article. The English original is published on SitePoint - " Introducing GraphicsJS, a Powerful Lightweight Graphics Library ".



HTML5 is the cornerstone of the modern web. And today, when the challenge is to create interactive graphics, the choice most often falls on technologies such as SVG and Canvas. Flash is forgotten, Silverlight is a rare bird living on the outskirts of the web, and almost no one remembers third-party ActiveX and Java plug-ins.

')

The pros and cons of SVG and Canvas are well known - in general, it all comes down to the fact that SVG is more suitable for creating interactive elements and working with them. This is a vector format based on XML, and when an image is loaded onto a page using the <svg> , each of its internal elements are made available in the SVG DOM.



In this article I want to talk about GraphicsJS . This is a powerful, open-source, graphical JavaScript library based on SVG technology ( VML for older versions of IE). I’ll start with a brief introduction to the basics of GraphicsJS, and then illustrate the library’s possibilities with two small but illustrative examples. The first one is dedicated to the visual arts. The second will show how to make a simple art game in the timekiller genre in less than 50 lines of code.



Why GraphicsJS



There are quite a few libraries that make it easier to work with SVG: Raphaël , Snap.svg, and BonsaiJS are among the best. Each has strengths and weaknesses, but their detailed comparison will be the subject of one of the following publications. This article is solely about GraphicsJS, and now I will try to explain how this library is good and stands out among others.



Firstly, GraphicsJS weighs quite a bit and has a very flexible JavaScript API. It provides rich possibilities for text formatting, as well as a virtual DOM - independent of the specifics of the HTML DOM in different browsers.



Secondly, the code of this library was only opened last fall . AnyChart , one of the leaders in developing solutions for interactive data visualization, has used GraphicsJS as a graphics engine in its commercial products for about three years (since the release of AnyChart 7.0), so this library has been tested in combat conditions. (Disclaimer: I'm AnyChart's R & D executive and lead graphicsjs developer.)



Third, unlike other AnyChart products — graphing JavaScript libraries — GraphicsJS is free for both commercial and non-commercial use. The library is available on GitHub under the Apache license.



Fourth, GraphicsJS has cross-browser compatibility, including support for Internet Explorer 6.0+, Safari 3.0+, Firefox 3.0+, Opera 9.5+. In older versions of IE, the library uses VML, in all other browsers, SVG.



Finally, GraphicsJS allows you to effectively combine graphics and animation. Look at the library’s main gallery : there are such examples as a blazing bonfire , a rotating galaxy , rain , procedurally generated leaves , a “Fifteen” puzzle, and so on. In the detailed documentation and detailed description of the API you can find even more examples of using GraphicsJS.



GraphicsJS Basics



To start working with GraphicsJS, you need to connect the library itself and create a block HTML element for the future drawing:



 <html lang="en"> <head> <meta charset="utf-8" /> <title>GraphicsJS Basic Example</title> </head> <body> <div id="stage-container" style="width: 400px; height: 375px;"></div> <script src="https://cdn.anychart.com/js/latest/graphics.min.js"></script> <script> //   GraphicsJS </script> </body> </html> 


Then you need to build a workspace and draw something in it, for example, a rectangle , a circle or some other shape :



 //    var stage = acgraph.create('stage-container'); //   var stage.rect(25, 50, 350, 300); 


Here is an example on CodePen , in which we go a little further and draw the Deathly Hallows mark.



Our first masterpiece



Contour, fill color and pattern



You can color any shape or line using the fill and outline settings . Everything has a contour (border), but the fill is available only for figures and closed lines.



GraphicsJS offers numerous settings for these parameters, up to a linear and radial gradient, both in the fill and in the contour. Lines can be dashed, and also supports fill image with multiple modes of paving. However, such a set of functions can be found in almost any library. What distinguishes GraphicsJS is the option to fill it with hatching and a pattern that allows you not only to choose from thirty-two (!) Ready fill options , but also to easily create your own patterns from shapes or text.



And now let's see what can be done specifically. I will draw a small picture (a little man standing near the house) and then modify it with the help of color and patterns. Let, for simplicity, this will be an image in the style of naive art (I will try not to reach ar Brut ). Go:



 //    var stage = acgraph.create('stage-container'); //   var frame = stage.rect(25, 50, 350, 300); //   var walls = stage.rect(50, 250, 200, 100); var roof = stage.path() .moveTo(50, 250) .lineTo(150, 180) .lineTo(250, 250) .close(); //   var head = stage.circle(330, 280, 10); var neck = stage.path().moveTo(330, 290).lineTo(330, 300); var kilt = stage.triangleUp(330, 320, 20); var rightLeg = stage.path().moveTo(320, 330).lineTo(320, 340); var leftLeg = stage.path().moveTo(340, 330).lineTo(340, 340); 


The result can be viewed at CodePen .



As you can see, here we use variables: all methods that paint something in the workspace return a reference to the created object, which can be used to change or delete it.



In addition, in ChainJS you can actively use chain calls (for example, stage.path().moveTo(320, 330).lineTo(320, 340); ), which allows you to reduce the code. You need to use this feature carefully, but with the right approach, a chain call really makes the code more compact and easy to read.



Now you can give the picture we got to some child and ask them to color it - even a child can master the following technique:



 //   //   frame.stroke(["red", "green", "blue"], 2, "2 2 2"); //   walls.fill(acgraph.hatchFill('horizontalbrick')); //   roof.fill("#e4d96f"); //   kilt.fill(acgraph.hatchFill('plaid')); 


Now our example looks like this .



Now the picture shows a highlander in a kilt. He stands beside his thatched-roof brick castle. You can even take a chance and really call our picture a work of art , the copyright to which we want to protect. Well, let's do it with the help of the original text pattern fill, which we ourselves will configure:



 // 169 -     var text = acgraph.text().text(String.fromCharCode(169)).opacity(0.2); var pattern_font = stage.pattern(text.getBounds()); pattern_font.addChild(text); //     frame.fill(pattern_font); 


As you can see, it is very simple: you need to create an instance of a text object , then build a pattern in the workspace, and finally insert text into the pattern.





We draw an art game (timekiller) in less than 50 lines of code



In the next part of the article, I'll show you how to use GraphicsJS to draw a cookie clicker like a clicker in less than 50 lines of code.



The name of this game is "Janitor in the Wind." In it, the user acts as a janitor who sweeps the street on a windy autumn day. Here we partially use the example code with procedurally generated leaves from the GraphicsJS gallery.



The final version of the game can be viewed at CodePen (or at the end of this article).



Layers, zIndex, virtual DOM



Start by creating a workspace (as in the previous example). And then we declare several source variables:



 //    var stage = acgraph.create("stage-container"); //     var palette_fill = ['#5f8c3f', '#cb9226', '#515523', '#f2ad33', '#8b0f01']; var palette_stroke = ['#43622c', '#8e661b', '#393b19', '#a97924', '#610b01']; //  var leavesCounter = 0; 


To create a game, we can use the ability to work with a layer - an object responsible for grouping elements in GraphicsJS. Elements must be grouped so that it is convenient to apply the same changes to them, for example transformations. Layers can be modified in pause mode (I’ll talk about it a little lower): this improves performance and usage impressions.



In this example, the functionality of the layer helps to group the leaves and not let them close the inscription, telling how many leaves we swept out. To do this, first create a caption, and then use the stage.layer method stage.layer create a layer for the entire stage.layer and assign the latter a lower zIndex than the caption.



 //      var counterLabel = stage.text(10,10, "Swiped: 0", {fontSize: 20}); //    var gameLayer = stage.layer().zIndex(counterLabel.zIndex()-1); 


Now, no matter how much we create leaves in this layer, they will never be on top of the text.



Transformations



Next, we add a function for drawing leaves, using a convenient transformation API that allows you to move, scale, rotate and crop both elements and groups of elements. Coupled with other features of GraphicsJS - layers and virtual DOM - this is a very powerful tool.



 function drawLeaf(x, y) { //      var index = Math.floor(Math.random() * 5); var fill = palette_fill[index]; var stroke = palette_stroke[index]; //        var scale = Math.round(Math.random() * 30) / 10 + 1; var angle = Math.round(Math.random() * 360 * 100) / 100; //    () var path = acgraph.path(); //      path.fill(fill).stroke(stroke, 1, 'none', 'round', 'round'); var size = 18; path.moveTo(x, y) .curveTo(x + size / 2, y - size / 2, x + 3 * size / 4, y + size / 4, x + size, y) .curveTo(x + 3 * size / 4, y + size / 3, x + size / 3, y + size / 3, x, y); //    path.scale(scale, scale, x, y).rotate(angle, x, y); return path; }; 


As you can see, each line is created in the same way, but then transformed. The result is a very nice random pattern of leaves.



Work with events



All objects, workspaces, and layers in GraphicsJS can handle events . A list of all available events is in the EventType API . The workspaces support four special events for rendering control.



In the game example, we use event listeners tied to each object (sheet) to make the leaves disappear one by one when you hover over them. To achieve this, add the following code at the end of the drawLeaf function, before the return :



 path.listen("mouseover", function(){ path.remove(); counterLabel.text("Swiped: " + leavesCounter++); if (gameLayer.numChildren() < 200) shakeTree(300); }); 


From this it is also clear that a layer is used to count the leaves.



 if (gameLayer.numChildren() < 200) shakeTree(300); 


Notice, in fact, we do not store the number of leaves here. Leaves are lines that are added to a particular layer or are removed from there, and therefore you can track how many children we have (and therefore how many leaves remain).



The GraphicsJS library allows you to use a virtual DOM , an HTML DOM abstraction that is light and independent of the specifics of using SVG / VML in different browsers. This technology is useful for implementing a number of useful functions, such as controlling all objects and layers, applying transformations to groups, and optimizing rendering using methods that allow you to monitor and control its entire process.



Performance optimization



Thanks to the virtual DOM, as well as event handlers, GraphicsJS users can control the rendering. How these things are connected, you can read in the article " Performance " from the library documentation.



At the time when the leaves are generated in our game, the rendering needs to be suspended and then resumed as soon as all changes are made:



 function shakeTree(n){ stage.suspend(); //   for (var i = 0; i < n; i++) { var x = Math.random() * stage.width()/2 + 50; var y = Math.random() * stage.height()/2 + 50; gameLayer.addChild(drawLeaf(x, y)); //   } stage.resume(); //   } 


With this method of adding elements, new leaves appear almost instantly.



 //      shakeTree(500); 


Finally, drop all the leaves by calling the shakeTree() method.



Final result





Conclusion



Switching to HTML5 changed the web. When it comes to modern web applications or even a simple site, we often encounter tasks that require manipulation of graphics. Although it is impossible to find a solution that works perfectly in absolutely any situation, I would suggest that you pay attention to the GraphicsJS library. It has an open source and open-source license, it is very functional and productive, and also has excellent browser support and many features. All this makes GraphicsJS an interesting, convenient and, of course, effective solution.



I would be happy to get feedback on GraphicsJS in the comments. Already using this library? Are you ready to consider the possibility of its use in a new project? It would be interesting to know why, as well as why not. By the way, I am currently working on creating a list of the best graphic JavaScript libraries and articles where they will be compared - so I suggest writing in the comments which libraries you would like to see there.



Links









The author of the original article on SitePoint : Roman Lyubushkin (Roman Lubushkin).

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



All Articles