Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 v4 - d3.zoom() prevents binding some events except on the Window

Unhelpful Github discussion led me to ask this question here:


After changing to the new v4.0 D3, seems like using d3.zoom() blocks some events, like:

Calling this:
svg.call(d3.zoom()
     .scaleExtent([1, 40])
     .translateExtent([[-100, -100], [width + 90, height + 100]])
     .on("zoom", zoomed));
And then this:
document.querySelector('svg').addEventListener('mouseup', function(){ alert(1) })

Won't alert anything when clicking anywhere on the SVG.


I really don't want to do:

window.addEventListener("mouseup", function(e){
    if( [target or target parent is the specific SVG element] ){
        // do something
    }
}

Because this will introduce a global non-namespaced event mouseup on the window (this technique seems to only work on the window object) and this event might be removed somewhere else, or happen multiple times. (It isn't easy to encapsulate it, or I simply don't know how).

Any better ideas on how to capture mouseup events on the SVG?


Related to another question of mine: Event capturing namespace

Demo page


Update:

With the help of Mark's answer, here's the working demo

like image 522
vsync Avatar asked Jul 26 '16 10:07

vsync


1 Answers

Still not sure I understand your intent, but you might be approaching this from the wrong angle. Instead of trying to add your own events, just work within the events provided by the zoom behavior. The zoom functionality provides for panning where mousedown starts a pan (i.e. zoom start event) and mouseup ends a pan (i.e. zoom end event). So, the real question becomes, how can you differentiate a pan vs a "click" mouseup? To do that, just check if the user moved the mouse:

svg.call(d3.zoom()
         .scaleExtent([1, 40])
         .translateExtent([[-100, -100], [width + 90, height + 100]])
         .on("start", zoomstart)
         .on("end", zoomend)
         .on("zoom", zoomed));

var mousePos = null;
function zoomstart(){
  mousePos = d3.mouse(this);
}

function zoomend(){
  var m = d3.mouse(this);
  if (mousePos[0] ===  m[0] && mousePos[1] === m[1]){
    alert('mouseup');
  }
}

function zoomed() {
  svg.attr("transform", d3.event.transform);
  gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
  gY.call(yAxis.scale(d3.event.transform.rescaleY(y)));
}

Update fiddle.

like image 192
Mark Avatar answered Nov 13 '22 14:11

Mark