Chat with us, powered by LiveChat

JavaScript Drawing Library GraphicsJS 1.2.0 Released + Introduction from SitePoint

May 3rd, 2017 by AnyChart Team

GraphicsJS, our powerful JavaScript drawing library that we open-sourced last year, has recently got an update to version 1.2.0. It is the next best news of 2017, a great addition to winning a Devies Award with GraphicsJS for the category “JavaScript Technologies” and to the 7.13.0/7.13.1 releases of our JS/HTML5 charting solutions AnyChart, AnyStock, AnyMap, and AnyGantt.

So, we invite you to take a very quick look at the most important updates (we’ll highlight the two below). And then – in case you want to feel the real power of JavaScript drawing and have not used GraphicsJS in your business or fun web projects yet – we are sharing a nice article published on SitePoint just recently. It is an introduction to GraphicsJS based on two tutorials. They will guide you through the most valuable features of this JavaScript drawing library and demonstrate them in action, and you’ll learn how to easily create a naïve art picture and a time-killer game.

GraphicsJS, a lightweight and powerful SVG-based JavaScript drawing library by AnyChart

JavaScript Drawing with GraphicsJS: Main Improvements

  • Closure library and Closure compiler were updated to version 20161024.
  • Enjoy an improved JavaScript drawing performance! In particular, we optimized the process of obtaining a link to a container for the stage. Also, resize events are now handled with the help of the Timer object, not the iFrame element.

Now, you are welcome to read the SitePoint article about GraphicsJS. Please do not forget to ask your questions, if any. You may do that by leaving a comment here right below the article.

Introducing GraphicsJS, a Powerful Lightweight Graphics Library

This article was originally published on SitePoint.

HTML5 is the backbone of the modern web. And nowadays, when it comes to creating interactive images, SVG and Canvas are often the technologies of choice — Flash has been forgotten, Silverlight is a rare unicorn that dwells on the outskirts of the Web, and there are few who remember 3rd party plugins.

The pros and cons of each are well documented, but in a nutshell, SVG is better for suited to creating and handling interactive elements. This is because SVG is an XML-based vector format, and when an image is loaded into a page using an <svg> tag, every element within it becomes available in the SVG DOM.

In this article, I want to introduce you to GraphicsJS, a new and powerful open-source JavaScript drawing library, which is based on SVG (with VML fallback for old IE versions). I’ll start with a quick introduction to its basics, and then showcase the functionality of the library with the help of two short, yet spectacular samples: the first one is all about art, whereas the second one illustrates how to code a simple time-killer art game in less than 50 lines.

Why GraphicsJS

There are a lot of libraries out there that can help developers work with SVG: Raphaël, Snap.svg, and BonsaiJS to name a few of the best. Each of these has its own strengths and weaknesses, but their thorough comparison will be the subject of another article. This article is all about GraphicsJS, so let me explain what makes it good and special.

First of all, GraphicsJS is lightweight and has a very flexible JavaScript API. It implements many rich text features, as well as a virtual DOM — detached from the browser-specific implementation of the HTML DOM.

Secondly, it is a new open-source JavaScript library that was published as recently as last fall by AnyChart, one of leading global software developers in the field of interactive data visualization. AnyChart has been using GraphicsJS to render charts in its proprietary products for at least three years (since the release of the AnyChart 7.0) so GraphicsJS has been fully battle-tested. (Disclaimer, I am the head of R&D at AnyChart and the lead developer of GraphicsJS)

Thirdly, unlike AnyChart’s JavaScript charting libraries, GraphicsJS can be used for free in both commercial and non-profit projects. It is available on GitHub under the Apache license.

Fourthly, GraphicsJS is cross-browser compatible, supporting Internet Explorer 6.0+, Safari 3.0+, Firefox 3.0+, and Opera 9.5+. It renders in VML in older IE versions and SVG in all the other browsers.

Finally, GraphicsJS allows you to combine graphics and animation to great effect. Check out its main gallery which features an animated bonfire, rotating galaxy, falling rain, procedure generated leaves, playable 15-puzzle, and much more. GraphicsJS contains many further examples in its extensive documentation and its comprehensive API Reference.

