【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...

相关推荐
bysking14 分钟前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓30 分钟前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_41133 分钟前
无网络安装ionic和运行
前端·npm
理想不理想v34 分钟前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云44 分钟前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205871 小时前
web端手机录音
前端
齐 飞1 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹1 小时前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
GIS程序媛—椰子2 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0012 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html