Introducing GraphicsJS, a Powerful Lightweight Graphics Library

Share this article

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

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.

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

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 colored copyrighted house / graphicsjs 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 street sweeper in the wind / graphicsjs by SitePoint (@SitePoint) on CodePen.

Сonclusion

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 GrphicsJS 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.

Links for Further Reading

Frequently Asked Questions about GraphicsJS

What makes GraphicsJS different from other JavaScript graphics libraries?

GraphicsJS stands out from other JavaScript graphics libraries due to its powerful and lightweight nature. It is a robust library that allows developers to draw and animate any graphics with high precision and performance. Unlike other libraries, GraphicsJS provides a comprehensive set of features, including layers, gradients, patterns, and more, without compromising on speed or efficiency. It also supports all modern browsers, making it a versatile choice for developers.

How can I start using GraphicsJS?

To start using GraphicsJS, you need to include the GraphicsJS library in your HTML file. You can download the library from the official website or use a CDN. Once the library is included, you can start creating graphics by calling the appropriate functions and methods provided by the library.

Can I use GraphicsJS for complex animations?

Yes, GraphicsJS is designed to handle complex animations with ease. It provides a rich set of animation features, including easing functions, delays, and duration settings. You can animate any attribute of a graphic, such as its position, size, color, and more. This makes GraphicsJS a powerful tool for creating interactive and dynamic graphics.

Is GraphicsJS compatible with all browsers?

GraphicsJS is designed to be compatible with all modern browsers, including Chrome, Firefox, Safari, and Internet Explorer. It uses SVG and VML for rendering, which are supported by all these browsers. This ensures that your graphics will look consistent and perform well across different platforms and devices.

How can I create a gradient with GraphicsJS?

Creating a gradient with GraphicsJS is straightforward. You can use the gradient method to define a linear or radial gradient, specify the colors and positions, and then apply the gradient to any graphic. This allows you to create rich and vibrant graphics with ease.

Can I use GraphicsJS to create interactive graphics?

Yes, GraphicsJS provides a set of event handling features that allow you to create interactive graphics. You can attach event listeners to any graphic, enabling you to respond to user actions such as clicks, mouse movements, and more. This makes GraphicsJS a great choice for creating interactive web applications.

Does GraphicsJS support layers?

Yes, GraphicsJS supports layers, allowing you to organize your graphics into separate groups. Each layer can be manipulated independently, making it easier to manage complex graphics. You can also control the visibility and z-order of each layer, providing you with fine-grained control over your graphics.

How can I optimize my graphics with GraphicsJS?

GraphicsJS provides several features that can help you optimize your graphics. For example, you can use the clip method to hide parts of a graphic that are outside a specified area, reducing the amount of rendering required. You can also use the cache method to store the rendered output of a graphic, improving performance for graphics that are redrawn frequently.

Can I use GraphicsJS to create charts and graphs?

While GraphicsJS is not specifically designed for creating charts and graphs, its powerful drawing and animation features make it possible to create any kind of graphic, including charts and graphs. You can use the library’s methods to draw lines, curves, rectangles, circles, and more, allowing you to create a wide range of chart types.

Is GraphicsJS free to use?

Yes, GraphicsJS is a free and open-source library. You can use it in your projects without any cost. The library is also actively maintained, ensuring that it stays up-to-date with the latest web standards and technologies.

Roman LubushkinRoman Lubushkin
View Author

Roman is an experienced web developer and currently the Head of R&D at AnyChart, one of the globally leading providers of interactive data visualization solutions. He enjoys exploring new technologies and orchestrates all the investigative activities in the company as well as the entire development of its JavaScript (HTML5) charting libraries and related components.

graphicsjsjameshSVGsyndicated
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week