Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Zoomable map problem

The Issue

I'm trying to build a map that can be zoomed using the mouse wheel and panned with drag. For that I'm using d3.behavior.zoom() and it works fine for the map. However, I also need to mark some points in the map (which are included in the same topojson used to draw the map). They get rendered just fine, but I'm having trouble handling the zoom behaviour with these points. If you try to zoom or pan, the points get translated abruptly and even seem to change their path!

Any ideas?

<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.js"></script>
<script src="topojson.v0.min.js"></script>
<html>
<style>
.background {
fill: none;
pointer-events: all;
}
.department {
fill: #aaa;
stroke: #fff;
stroke-width: 1.5px;
}
</style>
<body>
<script>
d3.json("santafe.json", function(error, theProvince) {
var width= 960, height= 500;
var svg = d3.select("body").append("svg");
var departments = topojson.object(theProvince, theProvince.objects.departments);
// The projection
var projection = d3.geo.mercator()
.scale(14000)
.center([-60.951,-31.2])
.translate([width / 2, height / 2]);
// The path
var path = d3.geo.path()
.projection(projection);
// Zoom behavior
var zoom = d3.behavior.zoom()
.translate(projection.translate())
.scaleExtent([height, Infinity])
.scale(projection.scale())
.on("zoom", function() {
projection.translate(d3.event.translate).scale(d3.event.scale)
map.selectAll("path.zoomable").attr("d", path);
});
// The map
var map = svg.append("g")
.classed("provinceMap", true)
.call(zoom);
map.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
// Departments
map.selectAll(".department")
.data(departments.geometries)
.enter().append("path")
.classed("department", true)
.classed("zoomable", true)
.attr("d", path);
// Places
map.selectAll(".place-label")
.data(topojson.object(theProvince, theProvince.objects.maternidades).geometries)
.enter().append("path")
.classed("place", true)
.classed("zoomable", true)
.attr("d", d3.svg.symbol().type("cross"))
.attr("transform", function(d) { return "translate(" + projection(d.coordinates.reverse()) + ")"; });
});
</script>
</body>
</html>
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
topojson=function(){function t(t,e){function n(e){var n=t.arcs[e],r=n[0],a=[0,0];return n.forEach(function(t){a[0]+=t[0],a[1]+=t[1]}),[r,a]}var r={},a={},o={};e.forEach(function(t){var e=n(t);(r[e[0]]||(r[e[0]]=[])).push(t),(r[e[1]]||(r[e[1]]=[])).push(~t)}),e.forEach(function(t){var e,r,c=n(t),i=c[0],s=c[1];if(e=o[i])if(delete o[e.end],e.push(t),e.end=s,r=a[s]){delete a[r.start];var u=r===e?e:e.concat(r);a[u.start=e.start]=o[u.end=r.end]=u}else if(r=o[s]){delete a[r.start],delete o[r.end];var u=e.concat(r.map(function(t){return~t}).reverse());a[u.start=e.start]=o[u.end=r.start]=u}else a[e.start]=o[e.end]=e;else if(e=a[s])if(delete a[e.start],e.unshift(t),e.start=i,r=o[i]){delete o[r.end];var f=r===e?e:r.concat(e);a[f.start=r.start]=o[f.end=e.end]=f}else if(r=a[i]){delete a[r.start],delete o[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);a[f.start=r.end]=o[f.end=e.end]=f}else a[e.start]=o[e.end]=e;else if(e=a[i])if(delete a[e.start],e.unshift(~t),e.start=s,r=o[s]){delete o[r.end];var f=r===e?e:r.concat(e);a[f.start=r.start]=o[f.end=e.end]=f}else if(r=a[s]){delete a[r.start],delete o[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);a[f.start=r.end]=o[f.end=e.end]=f}else a[e.start]=o[e.end]=e;else if(e=o[s])if(delete o[e.end],e.push(~t),e.end=i,r=o[i]){delete a[r.start];var u=r===e?e:e.concat(r);a[u.start=e.start]=o[u.end=r.end]=u}else if(r=a[i]){delete a[r.start],delete o[r.end];var u=e.concat(r.map(function(t){return~t}).reverse());a[u.start=e.start]=o[u.end=r.start]=u}else a[e.start]=o[e.end]=e;else e=[t],a[e.start=i]=o[e.end=s]=e});var c=[];for(var i in o)c.push(o[i]);return c}function e(e,r,a){function o(t){0>t&&(t=~t),(l[t]||(l[t]=[])).push(f)}function c(t){t.forEach(o)}function i(t){t.forEach(c)}function s(t){f=t,d[t.type](t.arcs)}var u=[];if(arguments.length>1){var f,l=[],d={LineString:c,MultiLineString:i,Polygon:i,MultiPolygon:function(t){t.forEach(i)}};"GeometryCollection"===r.type?r.geometries.forEach(s):s(r),l.forEach(3>arguments.length?function(t,e){u.push([e])}:function(t,e){a(t[0],t[t.length-1])&&u.push([e])})}else for(var h=0,v=e.arcs.length;v>h;++h)u.push([h]);return n(e,{type:"MultiLineString",arcs:t(e,u)})}function n(t,e){function n(t,e){e.length&&e.pop();for(var n,a=h[0>t?~t:t],o=0,c=a.length,i=0,s=0;c>o;++o)e.push([(i+=(n=a[o])[0])*u+l,(s+=n[1])*f+d]);0>t&&r(e,c)}function a(t){return[t[0]*u+l,t[1]*f+d]}function o(t){for(var e=[],r=0,a=t.length;a>r;++r)n(t[r],e);return e}function c(t){return t.map(o)}function i(t){return t=Object.create(t),t.coordinates=v[t.type](t),t}var s=t.transform,u=s.scale[0],f=s.scale[1],l=s.translate[0],d=s.translate[1],h=t.arcs,v={Point:function(t){return a(t.coordinates)},MultiPoint:function(t){return t.coordinates.map(a)},LineString:function(t){return o(t.arcs)},MultiLineString:function(t){return c(t.arcs)},Polygon:function(t){return c(t.arcs)},MultiPolygon:function(t){return t.arcs.map(c)}};return"GeometryCollection"===e.type?(e=Object.create(e),e.geometries=e.geometries.map(i),e):i(e)}function r(t,e){for(var n,r=t.length,a=r-e;--r>a;)n=t[a],t[a++]=t[r],t[r]=n}function a(t,e){for(var n=0,r=t.length;r>n;){var a=n+r>>>1;e>t[a]?n=a+1:r=a}return n}function o(t,e){function n(t,e){t.forEach(function(t){0>t&&(t=~t);var n=c[t]||(c[t]=[]);n[e]||(n.forEach(function(t){var n,r;r=a(n=i[e],t),n[r]!==t&&n.splice(r,0,t),r=a(n=i[t],e),n[r]!==e&&n.splice(r,0,e)}),n[e]=e)})}function r(t,e){t.forEach(function(t){n(t,e)})}function o(t,e){s[t.type](t.arcs,e)}var c=[],i=e.map(function(){return[]}),s={LineString:n,MultiLineString:r,Polygon:r,MultiPolygon:function(t,e){t.forEach(function(t){r(t,e)})}};return e.forEach(o),i}return{version:"0.0.8",mesh:e,object:n,neighbors:o}}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment