Reputation: 14440
I'm seeing some strange behavior in d3. I have a force directed graph in the usual way
node = svg.selectAll(".node").data(graph.nodes).enter().append("circle")....
and when someone clicks on a node, I want a simple animation (instead of a console.log)
function set_focus(d) { console.log('set'); }
function remove_focus() { console.log('remove'); }
node.on("mousedown", set_focus);
node.on("mouseup", remove_focus);
Interestingly, when I mousedown on a node, the set event fires, but when I release the mouse, remove_focus
doesn't fire. Anyone have any idea what's going on?
d3v5, chrome 65, macOS 10.13
Upvotes: 1
Views: 2071
Reputation: 131
Now you have a listener for the end of a zooming event see here
so you could do something like
d3.zoom().on('end', remove_focus)
Upvotes: 0
Reputation: 451
tldr: the zoom event is conflicting with your mouseup event.
I created a fork because I'm not too sure what you're going to want to do with this and I didn't want to mess with your git history: this link is the fork.
It seems that your Zoom event on the SVG is "consuming" all other events once the mouse is clicked. My impression is that this is a known and commonly complained about issue. I think that this GitHub ticket is related, and so is this one. Per Mike Bostock,
This is the expected behavior. Per the release notes: “The zoom behavior now consumes handled events.” So, if a mouseup event was part of a zoom gesture, then the zoom behavior stops the immediate propagation of that mouseup event preventing other listeners from receiving it (and where possible prevents the associated browser default behavior). This makes it easier to combine zooming and dragging as in this example:
http://bl.ocks.org/mbostock/3127661b6f13f9316be745e77fdfb084
If you want to prevent a zoom gesture from starting, use zoom.filter to ignore certain events, or use event.stopPropagation or event.stopImmediatePropagation to prevent the zoom behavior from receiving the initiating event. If you want to do something after a zoom gesture, listen to the zoom event.
I can get your mouseup
event to fire by either deleting the d3.zoom
event, or by calling d3.event.stopPropagation
within the set_focus
function. So, the two lines below (and in the fork) get your remove_focus
function to fire, but I'm not sure if I also messed up how you want the zoom event to be working:
function set_focus(d) {
console.log('set');
d3.event.stopPropagation();
node.style("opacity", function(o) { return (d == o || o.layer == d.layer - 1) ? 1 : 0.1; });
link.style("opacity", function(o) { return (o.target == d.id) ? 1 : 0.02; });
}
function remove_focus() {
console.log('remove');
d3.event.stopPropagation();
node.style("opacity", 1);
link.style("opacity", function () { return edgeOpacity; })
}
Upvotes: 5