我正在尝试修复我正在处理的一些事件代码。在这种特殊情况下,我需要能够订阅click上的svg:circle事件。但是,还需要将圆移动到mousedown上的z-index的顶部,以便可以将该元素拖动到其他元素的顶部。

完成此操作的方法是将元素从DOM中取出,并使用我从http://bl.ocks.org/eesur/4e0a69d57d3bfc8a82c2使用的辅助函数将其重新插入正确的位置。这样做的问题在于,事件链似乎已损坏,将元素移出了dom阻止了click事件触发。

我想知道是否有人可以提出一种更好的方法来确保click正确触发,但仍然允许在拖动生命周期中的某处更改z-index?

这个小示例显示了z-index的变化方式,但click事件不会在控制台中触发。元素再次位于顶部时,再次单击它确实可以正确触发单击。



d3.selectAll("circle")
  .on("mousedown", function() {
    d3.select(this).moveToFront();
  })
  .on("click", function() {
    var fill = d3.select(this).style("fill");
    console.log("You clicked on : " + fill);
  });

d3.selection.prototype.moveToFront = function() {
  return this.each(function() {
    this.parentNode.appendChild(this);
  });
};

.red {
  fill: red;
}
.blue {
  fill: blue;
}
.green {
  fill: green;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js"></script>
<svg width="600" height="600">
  <circle class="red" cx="50" cy="50" r="50" />
  <circle class="blue" cx="100" cy="100" r="50" />
  <circle class="green" cx="150" cy="150" r="50" />
</svg>

最佳答案

我想知道问题是否出在d3上,所以我用纯JS编写了等效内容,并且在Chrome上的结果与d3完全一样。我可以通过将click替换为mouseup并将其与mousedown元素进行比较来使其工作,就像我的评论一样。您在评论中表示,由于其他项目限制,您无法使用该解决方案。我认为我还是应该发布解决方案,因为有人提到FF和IE中的行为是不同的。



const circles = Array.from(document.getElementsByTagName('circle'));
let mousedown;
for (let circle of circles) {
  circle.addEventListener('mousedown', (e) => {
    mousedown = e.target;
    e.target.parentNode.appendChild(e.target);
  }, false);
  circle.addEventListener('mouseup', (e) => {
    if (mousedown === e.target) {
      console.log('You clicked on : ' + window.getComputedStyle(e.target).fill);
    }
    mousedown = null;
  }, false);
}

.red {
  fill: red;
}
.blue {
  fill: blue;
}
.green {
  fill: green;
}

<svg width="600" height="600">
  <circle class="red" cx="50" cy="50" r="50" />
  <circle class="blue" cx="100" cy="100" r="50" />
  <circle class="green" cx="150" cy="150" r="50" />
</svg>

07-24 09:47
查看更多