Created
January 27, 2018 21:28
-
-
Save robert-moore/38ebc00b8bb2ca33e85b8c415cbe03b0 to your computer and use it in GitHub Desktop.
D3 Tooltips
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// generates innerHTML for tooltip based on title and a map of key:value pairs | |
export function keyValueTitleTooltip(tooltip, title, map) { | |
tooltip.classed("key-value-tooltip", true).html("") | |
if (title) | |
tooltip | |
.append("p") | |
.attr("class", "title") | |
.text(title) | |
tooltip | |
.selectAll("p.value") | |
.data(Object.keys(map)) | |
.enter() | |
.append("p") | |
.attr("class", "value") | |
.html(d => `<b>${d}:</b> ${map[d]}`) | |
} | |
// generates innerHTML for tooltip bar chart comparing values | |
// [ { name: focalName, value: focalValue formattedValue: focalDisplay }, { name: compareName ... }] | |
export function comparisonBarChartTooltip(tooltip, title, data) { | |
tooltip.classed("bar-chart-tooltip", true).html("") | |
tooltip.style("min-width", "200px") | |
let x = d3 | |
.scaleLinear() | |
.range([0, 170]) | |
.domain([0, d3.max(data, d => d.value)]) | |
if (title) tooltip.append("p".attr("class", "title")).text(title) | |
tooltip | |
.append("p") | |
.attr("class", "name") | |
.text(data[0].name) | |
for (let i = 0; i < 2; i++) { | |
let valueContainer = tooltip | |
.append("div") | |
.attr("class", "value-container") | |
.classed("focal", i === 1) | |
valueContainer | |
.append("div") | |
.attr("class", "value-bar") | |
.style("width", x(data[i].value) + "px") | |
.style("height", "30px") | |
valueContainer | |
.append("p") | |
.attr("class", "value-label") | |
.text(data[i].formattedValue || data[i].value) | |
} | |
tooltip | |
.append("p") | |
.attr("class", "name") | |
.text(data[1].name) | |
} | |
// places tooltip within container with config options | |
export function placeTooltip( | |
tooltip, | |
container, | |
{ | |
verticalAnchor = "bottom", | |
horizontalAnchor = "center", | |
x = 0, | |
y = 0, | |
position = "relative", | |
} = {}, | |
) { | |
// svg is the container used for absolute positioning and for setting a bounding box | |
const contentRect = tooltip.node().getBoundingClientRect() | |
const containerRect = container.node().getBoundingClientRect() | |
const contentWidth = contentRect.width | |
let tooltipLeftEdge = x | |
if (position === "relative") tooltipLeftEdge += containerRect.left | |
if (horizontalAnchor === "center") tooltipLeftEdge -= contentWidth / 2 | |
if (horizontalAnchor === "right") tooltipLeftEdge -= contentWidth | |
const containerRightEdge = containerRect.left + containerRect.width - 5 // padding | |
// If the right edge of tooltip is beyond the right edge of the container, | |
// fix the tooltip to the edge of the container: | |
if (tooltipLeftEdge > containerRightEdge - contentWidth) { | |
tooltipLeftEdge = containerRightEdge - contentWidth | |
} else if (tooltipLeftEdge < containerRect.left) { | |
tooltipLeftEdge = containerRect.left | |
} | |
let tooltipTopEdge = y + window.scrollY | |
if (position === "relative") tooltipTopEdge += containerRect.top | |
if (verticalAnchor === "bottom") tooltipTopEdge -= contentRect.height | |
if (tooltipTopEdge < containerRect.top) { | |
tooltipTopEdge = containerRect.top | |
} | |
tooltip | |
.style("top", `${tooltipTopEdge}px`) | |
.style("left", `${tooltipLeftEdge}px`) | |
.style("visibility", "visible") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment