block by davo 5094476

5094476

Full Screen

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?

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<script src="//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>

topojson.v0.min.js

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}}();