gpt4 book ai didi

javascript - 在 d3.js 中的拖放操作期间不会触发鼠标悬停事件

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:48:23 24 4
gpt4 key购买 nike

我试图将一个圆圈拖到另一个圆圈上以连接两条路径。问题是当我将一个圆圈 (c2) 拖到另一个圆圈 (c1) 上时,如果圆圈 c1 是在圆圈 c2 之前创建的,则不会触发 c1 鼠标悬停事件。

Here the js fiddle link

    var closedRoad = true;

var width = 960,
height = 500;

var points = d3.range(1, 5).map(function(i) {
return [i * width / 5, 50 + Math.random() * (height - 100)];
});

var points1 = d3.range(1, 5).map(function(i) {
return [i * width / 5, 50 + Math.random() * (height - 100)];
});

var points2 = d3.range(1, 5).map(function(i) {
return [i * width / 5, 50 + Math.random() * (height - 100)];
});

var count = 0;
var ways = [];

var currentWay = null;

var selected = null;

var line = d3.svg.line();

var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);

var rect = svg.append("rect")
.attr("width", width)
.attr("height", height);

ways.forEach(function(way, i) {
svg.append("path")
.datum(way)
.attr("id", "p" + way.id)
.attr("class", "line")
.call(redraw);
});

d3.select(window)
.on("keydown", keydown)
//.on("mousemove", mousemove)
//.on("mouseup", mouseup)
.on("mousedown", mousedown)
.on("dblclick", dblclick);

function redraw(way) {
way.attr("d", function(d) { return line(d.pts); });

var circle = svg.selectAll(".way" + way.data()[0].id)
.data(way.data()[0].pts, function(d) { return d; });
circle.enter().append("circle")
.attr("class", "way" + way.data()[0].id)
.attr("r", 1e-6)
.on("mousedown", function(d) {
if (closedRoad) {
currentWay = way.data()[0];
selected = d;

if (d3.event) {
d3.event.preventDefault();
d3.event.stopPropagation();
}
}
})
.on("mouseover", function() { d3.select(d3.event.target).classed("highlight", true); })
.on("mouseout", function() { d3.select(d3.event.target).classed("highlight", false); })
.transition()
.duration(750)
.ease("elastic")
.attr("r", 6.5);

circle
.attr("cx", function(d) { return d[0]; })
.attr("cy", function(d) { return d[1]; });

////
var drag = d3.behavior.drag();
drag.on("dragstart", function(d) {
console.log('START');
})
.on("drag", function(d) {
console.log('MOVE');

var m = d3.mouse(svg.node());
d[0] = Math.max(0, Math.min(width, m[0]));
d[1] = Math.max(0, Math.min(height, m[1]));

//redraw(way);
redrawAll();
})
.on("dragend", function(d) {
console.log('END');
});

circle.call(drag);
////

circle.exit().remove();

}

function dblclick() {
currentWay.pts.pop();
//redraw(svg.select("#p" + currentWay.id));
redrawAll();

closedRoad = true;
}

function mousedown() {
if (closedRoad) {
currentWay = { id: ++count, pts: [] };
ways.push(currentWay);

svg.append("path")
.datum(currentWay)
.attr("id", "p" + currentWay.id)
.attr("class", "line")
.on("mouseover", function() {
d3.select(d3.event.target).classed("highlight", true);
})
.on("mouseout", function() { d3.select(d3.event.target).classed("highlight", false); })
.call(redraw);

closedRoad = false;
}

currentWay.pts.push(selected = d3.mouse(svg.node()));
//redraw(svg.select("#p" + currentWay.id));
redrawAll();
}

function redrawAll() {
ways.forEach(function(way, i) {
redraw(svg.select("#p" + way.id));
});
}

function mousemove() {

}


function keydown() {
if (!selected) return;
switch (d3.event.keyCode) {
case 8: // backspace
case 46: { // delete
var i = currentWay.pts.indexOf(selected);
currentWay.pts.splice(i, 1);
selected = currentWay.pts.length ? currentWay.pts[i > 0 ? i - 1 : 0] : null;
redraw(svg.select("#p" + currentWay.id));
break;
}
}
}

你能帮帮我吗?

谢谢!前!

最佳答案

问题很简单,当两个元素重叠绘制时,'mouseover' 事件只会在最顶层的元素上触发。无论您是否正在处理最顶层元素的鼠标事件,都是如此。改变这种行为需要大量的变通办法,但没有一个是理想的。

一些可能的解决方案:

  • 在您的拖动函数中,反复检查此时是否还有另一个圆圈。

    您可以使用 SVGSVGElement.getIntersectionList() 方法来查找给定矩形中的所有元素。请注意,此方法是在 SVG 节点上调用的,而不是在 d3 选择上调用的。

  • 当您拖动一个节点时,通过设置样式使其对鼠标事件“透明”pointer-events:none;在上面。

    当然,这也会使其对拖动事件透明,因此您必须将拖动事件添加到容器而不是节点,然后在'dragstart'事件中找出正在拖动哪个圆,更改它的指针事件样式,并将圆圈选择存储在您的 drag 可访问的变量中函数(它将像您当前的代码一样移动它)和 dragend函数(它将重新设置其指针事件样式)。您还需要将背景矩形添加到 <svg><g>分配了拖动行为的元素,这样即使鼠标仅在“透明”圆上,它也会响应鼠标事件。

  • 当您拖动一个节点时,将其移至绘制顺序的底部,以便所有其他节点绘制在顶部。

    由于 SVG 没有像 HTML 那样的“z-index”属性,实现这一点的唯一方法是使用 selection.order() 重新排序 DOM。或纯 Javascript insertBefore() .

  • 或者,接受这只是一个小的美学缺陷,不会改变代码的功能,因此不值得为上述方法带来的麻烦和性能影响。

    如果您不喜欢 某些 圆圈在拖动时会改变颜色,您可以在拖动期间在 svg 上设置一个“拖动”类,并为'highlight' 类只有在它不是 'svg.dragging' 的子级时才进行可见的更改。

关于javascript - 在 d3.js 中的拖放操作期间不会触发鼠标悬停事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21523950/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com