Closed liebig closed 6 years ago
@liebig
Hey I'm glad to hear that you like the plugin and thanks for the feedback. I guess I just want to be clear about your request, though. So, I guess, in order to zoom, you need to have a point toward which you are zooming. In other words, you need to define a center for the SVG math to work.
But it sounds like you would expect the default center to be the center of the visible map, no matter what projection you are using. Does that sound correct?
@jdlubrano Thank you for your quick answer and please excuse my vague description. I want to use your plugin not only to jump to a certain point, but also to zoom with the mouse wheel. By specifying the duration, a pleasant scrolling process is possible. But if I now enter the scale factor and the duration without coordinations, the system automatically zooms to the coordinates 0. Here I would wish that you simply scroll on the center of the displayed map. If I understand correctly, you are already doing this with the oldCenterCoordsXY.
@liebig
I opened a PR that is functional, although after looking at this code for the first time in a long time, there are several things I would like to improve. Especially to support ES6 imports and such. Nevertheless, would you mind attempting to use the feature/zoom-to-center-of-map-by-default
branch? I think that functionally it suits your needs. If that branch works for you, I can merge the PR, cut a new release, and publish to NPM. I'm happy to get the release to you quickly and refactor my debt later.
@jdlubrano Wow, that was quick. Thank you, that works exactly as I had wished. Maybe you can help me with another problem. Now I'm just trying to implement dragging. So when the left mouse button is pressed the 2D map should be moved. This is my attempt:
var drag = d3.behavior.drag().on('drag', function () {
var dx = d3.event.dx;
var dy = d3.event.dy;
d3.select("#world").selectAll('svg>g').transition()
.duration(100)
.attr('transform', 'translate(' + ((document.getElementById('world').offsetWidth / 2) + dx) + ',' + ((document.getElementById('world').offsetHeight / 2) + dy) + ')')
});
Unfortunately, that doesn't even work out a bit. Do you have any advice for me? Thank you.
@liebig
For me to dive into this and produce some sample code will take some time. I may have something specific for you after the weekend if I have the time to work through your example.
Nevertheless, I can provide some higher-level thoughts. So SVG transformations are, well, complicated. Probably out of necessity. Often times, in order to achieve the behavior that we as humans want or expect, you have to consider and account for existing transformations on your SVG before performing a new transformation.
You may want to take a look at this example: https://github.com/jdlubrano/datamaps-zoomto-plugin/blob/master/examples/mousewheel-zoom.html. Of particular interest to you may be the idea of using the onZoomComplete
hook to keep track of the current scale and translation of your datamap. I will admit, though, that I never quite figured out the math for translating after zooming with the zoomto plugin. I don't understand the d3.zoom functionality well enough to consider its interaction with zoomto.
I do have however, an example of just using d3.zoom with the mousewheel and dragging. Maybe this is ultimately what you are looking for, but I don't know your exact use case, so I can't say for sure. Nevertheless, here is that full example
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="../node_modules/datamaps/dist/datamaps.all.js"></script>
<script src="../src/datamaps-zoomto.js"></script>
</head>
<body>
<style>
#map {
position: relative;
margin: 0 auto;
width: 800px;
height: 450px;
}
</style>
<div id="map"></div>
<script>
var dm = new Datamap({
element: document.getElementById('map')
});
var zoom = d3.behavior.zoom();
dm.svg.call(zoom.on("zoom", redraw)); // on mousewheel or drag
function transformStr(x, y, scale) {
return "translate(" + [x, y] + ")scale(" + scale + ")";
}
var previousScale = 1;
function redraw() {
var translateX = d3.event.translate[0];
var translateY = d3.event.translate[1];
var scale = d3.event.scale;
var g = dm.svg.selectAll("g");
if (previousScale !== scale) {
// Only animate the user's zoom. Animating drags creates a weird UX, I think.
g = g.transition().duration(400);
previousScale = scale;
}
g.attr("transform", transformStr(translateX, translateY, scale));
}
</script>
</body>
</html>
@jdlubrano Thank you very much! This works just the way I imagined it. I couldn't have done this without your help. Thank you for taking the time to help me so well. If there's anything I can do to support you, just let me know. In any case, I would help you as a tester.
@liebig
I'm glad that example works for you. I am not sure if you still need the feature/zoom-to-center-of-map-by-default
branch, but I will work toward a new release with zooming to the center of the map by default and ES6 module support as the main features.
For anyone else who stumbles upon this thread, I will keep this issue open until I finish a new version of the plugin with these feature.
Thank you for this great tiny plugin. However, I would wish that if no lat and lng are specified, the values 0 are not used automatically. I think it would be better to just zoom in or out and not to move to center.