【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的scaleBandscaleLinear函数来设置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的selectAlldataenter方法,我们创建一组矩形元素来表示数据集中的每个数据点,并设置相应的属性和事件处理程序:

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的axisBottomaxisLeft方法来创建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...

相关推荐
m0_748255026 分钟前
前端常用算法集合
前端·算法
真的很上进20 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web1309332039826 分钟前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
图表制作解说(目标1000个图表)38 分钟前
ECharts散点图-气泡图,附视频讲解与代码下载
echarts·统计分析·数据可视化·散点图·大屏可视化
NiNg_1_2341 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1231 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~2 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语2 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport2 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg2 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全