我正在尝试修复一些我正在处理的事件代码。在这种特殊情况下,我需要能够在click
上订阅svg:circle
个活动。但是,还需要将圆圈移动到mousedown
上的z-index顶部,以便可以将元素拖到其他元素的顶部。
这样做的方法是将元素从DOM中取出,然后使用我在http://bl.ocks.org/eesur/4e0a69d57d3bfc8a82c2中使用的辅助函数将其重新插入到正确的位置。这样做的问题在于事件链似乎已经破坏了将元素从dom中移除,从而阻止click
事件触发。
我想知道是否有人能够提出更好的方法来确保click
正确触发但仍允许在拖动生命周期中某处更改z-index?
这个小例子展示了z-index如何变化,但点击事件不会在控制台中触发。一旦它在顶部再次单击该元素,则会正确触发该点击。
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>
&#13;
答案 0 :(得分:1)
我设法提出了一个稍微古怪的想法,这看起来很有效,但如果DOM内有很多元素,我会对性能有点担心。
这个想法本质上是,而不是将选择(在mousedown
上)移动到顶部,而不是移动鼠标元素后面的所有其他东西(相同类型,在这种情况下为svg:circle
)堕落。
d3.selectAll("circle")
.on("mousedown", function() {
var that = this;
d3.select(this.parentNode)
.selectAll("circle")
.filter(function() { return this !== that; })
.moveBehind(that);
})
.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);
});
};
d3.selection.prototype.moveBehind = function(element) {
return this.each(function() {
this.parentNode.insertBefore(this, element);
});
};
&#13;
.red {
fill: red;
}
.blue {
fill: blue;
}
.green {
fill: green;
}
&#13;
<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>
&#13;
答案 1 :(得分:1)
我想知道问题是否与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>