GraphicsJS Basics

To start with GraphicsJS, you need to reference the library and create a block-level HTML element for your 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 code here
    </script>
  </body>
</html>

Then you should create a stage and draw something in it, such as a rectangle, a circle, or other shape:

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

Here is the example on CodePen in which we go a little bit further and draw the Deathly Hallows symbol.

Our First Masterpiece

Fill, Stroke and Pattern Fill

Any shape or a path can be colored using fill settings and stroke settings. Everything has a stroke (border), but only shapes and closed paths have a fill. Fill and stroke settings are very rich, you can go as far as a linear or circular gradient for both fill and stroke. Also, lines can be dashed, and image fill with several tiling modes is supported. But all this is a pretty standard stuff you can find in almost any library. What makes GraphicsJS special is its hatch and pattern fill feature that allows you not only to use one of the 32(!) available hatch fill patterns out of the box, but also to easily create your own patterns made of shapes or text.

Now, let’s see what exactly is possible! I will draw a small picture of a man standing near a house and then enhance it with different pattern and colour fills. For the sake simplicity, let’s make it a naïve art picture (and try not to get into art brut). Here it goes:

// create a stage
var stage = acgraph.create('stage-container');

// draw the frame
var frame = stage.rect(25, 50, 350, 300);

// draw the house
var walls = stage.rect(50, 250, 200, 100);
var roof  = stage.path()
  .moveTo(50, 250)
  .lineTo(150, 180)
  .lineTo(250, 250)
  .close();

// draw a man
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);

Check out the result on CodePen.

As you can see we are using variables now — all methods that draw something on the stage return a reference to the object created, and this link can be used to alter or remove the object.

Also note how chaining, which is everywhere in GraphicsJS, helps shorten the code. Chaining (e.g. stage.path().moveTo(320, 330).lineTo(320, 340);) should be used carefully, but it does make the code compact and easier to read if properly applied.

Now, let’s give this coloring page to a child and let them color it. Because even a child can master the following technique:

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

Here’s what our example looks like now.

Now we have a picture of a highlander in a kilt, who is standing near his brick castle with a straw roof. We can even go out on a limb and say it is indeed a piece of art which we want to copyright. Let’s do that with the custom text-based pattern fill:

// 169 is a char code of the copyright symbol
var  text = acgraph.text().text(String.fromCharCode(169)).opacity(0.2);
var  pattern_font = stage.pattern(text.getBounds());
pattern_font.addChild(text);
// fill the whole image with the pattern
frame.fill(pattern_font);

As you can see, this is very easy to do: you create an instance of a text object, then form a pattern in a stage, and put a text into the pattern.

See the Pen GraphicsJS – colored copyrighted house by SitePoint (@SitePoint) on CodePen.

Create a Time-Killer Art Game in Less Than 50 Lines of Code

In the next part of this article, I want to show you how to create a Cookie Clicker type game with GraphicsJS in less than 50 lines of code.

The name of the game is “Street Sweeper in the Wind”, and the player takes the role of a street sweeper cleaning a street during a windy fall afternoon. The game uses some code from the procedure generated leaves sample in the GraphicsJS gallery.

You can check out the finished game on CodePen (or at the end of the article).

Layers, zIndex and the Virtual DOM

We start off by creating a stage (as before), then declaring some initial variables:

// create stage
var stage = acgraph.create("stage-container");

// color palettes for leaves
var palette_fill = ['#5f8c3f', '#cb9226', '#515523', '#f2ad33', '#8b0f01']; 
var palette_stroke = ['#43622c', '#8e661b', '#393b19', '#a97924', '#610b01'];

// counter
var leavesCounter = 0;

For this game we’re going to be working with Layer — an object intended for grouping elements in GraphicsJS. Elements must be grouped if you want to apply similar changes to them, such as transformations. You can change layers when in suspended mode (more about this later), which improves performance and the user experience.

In this demo, we are using the layer functionality to help us group leaves together and avoid them covering the label (which tells us how many were swiped). To do this, we create a label and then call the stage.layer method, which create stage bound layer. We assign this layer a lower zIndex property than that of the label.

