This article originally appeared on the Inspire.nl Blog. Inspire is a Dutch software studio that develops innovative Ruby on Rails web applications for computer, tablet and mobile.
For the Elsevier Journal Insights project we wanted to create interactive graphs in the browser. The type of graphs are different, but one of the simplest among them is a regular line-graph. We chose the jQuery-SVG library to let us interact with a graph built with SVG. An other popular library is Raphaël, but we decided to go for the former because it seemed to give us more freedom while keeping close the SVG specifications.
- A visual grid consisting of white dashed lines. These help the user to interpret the value of the data points.
- The data points, each belonging to a year and with a value, represented as white/colored disc.
- Underneath the data points lies a surface, giving an indication of the volume underneath the data points.
- Textual labels at the axis determining the domain and range of the graph.
In the following sections of this article we look at each of these parts and how to construct them using HTML, SVG and CSS.
For the lines of the visual grid we first need to determine the dimensions of the canvas we work on and the range of the data we need to display. Lets assume the final html element will have a width of 720 pixels and a height of 410 pixels. We want to plot the value of something over a period of time, the domain of the graph. In this case; we have five domain points (a year for which there is a value) and we have established that our range goes from 0-15. The grid system we want consists of vertical lines for every year and horizontal lines for every 2.5 points on the range. Keeping in mind we need some margins on sides, we can create the following grid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
You will see the use of the
This acts as a grouping element, or a container.
It has no visual properties of its own.
Using CSS we can create a nice subtle dashed style for these lines:
1 2 3 4 5 6 7 8 9 10
With the grid in place, we should know were every data point belongs.
So; we now have our grid and we know how to calculate positions for domain and range points on that grid. The next step is to draw some real data points on that grid. For this we use the circle element, and again we wrap them all in a grouping element:
1 2 3 4 5 6 7
Here we use some
data- attributes to keep track of some information assigned to this data set.
data-setname can be used for a tooltip when inspecting this data point, and the value of
data-value gives a precise numeric representation of the data point.
When we use both the
fill styling properties of circles, we can create the effect of double circles and create the white/colored discs:
1 2 3 4 5 6 7
The data points now need some form of connection between them; a clear visual guide to relate them to the overall graph and their siblings.
To create a more clear visual indication of our data points, we like to color the area underneath the lines (an other option would be to connect the data points with a line).
For this we use the
<path> element of svg.
Using this element, we can create a polygon of any shape which will appear as a surface in our graph.
You can look at is like putting your pen down on a piece of paper and moving it, without lifting it from the paper, to the specified coordinates (this is closely related to my first programming education on primary school; LOGO and Turtle Graphics).
More information on the
<path> element can be found in the path specifications.
The important commands are:
M(x,y): move the pen to the absolution point (x,y)
L(x,y): draw a straight line to the absolution point (x,y)
Z: close the current path and draw a straight line to the initial point
So to create our surface we have to start (
M) in the lower left corner, draw a line (
L) up to the first point and then follow all the points using the
L command again.
We end the path with a
Z, after specifying the lower right corner of our graph.
You can see that the coordinates of the path are the same as for the data points.
1 2 3
The color of this surface is already defined when we created that data points, but we would to keep the grid visible. One solution is to make the surface transparent:
1 2 3
Although this works for a single surface, this does not work when we have multiple data sets and surfaces in our graph.
That is because when we stack multiple transparent elements, the background comes less and less visible.
So we need to redraw the grid over de surface again.
The dirty way would be to copy the
<g> elements of our surface, but SVG offers us a nice trick with the
With that element we can refer to an other element and let the SVG internally copy it.
Notice that we have created
id attributes for the
g elements of the grid.
xlink:href path, we can display them above the surfaces:
To keep the visual effect of transparency, we give these line a
stroke-opacity, so it looks they are under the surface:
1 2 3
We now have all the visual elements of our graph; the grid for visual guidance, the data points and a surface under the data points. What we still need is some textual indication of what we are looking at.
SVG offers us the nice ability to add text elements which can act as labels, but the CSS-settings are a bit different than for normal html elements.
Instead of the
text-align property, we can use
text-anchor which accepts values
For the labels with the vertical lines, we use the
middle property so that every year is centered on the line.
For the labels which indicate a value for the horizontal lines, we use
end so the right side of the label is on the same place.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Other regular css-font properties can also be applied to the svg text elements.
We use the
kerning property to separate each character a bit from the other.
1 2 3 4 5 6 7 8 9 10 11 12 13
We just have created all the elements we need to create a graph.
When we combine it all in a single
<svg> element, we get the result as in this jsFiddle or this stand alone page.
Notice that the order of the surfaces and points are switched; otherwise the surface falls over the points.
In our original graphs we use multiple data sets.
In this system that is very easy; for each data set you can create a
g.points group elements with the points and a
path element for the surface.
With the surfaces you need to be careful; we know that for our data the values of one set are always equal or larger than to the other.
If that is unknown, the data points can “disappear” behind other surfaces.
In the next post we will show how you can interact with this graph using jQuery.
Then you are able to add some nice animations (e.g. when you hover over a data point) and add a tooltip with information (remember the
data-value attribute we used?).