jdlubrano / datamaps-zoomto-plugin

A Datamaps plugin to zoom to coordinates on a Datamaps svg.
MIT License
3 stars 1 forks source link

how to get the new scale and translate after a zoom? #1

Closed gregdevs closed 8 years ago

gregdevs commented 8 years ago

Hi, very cool plugin. One question I have is, once I call the zoomto function, and the map correctly zooms, once I go to zoom in and out with the mousewheel, the translate and scale reset to original size, instead of maintaining the new zoom.

What would be the best way to set the new translate and scale so there is no reset?

Thanks

jdlubrano commented 8 years ago

Hmm...I don't know off the bat. It has been a while since I looked at this plugin.

I will dive into it this weekend and try to find an answer for you though.

-----Original Message----- From: "Greg" notifications@github.com Sent: ‎6/‎10/‎2016 5:45 PM To: "jdlubrano/datamaps-zoomto-plugin" datamaps-zoomto-plugin@noreply.github.com Subject: [jdlubrano/datamaps-zoomto-plugin] how to get the new scale adtranslate after a zoom? (#1)

Hi, very cool plugin. One question I have is, once I call the zoomto function, and the map correctly zooms, once I go to zoom in and out with the mousewheel, the translate and scale reset to original size, instead of maintaining the new zoom. What would be the best way to set the new translate and scale so there is no reset? Thanks — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

gregdevs commented 8 years ago

Sure thing, thank you. Here's a bit more info on my use case: I have some functionality in which the map zooms to the state depending on the geolocation coordinates of the user on load. Thats working fine, however when I go to zoom or drag around, the map resets its scale and translate to its original origin.

I believe I need to update the redraw with the new d3 translate and scale origin but I'm not certain.

navigator.geolocation.getCurrentPosition(function(position) {
  var loc = [position.coords.latitude, position.coords.longitude]
  var zoomOpts = {
    scaleFactor: 4, // The amount to zoom
    center: {
      lat: position.coords.latitude, // latitude of the point to which you wish to zoom
      lng: position.coords.longitude, // longitude of the point to which you wish to zoom
    },
    transition: {
      duration: 1000 // milliseconds
    }
  };

  datamap.zoomto(zoomOpts); // performs zoom

  datamap.svg.call(d3.behavior.zoom().on("zoom", function() {redraw(isGeo);})); // on mousewheel

  function redraw(isGeo) {           
      datamap.svg.selectAll("g").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");

  }
jdlubrano commented 8 years ago

@gregdevs You are correct regarding the root cause of your issue. I have a couple of solutions in mind and I am currently weighing my options.

At the very least, I will add a hook to the plugin that fires after a zoomto is complete. Then you would be able to track the zooms performed by the plugin and compensate accordingly.

I will make the changes and provide an example soon.

gregdevs commented 8 years ago

@jdlubrano awesome, thanks for checking into it.

jdlubrano commented 8 years ago

Alright, there is now a hook fired on the completion of zoom events. You can find an example of how to use it in examples/mousewheel-zoom.html. Please let me know if the example meets your needs so that I can close this issue.

gregdevs commented 8 years ago

@jdlubrano Great, will give it a shot and post followup. Thanks again for digging into it.

gregdevs commented 8 years ago

@jdlubrano Thanks, this worked perfectly. One minor change I had to make was to the' transformStr' function (Just had to pass the correct parameters)

            function transformStr(x, y, scale) {
              return "translate(" + [x, y] + ")scale(" + scale + ")";
            }

instead of

        function transformStr(x, y, scale) {
              return "translate(" + [translateX, translateY] + ")scale(" + scale + ")";
            }
gregdevs commented 8 years ago

@jdlubrano One last question.., I noticed in your example if you click on the zoomin or zoomout buttons, and then try and zoom in or out with the mosuewheel to an area on the map, the origin is a bit off from the mouse target. Any idea or suggestions for recalculating the current origin? thanks again

jdlubrano commented 8 years ago

It probably has something to do with the effect on the existing scale on the d3.event.translate. I would guess (because I do it in the plugin itself) that you might have to do something along the lines of

 function redraw() {
   var translateX = d3.event.translate[0];
   var translateY = d3.event.translate[1];
   var scale = d3.event.scale;

   if (currentZoom) {
     scale *= currentZoom.scale;
     translateX += currentZoom.translate.x * currentZoom.scale; // or * scale
     translateY += currentZoom.translate.y * currentZoom.scale; // or * scale
   }

   dm.svg.selectAll("g")
        .attr("transform", transformStr(translateX, translateY, scale))
   ;
}

It may also require division. It's tough to say without playing with it myself; unfortunately, I tend to be pretty busy with my day job during the week. If you can wait for the weekend, I can probably work something out. Otherwise, if you happen to figure it out, feel free to let me know what worked for you. You can even submit a PR if you like.

gregdevs commented 8 years ago

Thanks again. Will keep you posted. If I figure anything out as well.