In the previous post in this series we have looked at creating SVG graphs. We constructed the graph using parts as the visual grid, data points, surfaces and text labels. In this post we will look at the ability to interact with the graph and add some nice animations.
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.
What to add
The previous post ended with this graph as its result. It is a nice visualization, but it is at some points a bit vague. For instance, it is not clear what the precise value of data point is. Also, it would be nice to make the graph alive by adding some animations to it. For this we have the following in mind:
- Nice shadows to appear behind data points when the mouse is over it.
- A vertical bar which helps the user focus on a data point and it’s location on the domain
- A tooltip which precise values for each data point
Each of these three elements will be discussed in this post. The final result will be this.
Shadows on mouse hover
Our fist addition is to add a nice shadow around a data point when the mouse pointer hovers over it.
This is to empathize that data point has the focus of the user.
On the right you can see the desired result; the shadow is a round gradient around the point.
This is our first difficulty; it is very hard to add (drop) shadows to SVG elements.
In a normal situation we could use the border property of an element, but for the discs we have already used the
fill
and stroke
properties.
The solution we chose for was to place copies of the data points under each one, and give that copy gradient properties.
So lets first create that gradient.
In a SVG document you can define some recurring elements and properties, using <defs>
at the top of the document (or inside the <svg>
element).
Here you can see the code to construct a radial gradient, which we give an id gradientShadow
.
1 2 3 4 5 6 |
|
For the precise workings of the <radialGradient>
element, see the gradients and patterns specifications.
With this gradient defined we can create copied elements to mimic a shadow.
For this we use the same coordinates as the plain
circles and in the style
we set the fill
to the gradient we have just created:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
You will notice that we have placed styling properties as attributes, instead of the more common way in a stylesheet. That is because the SVG animation library can’t animate styles from CSS correctly, but it does with attributes.
So what do we need to animate this shadow? First, we need the jQuery-SVG plugin, the SVG-DOM extension (to traverse the DOM) and the SVG-Animate extension (to animate properties of elements). So, the following is added to our document head after loading the jQuery javascript:
1 2 3 |
|
Now we can create our Javascript to add mouseenter
and mouseleave
events to each (plain) data point.
When the mouse enters one, we first stop any ongoing animation for the shadow point and then grow the circle.
When the mouse leaves the point we shrink the shadow point back to its original size.
The SVG properties can be animated by prepending svg
to their attribute name.
We use the knowledge that (in order of elements) before each normal data point a shadow point is present to select it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
This extension to the original SVG is now complete, and you can see the result here. We now have a nice visual effect, but it is not enough for out taste. We would also like to create a “vertical coherence”, to draw even more attention to the point. For this we create an “indicator line”.
Indicator line
The indicator we have in mind is a vertical bar which scrolls horizontally over the graph and goes from the lower part of the graph to the height of the (highest) data point.
We use the <rect>
element to construct it.
We initialize it on the left of the graph, and thus it goes up to the first data point:
1
|
|
We give it a simple style to be white with a gray border but be hidden on first display:
1 2 3 4 5 6 |
|
This indicator line should move over the graph, sticking at the data points, when the user moves the mouse.
We already have the data points at which we could add more functionality, but we would like the have the whole column of data lines triggering the indicator line to that vertical line.
We can do this by adding, for each vertical line in our line grid, a
<line>
element with a specified stroke-width
, which will act as a sensitivity area.
We chose lines over rects because the lines will always be centered on the year-points; there is no need for extra calculations, independent to the width of the sensitivity.
The image on the right shows the construction of the trigger lines when they would be visible.
1 2 3 4 5 6 7 |
|
1 2 3 4 |
|
We place the trigger lines just after the indicator line but before the data points; otherwise the mouse events we are to apply will be “blocked” by other elements.
For the real animation we first create a Javascript function which moves the indicator line to a specified column. A tricky part is getting the height of the indicator; in our examples we have only used one data set, but the function can handle multiple data sets; it will always scale the indicator to the height of the first defined data set (which should be of largest value). The index of the triggering line is used to get the corresponding data point.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
To make the animation complete, we have to add mouse event handlers to the tigger lines to move the indicator to that column:
1 2 3 4 5 6 |
|
We also modify the mouse event handlers for the data points to call the moveIndicator
method when the mouse enters it:
1 2 3 4 5 6 |
|
And with that last mouse event we have completed the functionality for the moving line indicator. You can see the result of this stage here.
All the elements needed to give better indication of the users focus are now present. But still the data points are sometimes hard to interpret. For that, we want to create a tooltip giving precise information.
Tooltip
As a final showcase of interactivity with SVG elements we will create a tooltip which shows when we hover over a data point.
In that tooltip we would like to display the precise value of a data point.
The tooltip will have a nice litte triangle to point to the data point, which will be constructed with the
<polygon>
element.
The #tooltip-title
element will contain the data set name of the selected data point and span.value-part
will hold the corresponding value of this data point.
1 2 3 4 5 6 7 8 9 10 |
|
The styling for this tooltip element and its child elements is quite extensive and of little intereset, so we skip it here for brevity. In the final jsFiddle you can inspect it.
The first Javascript function we write is to show (of fade in) the tooltip, given a data point element which is of interest.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
A nice litte feature is that in normal situations the tooltip shows right of the data point.
In case of a small screen, the tooltip flips to the left side, to prevent unnecessary scrollbars appearing.
The data-
attributes of the <g>
and <circle>
elements of the first tutorial are used to display information.
For everything we can show, we would like a function to hide:
1 2 3 4 5 |
|
Finally we again modify the mouse events for the data points, to show and hide the tooltip on enter and leave, respectively:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Wrapup
We have created three extensions to our base SVG graph; shadows on the data points, an indicator line for more visual focus and a tooltip for every data point which gives the precise values. The final interactive graph can be inspected in this jsFiddle or on this stand alone page. You can see the real-world project for one of the graphs with multiple data sets at the Elsevier Journal Insights website.
We hope you have learned a bit about how you can use SVG, how to access it with jQuery and add interactivity by animating properties using mouse events.
This blog post appeared earlier on the Inspire.nl blog, where I was lead developer on the Elsevier Journal Insights project.