本篇简单介绍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>
添加坐标点标识
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) + ")";})
添加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);});
线性的数值展示
.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 + ")");});