d3 / d3-zoom

Pan and zoom SVG, HTML or Canvas using mouse or touch input.
https://d3js.org/d3-zoom
ISC License
505 stars 143 forks source link

Zoom and Drag with d3.geo.projections v4 #150

Closed Maarondesigns closed 5 years ago

Maarondesigns commented 6 years ago

I can't seem to get d3 zoom to work properly with d3 geo projections.

I've converted Ivy Wang's Drag to Rotate the Globe to v4 and combined it with zoom. It works properly with mouse functions as long as I include svg.on("mousedown.zoom", null); , otherwise d3.zoom mousedown overrides the d3.drag functions. I still can't get it to work with touch. Double tapping and two finger zooming works on a laptop (Asus, windows 10, google chrome), but on mobile (IOS 11.4) it only changes lineweights I've included in my zoom function but doesn't scale. Also, rotating the projection doesn't work unless I include

   svg.on("mousedown.zoom", null)
      .on("touchstart.zoom", null)
      .on("touchmove.zoom", null)
      .on("touchend.zoom", null);

which disables touch zooming all together. These things seem to work together on Jason Davies site though when you try to zoom on mobile it usually zooms the entire page. I would love to know if I am relatively close to getting this to work, or if it simply won't work combining these zoom and drag functions. Is there a working example of this somewhere? I haven't been able to find anything in v4 with map projections and that works on touch.

My whole project is on my Codepen. Zoom function start on line 287 and drag on line 344. Here's a code snippet:

var svg = d3
    .select("body")
    .append("svg")
    .attr("id", "world")
    .attr("width", width)
    .attr("height", height)
    .call(d3.zoom().on("zoom", zoomed));

   svg.on("mousedown.zoom", null)
      .on("touchstart.zoom", null)
      .on("touchmove.zoom", null)
      .on("touchend.zoom", null);

  function zoomed() {
     let k = d3.event.transform.k;
     d3.selectAll("#world").attr("transform", "scale(" + k + ")");
     d3.selectAll(".graticule").attr("stroke-width", 0.5 / k);
     d3.selectAll(".pin").attr("stroke-width", 2 / k);
     d3.selectAll(".travelPath").attr("stroke-width", 2 / k);
     d3.selectAll(".land").attr("stroke-width", 1 / k);
     d3.selectAll(".border").attr("stroke-width", 1 / k);
   }
mbostock commented 5 years ago

There’s an up-to-date Versor Dragging example here:

https://observablehq.com/@d3/versor-dragging

It’d be nice to improve it by adding zooming. I’m not sure this would qualify for using d3.zoom, however, as the logic for panning and zooming a globe is very different from panning and zooming on the plane. Maybe take a look at d3-geo-zoom?