// create a label to count leaves
var counterLabel = stage.text(10,10, "Swiped: 0", {fontSize: 20});

// a layer for the leaves
var gameLayer = stage.layer().zIndex(counterLabel.zIndex()-1);

After doing that, no matter how many leaves we create in the layer, we can be sure they won’t cover the text.

Transformations

Next, let’s add a function to draw our leaves. This will make use of the convenient GraphicsJS transformations API that allows you to move, scale, rotate and shear both elements and groups of elements. When used in conjunction with layers and a virtual DOM, this is a very powerful tool.

function drawLeaf(x, y) {
  // choose a random color from a palette
  var index = Math.floor(Math.random() * 5);
  var fill = palette_fill[index];
  var stroke = palette_stroke[index];

  // generate random scaling factor and rotation angle
  var scale = Math.round(Math.random() * 30) / 10 + 1;
  var angle = Math.round(Math.random() * 360 * 100) / 100;

  // create a new path (leaf)
  var path = acgraph.path();

  // color and draw a leaf
  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);

  // apply random transformations
  path.scale(scale, scale, x, y).rotate(angle, x, y);

  return path; 
};

You see that every path is created in the same way, but then gets transformed. This results in a very nice random leaves pattern.

Handling Events

Any object, stage and layer in GraphicsJS can handle events. The full list of supported events is available in the EventType API. Stages have four special events to control rendering.

In this game example, we are using event listeners attached to the leaf objects so they disappear one by one when a user mouses over them. To do this, add the following code to the bottom of the drawLeaves function, before the return statement:

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

Here we can also see that we are using the layer to count leaves.

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

Note that we are not actually storing the number of leaves here. As leaves are paths we add to and remove from a specific layer, this enables us to track how many children we have (and thus how many leaves remain).

GraphicsJS provides a virtual DOM, an abstraction of the HTML DOM, lightweight and detached from the browser-specific SVG/VML implementation. It is useful for doing a lot of great things such as keeping track of all objects and layers, applying transformations to groups, and optimizing rendering with the help of methods that allow us to track and control the rendering process.

Performance Optimization

The virtual DOM, along with event handlers, allows GraphicsJS users to control rendering. The Performance article can give you an idea of the ways these things are related.

When generating leaves in our game, we need to suspend rendering while adding new leaves and resume it only when all changes are done:

function shakeTree(n){
  stage.suspend(); // suspend rendering
  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)); // add a leaf
  }

  stage.resume(); // resume rendering
}

This way of handling new elements makes new leaves appear almost instantly.

Finally, kick everything off with a call to shakeTree().

// shake a tree for the first time
shakeTree(500);

The End Result

See the Pen GraphicsJS – street sweeper in the wind game by SitePoint (@SitePoint) on CodePen.

Conclusion

The shift to HTML5 has changed the Web. When it comes to modern web applications or even a simple site, we often encounter tasks that require image manipulation. While it is impossible to find a solution that works well in every situation, you should consider the GraphicsJS library. It is open-source, robust, has great browser support and lots of features that make it interesting, handy, and of course helpful.

I would be happy to hear your feedback regarding GraphicsJS in the comments below. Are you using it already? Would you consider using it for a new project? I’d love to hear why, or indeed why not. I am also currently working on a list of major JavaScript drawing libraries and an article that will compare and contrast them all. Also feel free to point me to any libraries you would like to see featured there.


Comments (2)

*

Manfred    18th Aug 17 7:03 pm

Well – all this is great! It inspired me to make an experiment: In the tree-example I copied the div and the script and found a new name for the second div (second stage). So I got two trees which seemed to be independent listeners, but the counter stayed 0 all the time for both. So I have a question: How can we get independent namespaces for independent stages in one document? And if we can detach one from the other, how can we install some kind of restricted interoperability (globally)? After all, I’m speaking of a modular approach inside a document.

  1. Reply
  2. Link
Timothy Loginov    7th Oct 17 12:08 pm

Manfred, we are really sorry we missed your comment. Can you, please, send us a link to your demo so we could clearly see what happens?

  1. Reply
  2. Link