【d3.js入门】使用Tooltip增强数据可视化效果

在数据可视化中,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)
    })

在线演示地址:scqilin.github.io/d3js/intera...

相关推荐
变与不变8062 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半2 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck2 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.2 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子2 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常2 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常2 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋3 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
鸿蒙开发4 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos
屏什么录4 小时前
录屏超过两小时就卡顿崩盘?从参数调优到代码实现,一文彻底搞定长时间录屏
前端·音视频开发