In this blog post I want to share my lessons learned from creating tooltips for the Lightbeam visualisations.
Visualisations are the major part of this Outreachy – Lightbeam internship. We use D3-force to create a simulation for an array of nodes (websites), compose the desired forces, and then listen for tick events to render the nodes as they update. When we started, the preferred graphics renderer was SVG. We now have a Canvas based implementation because this is more efficient than SVG. Here is an article why canvas is better than svg and here are the initial results.
Having said that, lets talk about tooltips.
SVG based solution
I had first implemented tooltips(text labels) on the SVG version. Here is the PR.
In SVG, you can render every node as a DOM element. This is why SVG isn’t the right solution for graphs with too many nodes, because it can easily slow down the browser’s page loading time due to too many nodes.
Since this is an SVG based solution, I chose text-labels over tooltips.
Tooltips vs text-labels
Tooltips come with an additional overhead of dynamically updating the
x,y coordinates and the
title. Text labels are rendered like ordinary DOM elements, the SVG
<text> element, one for each node(website).
But using tooltips, you can cut down the number of text nodes. As opposed to having one text node for each node(website), there is one tooltip (DOM element) whose position and content is dynamically updated.
I shall discuss the tooltip based solution in the canvas implementation.
1) Text labels in SVG
- By default, the visibility of text-labels is set to
- All text-labels have a common class
- On hover, over the circular nodes, the corresponding text-label’s visibility is changed from
- For each node(website) there is a corresponding
- In order to identify and set the visibility of the right
<text>corresponding to the hover on node(website), every
<text>element is assigned an additional class
iis the index corresponding to each node(website).
- When node(website) with index
iis hovered, the corresponding
text-iis set to
2) Hover on the nodes(websites)
In order to achieve the hover effect,
mouseleave event handlers are registered on each node(website).
After the initial implementation, there was a lot of flicker when the text labels were made visible on node hover. Although it isn’t very clear from the above gif, notice the time taken to display
http://www.google.com on the third node. Looks like gifs aren’t good at capturing flickers (I need to find out a better solution), but the time delay to show the third label in the above gif === flicker effect.
At first, I thought the flickering was due to the mouse events. Later, I found out that these mouse events had nothing to do here. However, it is worth making a note of the above two mouse events. Link
Below is the DOM for the SVG version:
Since the nodes/circles are independent of the text labels, and have no direct descendant nodes, the mouse events had nothing to do with the flicker.
2) SVG and z-index
After wracking my brains for a while, I figured out the cause for the flickering of labels. If you carefully examine the above gif, you will notice that the lines are on top of the circles. On mouse hover over the nodes, it was
mouseenter for circles and labels were made
visible. But, when the mouse accidentally appeared on top of the lines (because you don’t realise you are doing so) it caused the
mouseleave for circles and the visibility was getting toggled.
When I figured out this cause, the obvious solution to run in my head was to set
z-index for circles to be greater than the lines. Despite this, the flickering was still there. On further investigation, this is what I found from the SVG specification:
z-index in SVG is defined by the order the elements appear in the document. You will have to change the element order if you want to bring a specific shape to the top. Drawing lines first, followed by drawing circles fixed the flickering bug.
It was good to learn about
z-index in SVGs.
To be continued… tooltips – a canvas base implementation