问题
Following this example, why isn't drag event triggering on the polygons in the following code?
var data = [
{
"index" : 0,
"vx" : 0,
"vy" : 0,
"x" : 842,
"y" : 106
},
{
"index" : 1,
"vx" : 0,
"vy" : 0,
"x" : 839,
"y" : 56
},
{
"index" : 2,
"vx" : 0,
"vy" : 0,
"x" : 771,
"y" : 72
}
]
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var simulation = d3.forceSimulation(data)
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.on("tick", ticked);
var nodes = svg.append("g").attr("class", "nodes"),
node = nodes.selectAll("g"),
polygons = svg.append("g").attr("class", "polygons"),
polygon = polygons.selectAll("polygon");
var voronoi = d3.voronoi()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.extent([[0, 0], [width, height]]);
var update = function() {
polygon = polygons.selectAll("polygon")
.data(data).enter()
.append("polygon")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node = nodes.selectAll("g").data(data);
var nodeEnter = node.enter()
.append("g")
.attr("class", "node");
nodeEnter.append("circle");
nodeEnter.append("text")
.text(function(d, i) { return i; })
.style("display", "none");
node.merge(nodeEnter);
simulation.nodes(data);
simulation.restart();
}();
function ticked() {
var node = nodes.selectAll("g");
var diagram = voronoi(node.data()).polygons();
polygon = polygons.selectAll("polygon");
node.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
polygon
.attr("points", function(d, i) { return diagram[i]; });
polygon.call(d3.drag()
.on("start", dragstarted)
.on("drag", function(d) { console.log("drag"); })
.on("end", dragended));
node
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")" });
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
svg {
border: 1px solid #888888;
}
circle {
r: 3;
cursor: move;
fill: black;
}
.node {
pointer-events: all;
}
.polygons {
fill: none;
stroke: #999;
}
text {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.1/d3.min.js"></script>
<svg width="400" height="200"></svg>
Is it because of the update function? I've tried it without the circles nested in g elements and it still doesn't work. I'm guessing it's because of scoping but can't see why yet that it works in the example but not here. (Also, not sure why the node seems to need to bound again in the tick function).
The goal is to use d3 voronoi and force simulation to easily target the nodes for dragging, tooltips, mouseovers, and other events, and update nodes (and links) dynamically.
回答1:
why isn't drag event triggering on the polygons
The drag event happens in the bl.ock you've used as your example because of the fill. By changing the fill to none
on your polygons, the drag events will only trigger when you click on the outline.
If you want to keep none
as your fill for your polygons use this line in your css:
.polygon {
fill: none;
pointer-events: all;
...
来源:https://stackoverflow.com/questions/42319453/why-isnt-the-d3-voronoi-polygon-drag-event-triggering-on-polygons-in-force-simu