【问题标题】:Tooltip overwritten for moving images in D3为 D3 中的移动图像覆盖工具提示
【发布时间】:2026-01-07 15:35:01
【问题描述】:

在这里,我正在使用随机 x 和 y 在缩放和拖动 SVG 中动态移动图像。并且还在循环本身内为这些图像添加了工具提示。当工具提示出现时,其内容将被最后一个元素的工具提示覆盖。请查看FIDDLE。在下面的代码中,在 for 循环中,我尝试将工具提示显示为“用户工具提示:”+i,但所有图像都显示了最后一个工具提示内容。

for(var i in icons){

  var rectx = Math.floor(Math.random()*(max-min+1)+min);
  var recty = Math.floor(Math.random()*(max-min+1)+min);

  //console.log("i : "+i);

   if(icons[i]=="user"){

    var tip="user tooltip: "+i;
    console.log(tip);

    svg.append("image")
        .attr("id","user"+i)
        .attr('x',rectx)
        .attr('y',recty)
        .attr('width', 30)
        .attr('height', 24)
        .attr("xlink:href", "http://www.worryfreelabs.com/wp-content/uploads/2016/06/WFl_logo-2015-icon-only-white-background.png")
    .on("mouseover", function(d) {      
            div.transition()        
                .duration(200)      
                .style("opacity", .9);  

            div .html("user tooltip: "+i)   
                .style("left", (d3.event.pageX) + "px")     
                .style("top", (d3.event.pageY - 28) + "px");    
            })  

        .on("mouseout", function(d) {       
            div.transition()        
                .duration(500)      
                .style("opacity", 0);
        });

   }
}

【问题讨论】:

    标签: d3.js svg tooltip


    【解决方案1】:

    问题在于变量的范围。您可以通过以 d3 方式实现功能来解决此问题。使用enter 方法。

    var imgHeight = 1025,
      imgWidth = 1538, // Image dimensions (don't change these)
      width = 500,
      height = 500, // Dimensions of cropped region
      translate0 = [-290, -180],
      scale0 = 1; // Initial offset & scale
    
    svg = d3.select("body").append("svg")
      .attr("width", width + "px")
      .attr("height", height + "px");
    
    svg.append("rect")
      .attr("class", "overlay")
      .attr("width", width + "px")
      .attr("height", height + "px");
    
    svg = svg.append("g")
      .attr("transform", "translate(" + translate0 + ")scale(" + scale0 + ")")
      .call(d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom))
      .append("g");
    
    svg.append("image")
      .attr("width", imgWidth + "px")
      .attr("height", imgHeight + "px")
      .attr("xlink:href", "http://www.myfreetextures.com/wp-content/uploads/2015/01/deep-green-grass-texture.jpg");
    
    var div = d3.select("body").append("div")
      .attr("class", "tooltip")
      .style("opacity", 0);
    
    
    function zoom() {
      svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
    }
    
    var max = 400,
      min = 200;
    
    var icons = ["user", "user", "table"];
    
    svg.selectAll("image.icon")
      .data(icons.filter(function(d) {    
        return d == "user";
      }))
      .enter()
      .append("image")
      .classed("icon", true)
      .attr("id", function(d, i) {
        return "user" + i;
      })
      .attr('x', function() {
        return Math.floor(Math.random() * (max - min + 1) + min);
      })
      .attr('y', function() {
        return Math.floor(Math.random() * (max - min + 1) + min);
      })
      .attr('width', 30)
      .attr('height', 24)
      .attr("xlink:href", "http://www.worryfreelabs.com/wp-content/uploads/2016/06/WFl_logo-2015-icon-only-white-background.png")
      .on("mouseover", function(d, i) {
        div.transition()
          .duration(200)
          .style("opacity", .9);
    
        div.html("user tooltip: " + i)
          .style("left", (d3.event.pageX) + "px")
          .style("top", (d3.event.pageY - 28) + "px");
      })
      .on("mouseout", function(d) {
        div.transition()
          .duration(500)
          .style("opacity", 0);
      });
    
    
    setInterval(function() {
      for (var i in icons) {
    
        if (icons[i] == "user") {
          d3.select("#user" + i).transition()
            .delay(1000)
            .attr('x', function(d) {
              return Math.random() * 720 - 29;
            })
            .attr('y', function(d) {
              return Math.random() * 200 - 30;
            })
            .duration(6000)
        }
    
      }
    }, 500);
    .overlay {
      fill: none;
      pointer-events: all;
    }
    div.tooltip {
      position: absolute;
      text-align: center;
      width: 60px;
      height: 28px;
      padding: 2px;
      font: 12px sans-serif;
      background: lightsteelblue;
      border: 0px;
      border-radius: 8px;
      pointer-events: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

    【讨论】:

    • 非常感谢,它成功了。还有一个疑问,我是否需要另一张图片,如果 icon[i] == "table" 并为其附加另一个工具提示,该怎么做?请解释一下。