Step 8: Tooltip

In this step, we will use the mouseover functionality we created earlier and position the container showing the name to act as a tooltip which appears next to the mouse cursor.

Tooltip styling

First, we add some style for the tooltip. Most of it is just to make it look nicer. However, important is the declaration to use absolute positioning (position: absolute;). This allows to use the attributes top and left to position an element. Since the position will depend on the mouse cursor whose position we don’t know yet, we leave that for the moment and add it later in the code.

style.css - tooltip styling
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/* ... */

.tooltip {
  font-weight: bold;
  padding: 0.5rem;
  border: 1px solid silver;
  color: #222;
  background: #fff;
  border-radius: 5px;
  box-shadow: 0px 0px 5px 0px #a6a6a6;
  opacity: 0.9;
  position: absolute;
}

/* ... */

Tooltip positioning

To calculate the position of the tooltip (the left and top CSS attributes), we take the map container as reference element and get the position of the mouse cursor. Then we add a little offset so the tooltip appears next to the cursor and not on top of it.

We also try to guess if the tooltip is shown outside the map container on the right side. In this case, we show it more to the left so it does not go over the map. Yes, this it rather buggy and you might as well leave that part.

map.js - tooltip positioning
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// ...

/**
 * Show a tooltip with the name of the feature. Calculate the position
 * of the cursor to show the tooltip next to the mouse.
 *
 * @param {object} f - A GeoJSON Feature object.
 */
function showTooltip(f) {
  // Get the ID of the feature.
  var id = getIdOfFeature(f);
  // Use the ID to get the data entry.
  var d = dataById[id];

  // Get the current mouse position (as integer)
  var mouse = d3.mouse(d3.select('#map').node()).map(
    function(d) { return parseInt(d); }
  );

  // Calculate the absolute left and top offsets of the tooltip. If the
  // mouse is close to the right border of the map, show the tooltip on
  // the left.
  var left = Math.min(width - 4 * d.name.length, mouse[0] + 5);
  var top = mouse[1] + 25;

  // Show the tooltip (unhide it) and set the name of the data entry.
  // Set the position as calculated before.
  tooltip.classed('hidden', false)
    .attr("style", "left:" + left + "px; top:" + top + "px")
    .html(d.name);
}

// ...

Hide tooltip

Right now, the tooltip never disappears. If we move the cursor out of the map or even out of Switzerland, we would like the tooltip to disappear.

map.js - hide tooltip function
127
128
129
130
131
132
133
134
135
136
// ...

/**
 * Hide the tooltip.
 */
function hideTooltip() {
  tooltip.classed('hidden', true);
}

// ...

And we need to trigger the action when the mouse moves out of the features.

index.html - trigger tooltip hiding
91
92
93
94
95
96
97
98
        // ...
        .attr('d', path)
        // When the mouse moves over a feature, show the tooltip.
        .on('mousemove', showTooltip)
        // When the mouse moves out of a feature, hide the tooltip.
        .on('mouseout', hideTooltip);

  // ...

Next

Proceed to Step 9: Show details of features.