About
RGraph is a JavaScript charts library based on HTML5 SVG and canvas. RGraph is mature (over 15 years old) and has a wealth of features making it an ideal choice to show charts on your website.

More »

 

License
RGraph can be used for free under the GPL or if that doesn't suit your situation there's an inexpensive (£99) commercial license available.

More »

 

Download
Get the latest version of RGraph (version 6.17) from the download page. There's also older versions available, minified files and links to cdnjs.com hosted libraries.

More »

SVG paths for canvas

Written by Richard Heyes, RGraph author, on 3rd September 2015

Introduction to the path function

canvas paths are verbose. Unnecessarily so in my opinion. The addition of svg paths to the forthcoming Path2D object goes a long way to resolving this and providing a better solution for creating and working with canvas paths.

But I'm rather impatient, and support for the object is still not widespread enough for it to be in common use. So there must be a better way to creating and using canvas paths...

Enter the RGraph.path function. This is a function that takes the context and the desired path as arguments and calls the relevant functions for you. The path is an array of letters (and numbers) - each representing an action that should be taken. So it's similar to svg paths, but there are a few more options that make it more versatile.

So what does it look like to use? Like the example below:

context.path(['b', 'm', 5, 5, 'l', 45, 45, 'l', 5, 45, 'c', 'f', 'red']);

That would translate to the following sequence of function calls:

context.beginPath();
context.moveTo(5, 5);
context.lineTo(45, 45);
context.lineTo(5, 45);
context.closePath()'
context.fillStyle = 'red';
context.fill();

In terms of character size, it's approximately 55% smaller. If you don't compress your code (you really should) that's very significant and larger paths will potentially give you bigger savings. Even when you take compression and minification into account the savings may well be worth it.

Note:

You can further reduce the size of your paths by using string-based paths.

Path commands

So here's a list of the available path commands and what they represent. The RGraph path function is constantly evolving so if you want to update in the future it shouldn't be too difficult to extract it. The function in the RGraph core common library is a function expression (NOT a statement), so the declaration may at first glance be unfamiliar, but I've tried to make the code that you can download here similar so taking it out of an updated RGraph library and replacing your code should be quite straightforward.

String based paths

If you're not using animation with the path function you can use string-based paths instead of array based paths. These are far easier to write and are significantly less verbose too. Obviously, the strings need to be parsed so there's a tiny performance hit with them. An example of a string-based path is:

context.path('b r 5 5 50 50 s black f red');

Note:
If you want to use the lineDashOffset option - ldo - you need to use an array-based path. But you could do this to set the lineDashOffset before you specify your entire path:

context.path(['ldo', [5,5]]);
context.path('b r 5 5 56 56 s red');

Get the code

The code for the path function is here. You can include it in your page with a script tag:

<script src="rgraph.path.js"></script>

Example usage

A rectangle example

// Using the path function
context.path(['b', 'r', 5, 5, 90, 90, 'f', 'red']);

// Using the canvas API
context.beginPath();
context.rect(5,5,90,90);
context.fillStyle = 'red';
context.fill();

An arc example

// Using the path function
context.path(['b', 'a', 50, 50, 50, 0, 3.14, false, 'f', 'red']);

// Using the canvas API
context.beginPath();
context.arc(50,50,50,0, Math.PI false);
context.fillStyle = 'red';
context.fill();

A bezierCurveTo example

// Using the path function
context.path(['b', 'm', 5, 100, 'bc', 5, 0, 100, 0, 100, 100, 's', 'red']);

// Using the canvas API
context.beginPath();
context.moveTo(5, 100);
context.bezierCurveTo(5, 0, 100, 0, 100, 100);
context.strokeStyle = 'red';
context.stroke();

An arcTo example

// Using the path function
context.path(['b', 'm', 5, 100, 'at', 50, 0, 95, 100, 50, 's', 'red']);

// Using the canvas API
context.beginPath();
context.moveTo(5, 100);
context.arcTo(50, 0, 95, 100, 50);
context.strokeStyle = 'red';
context.stroke();

A clip example

// Using the path function
context.path(['sa', 'b', 'r', 0, 0, 50, 50, 'cl', 'b', 'r', 5, 5, 590, 240, 'f', 'red', 'rs']);

// Using the canvas API
context.save();
    context.beginPath();
    context.rect(0, 0, 50, 50);
    context.clip();
    
    context.beginPath();
    context.rect(5, 5, 590, 240);
    context.fillStyle = 'red';
    context.fill();
context.restore();

A setLineDash example

// Using the path function
context.path(['ld', [2,6], 'ldo', 4, 'b', 'r', 5, 5, 590, 240, 's', 'red']);

// Using the canvas API
context.setLineDash([2,6]);
context.lineDashOffset = 4;
    
context.beginPath();
context.rect(5, 5, 590, 240);
context.strokeStyle = 'red';
context.stroke();

A globalAlpha example

// Using the path function
context.path(['ga', 0.25, 'b', 'r', 5, 5, 590, 240, 'f', 'red']);

// Using the canvas API
context.globalAlpha = 0.25;
    
context.beginPath();
context.rect(5, 5, 590, 240);
context.fillStyle = 'red';
context.fill();

Changelog

10th November 2015

15th September 2015

7th September 2015

Changes available from RGraph 5.2

When working with RGraph, as well as inside the RGraph libraries, the path function has been made to be a member function of the chart object. This means that you can do this:
obj.path({
    path: 'b r % % % % f %',
    args: [10,10,100,100,'red']
});

And also this - an even shorter syntax:

obj.path('b r % % % % f %', 10, 10, 100, 100, 'red');