d3 mouseover Tips

本篇简单介绍d3 mouseover添加tips的实现

绘制曲线

  • 以前几篇的d3曲线为例

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <div id="test-svg">
        </div>
    </body>
    <script src="https://d3js.org/d3.v5.js"></script>
    <script>
        window.onload = function() {

            // 数据
            var data = [{
                date: new Date(2019, 3, 24),
                value: 23.24
            }, {
                date: new Date(2019, 3, 25),
                value: 72.15
            }, {
                date: new Date(2019, 3, 26),
                value: 38.84
            }, {
                date: new Date(2019, 3, 27),
                value: 58.62
            }, {
                date: new Date(2019, 3, 30),
                value: 10.80
            }, {
                date: new Date(2019, 4, 1),
                value: 85.47
            }];

            var width = 800,
                height = 400,
                padding = {
                    top: 40,
                    right: 40,
                    bottom: 40,
                    left: 40
                };

            var colors = d3.schemeSet2;
            var svg = d3.select("#test-svg")
                .append('svg')
                .attr('width', width + 'px')
                .attr('height', height + 'px');

            // x轴:时间轴
            var xScale = d3.scaleTime()
                .domain(d3.extent(data, function(d) {
                    return d.date;
                }))
                .range([padding.left, width - padding.right]);

            var xAxis = d3.axisBottom()
                .scale(xScale)
                .tickSize(10);

            var bisect = d3.bisector(function(d) {
                return d.date;
            }).left;

            svg.append('g')
                .call(xAxis)
                .attr("transform", "translate(0," + (height - padding.bottom) + ")")
                .selectAll("text")
                .attr("font-size", "10px")
                .attr("dx", "50px");

            var ymax = d3.max(data, function(d) {
                return d.value;
            });

            // y轴
            var yScale = d3.scaleLinear()
                .domain([0, ymax])
                .range([height - padding.bottom, padding.top]);

            var yAxis = d3.axisLeft()
                .scale(yScale)
                .ticks(10);

            svg.append('g')
                .call(yAxis)
                .attr("transform", "translate(" + padding.left + ",0)");

            var curveLine = d3.line()
                .x(function(d) {
                    return xScale(d.date);
                })
                .y(function(d) {
                    return yScale(d.value);
                })
                .curve(d3.curveCatmullRom.alpha(0.5));

            svg.append("path")
                .datum(data)
                .attr("fill", "none")
                .attr("stroke", "steelblue")
                .attr("stroke-width", 1.5)
                .attr("stroke-linejoin", "round")
                .attr("stroke-linecap", "round")
                .attr("d", curveLine);

        }
    </script>

</html>

1487780-20190817105555029-1668514834.png

添加坐标点标识


svg.append("g")
                .selectAll('circle')
                .data(data)
                .join("circle")
                .attr("r", 5)
                .attr("fill", "white")
                .attr("stroke", "steelblue")
                .attr("stroke-width", 1.5)
                .attr("transform", function(item) {
                    return "translate(" + xScale(item.date) + "," + yScale(item.value) + ")";
                })

1487780-20190817105742202-1865613939.png

添加tips

  • 添加tips,一个圆点及数据文本

var tips = svg.append("g")
                .attr("class", "tips")
                .style("display", "none");

            tips.append("circle")
                .attr("r", 3);

            tips.append("text")
                .attr("x", 8)
                .attr("dy", ".35em");

添加事件

  • 添加一个和svg同等大小的透明rect面板用来触发事件

  • 获取坐标


// d3.mouse(this)[0] 获取当前鼠标位置的x坐标
// xScale.invert() 转为曲线上的x坐标
xScale.invert(d3.mouse(this)[0])

// d3.bisector() 获取当前曲线上x坐标对应数据中的点序号
var bisect = d3.bisector(function(d) {
                return d.date;
            }).left;

bisect(data, xdata, 1, data.length - 1);

svg.append("rect")
                .attr("class", "overPlane")
                .attr("width", width)
                .attr("height", height)
                .attr("opacity", 0)
                .on("mouseover", function() {
                    tips.style("display", null);
                })
                .on("mouseout", function() {
                    tips.style("display", "none");
                })
                .on("mousemove", function() {
                    var xdata = xScale.invert(d3.mouse(this)[0]);
                    var yIndex = bisect(data, xdata, 1, data.length - 1);
                    var d0 = data[yIndex - 1],
                        d1 = data[yIndex],
                        d = xdata - d0.date > d1.date - xdata ? d1 : d0;
                    tips.attr("transform", "translate(" + xScale(d.date) + "," + yScale(d.value) + ")");
                    tips.select("text").text(d.value);
                });

1487780-20190817145636902-1418829358.gif

线性的数值展示

.on("mousemove", function() {

                    var mouse = d3.mouse(this);
                    var begin = 0,
                        end = line[0].getTotalLength(),
                        target = null;
                    
                    // 已知当前鼠标x轴坐标,求出对应的path上的坐标点
                    while(true) {
                        target = Math.floor((begin + end) / 2);
                                                // getPointAtLength 返回给定路径上给定长度的点坐标 
                        pos = line[0].getPointAtLength(target);
                        if((target === end || target === begin) && pos.x !== mouse[0]) {
                            break;
                        }
                                                // 当返回的路径的x坐标和鼠标对应的x坐标重合 break;
                        if(pos.x > mouse[0]) end = target;
                        else if(pos.x < mouse[0]) begin = target;
                        else break;
                    }

                    tips.select("text").text(yScale.invert(pos.y).toFixed(2));
                    tips.attr("transform", "translate(" + mouse[0] + "," + pos.y + ")");

                });

1487780-20190817155444632-454775036.gif

转载于:https://www.cnblogs.com/chenjy1225/p/11368632.html

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值