在数据可视化中,Tooltip(工具提示)是一个常用的交互元素,它可以提供更详细的数据信息,并在用户悬停或点击某个数据点时显示。本文将介绍如何使用D3.js的交互来实现Tooltip功能,从而增强图表的数据展示效果。
柱状图比较常见,其Tooltip也比较简单也很典型,鼠标hover到矩形上就弹出提示信息,而且弹出的位置跟随鼠标即可。
折线图要比柱状图复杂。为了方便鼠标hover,我们通常需要鼠标移动到指定区域的时候就会触发tooltip,比如线上面的点,以及单根线的时候 线所对应的区域。如图所示,红色区域都对于芒果这个点的tooltip,而且为了准确tooltip弹出的位置固定在点的位置。
柱状图Tooltip
我们需要准备一个数据集,用于展示每周某一天的数据值。假设我们有以下数据集:
javascript
let dataset = [
{ name: "周一", value: 30 },
{ name: "周二", value: 20 },
{ name: "周三", value: 50 },
{ name: "周四", value: 20 },
{ name: "周五", value: 80 },
{ name: "周六", value: 30 },
{ name: "周日", value: 60 }
];
然后,我们使用D3.js的scaleBand
和scaleLinear
函数来设置x轴和y轴的比例尺:
javascript
let xScale = d3.scaleBand()
.domain(d3.range(dataset.length))
.range([padding, svgWidth - padding])
.padding(0.3);
let yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function (d) { return d.value; })])
.range([svgHeight - padding, padding]);
为了实现Tooltip的功能,我们需要在HTML文档中定义一个Tooltip容器:
html
<div id="tooltip" class="tooltip">
<div class="tooltip-range">
Name: <span id="range"></span>
</div>
<div class="tooltip-value">
Value: <span id="count"></span>
</div>
</div>
然后,我们根据数据集的长度和比例尺的设置,计算每个柱形的宽度:
javascript
let barWidth = xScale.bandwidth();
通过使用D3.js的selectAll
、data
和enter
方法,我们创建一组矩形元素来表示数据集中的每个数据点,并设置相应的属性和事件处理程序:
javascript
let bars = svg.selectAll(".bar")
.data(dataset)
.enter()
.append("rect")
.attr("class", "bar")
.attr("fill", "#69b3a2")
.attr("x", function (d, i) {
return xScale(i);
})
.attr("y", function (d) {
return yScale(d.value);
})
.attr("width", barWidth)
.attr("height", function (d) {
return svgHeight - yScale(d.value) - padding;
})
.on("mouseover", function (d) {
tooltip.style("opacity", 1);
tooltip.select("#range").text(d.name);
tooltip.select("#count").text(d.value);
})
.on("mousemove", function (d) {
tooltip.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
})
.on("mouseout", function (d) {
tooltip.style("opacity", 0);
});
最后,我们使用D3.js的axisBottom
和axisLeft
方法来创建x轴和y轴,并将它们添加到SVG元素中。 以上代码实现了一个带有Tooltip的柱状图,当鼠标悬停在柱形上时,Tooltip将显示相应的数据信息。通过设置Tooltip的样式和位置,可以更好地展示数据,提高用户体验。
折线图 Tooltip
折线图的教程前面有【d3.js入门】基本折线图动画,这里不再复述,主要为了交互添加了点和隐藏的矩形区域。代码中比较关键的地方是计算弹窗的位置。
javascript
// 绘制圆点
svg.selectAll(".circle")
.data(dataset)
.enter()
.append("circle")
.attr("class", "circle")
.attr("cx", function (d, i) {
return xScale(i) + xScale.bandwidth() / 2;
})
.attr("cy", function (d) {
return yScale(d.value);
})
.attr("r", 4)
.attr("fill", "#ffffff")
.attr("stroke", "#69b3a2")
.attr("stroke-width", "3px")
// 每个区域绘制一个矩形 用于触发事件
let _w = (svgWidth - padding * 2) / (dataset.length - 1)
svg.selectAll(".rect")
.data(dataset)
.enter()
.append("rect")
.attr("class", "rect")
.attr("x", function (d, i) {
return xScale(i) - _w / 2;
})
.attr("y", padding)
.attr("width", _w)
.attr("height", svgHeight - padding * 2)
.attr("fill", "transparent")
.on("mouseover", function (d,i) {
tooltip.style("opacity", 1)
tooltip.select("#range").text(d.name)
tooltip.select("#count").text(d.value)
// tooltip 在 点上方显示 考虑svg在页面中的位置
// 计算svg 在页面中的位置
let svgRect = svg.node().getBoundingClientRect();
let svgLeft = svgRect.left;
let svgTop = svgRect.top;
// 滚动条的位置
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
tooltip.style("left", xScale(i) + xScale.bandwidth() / 2 + svgLeft + "px")
.style("top", yScale(d.value) + svgTop + scrollTop + "px")
})
.on("mouseout", function (d) {
tooltip.style("opacity", 0)
})