如何使用d3.js通过鼠标悬停显示XY图表的x和y坐标

dohp0rv5  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(145)

当鼠标悬停在XY图表上时,我试图显示数据点的x和y坐标。链接到我的小提琴可以找到here。我遵循了here的例子,但我不知道为什么当我将鼠标悬停在XY图表上的点上时,工具提示没有显示。代码如下,任何帮助都非常感谢!

var data = [ {x: 0, y: 0}, {x: 5, y: 30}, {x: 10, y: 40},
              {x: 15, y: 60}, {x: 20, y: 70}, {x: 25, y: 100} ];

  const margin = {
    left: 20,
    right: 20,
    top: 20,
    bottom: 80
  };

  const svg = d3.select('svg');
  svg.selectAll("*").remove();

  const width = 200 - margin.left - margin.right;
  const height = 200 - margin.top - margin.bottom;

  const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);

  var x = d3.scaleLinear()
          .domain([0, d3.max(data, function(d){ return d.x; })])
          .range([0,width])
          .nice();

  var y = d3.scaleLinear()
          .domain([0, d3.max(data, function(d){ return d.y; })])
          .range([0,height])
          .nice();

  const xAxis = d3.axisTop()
              .scale(x)
              .ticks(5)
              .tickPadding(5)
              .tickSize(-height)

  const yAxis = d3.axisLeft()
              .scale(y)
              .ticks(5)
              .tickPadding(5)
              .tickSize(-width);

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", `translate(20,${height-margin.top-60})`)
    .call(xAxis);

  svg.append("g")
    .attr("class", "y axis")
    .attr("transform", "translate(20,20)")
    .call(yAxis);

  var lineFunction = d3.line()
  .x(function(d) {return x(d.x); })
  .y(function(d) {return y(d.y); })
  .curve(d3.curveLinear);

  var tooltip = d3.select("svg")
      .append("div")
      .style("opacity", 0)
      .attr("class", "tooltip")
      .style("background-color", "white")
      .style("border", "solid")
      .style("border-width", "1px")
      .style("border-radius", "5px")
      .style("padding", "10px")

  // A function that change this tooltip when the user hover a point.
  // Its opacity is set to 1: we can now see it. Plus it set the text and position of tooltip depending on the datapoint (d)
  var mouseover = function(d) {
    tooltip
      .style("opacity", 1)
  }

  var mousemove = function(d) {
    tooltip
      .html("x: " + d.x + "<br/>" + "y: " + d.y)
      .style("left", (d3.mouse(this)[0]+90) + "px")
      .style("top", (d3.mouse(this)[1]) + "px")
  }

  // A function that change this tooltip when the leaves a point: just need to set opacity to 0 again
  var mouseleave = function(d) {
    tooltip
      .transition()
      .duration(200)
      .style("opacity", 0)
  }

  //defining and plotting the lines
  var path = g.append("path")
              .attr("class", "path1")
              .attr("id", "blueLine")
              .attr("d", lineFunction(data))
              .attr("stroke", "blue")
              .attr("stroke-width", 2)
              .attr("fill", "none")
              .attr("clip-path", "url(#clip)");

        // plot a circle at each data point
        g.selectAll(".dot")
            .data(data)
            .enter().append("circle")
            .attr("cx", function(d) { return x(d.x); } )
            .attr("cy", function(d) { return y(d.y); } )
            .attr("r", 3)
            .attr("class", "blackDot")
            .attr("clip-path", "url(#clip)")
            .on("mouseover", mouseover )
            .on("mousemove", mousemove )
            .on("mouseleave", mouseleave )

字符串

pbpqsu0x

pbpqsu0x1#

<div>标记不能存在于<svg>标记中,因此不会呈现工具提示元素。
我建议您修改元素访问器的.select(...)函数。您应该选择body元素并将其附加到那里,而不是选择svg元素。
此外,要在图形上方呈现div工具提示,您需要将div元素的位置设置为绝对位置,如下所示:

var tooltip = d3.select("body")
      .append("div")
      .style("opacity", 0)
      .attr("class", "tooltip")
      .style("background-color", "white")
      .style("border", "solid")
      .style("border-width", "1px")
      .style("border-radius", "5px")
      .style("padding", "10px")
      .style("position", "absolute")

字符串
它应该能像预期的那样工作,而here只是更新代码的一个小链接。

xdnvmnnf

xdnvmnnf2#

下面是如何在画布上找到一个点。

/* js/external.js */
//<![CDATA[
var doc, bod, I; // for use on other loads
addEventListener('load', function(){
doc = document; bod = doc.body;
I = function(id){
  return doc.getElementById(id);
}
var canvas = I('canvas');
canvas.onmousemove = function(e){
  var cb = canvas.getBoundingClientRect(), x = e.clientX-cb.left, y = e.clientY-cb.top;
  console.log('x:'+x+'; y:'+y);   
}
canvas.ontouchmove = function(e){
  var cb = canvas.getBoundingClientRect(), z = e.touches[0], x = z.clientX-cb.left, y = z.clientY-cb.top;
  console.log('x:'+x+'; y:'+y);
}
});
//]]>
/* css/external.css */
*{
  box-sizing:border-box; padding:0; margin:0;
}
html,body{
  width:100%; height:100%;
}
body{
  background:#ccc;
}
#canvas{
  display:block; width:100%; height:100%; background:#fff; margin:0 auto;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1' />
    <title>Test Template</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script type='text/javascript' src='js/external.js'></script>
  </head>
<body>
  <canvas id='canvas'></canvas>
</body>
</html>

相关问题