Skip to content Skip to sidebar Skip to footer

D3.js Shape Scaling/google Map Controls And Showing Markers Inside A Shape Area

Working on this application which I have broken down here. http://jsfiddle.net/pPMqQ/81/ In this example I want to show markers only inside the shape area allow for zoom of the m

Solution 1:

Fully working example: http://jsfiddle.net/PDf9G/5/

Edit: Now simplifies polygon before adding it to the map. Editing the polygon works as well.

First, the css and html: I moved the div called #canvas1 after the map and gave it absolute positioning and z-index = 0. I also gave the map the same absolute positioning to ensure that they always line up with each other, and gave it a z-index of 10.

When the draw button is clicked the canvas is moved to the front. The user can use it to draw free form using d3. When they are done the shape they drew is converted to a google maps polygon.

addShapeToBaseMap: function(divCoords) {
        var geoCoords = []
        for (var i = 0; i < divCoords.length; i++)
            geoCoords.push(overlay.getProjection().fromContainerPixelToLatLng(new google.maps.Point(Number(divCoords[i][0]), Number(divCoords[i][1]))));

        poly = new google.maps.Polygon({
            paths: geoCoords,
            strokeColor: '#FF0000',
            strokeOpacity: 0.8,
            strokeWeight: 2,
            fillColor: '#FF0000',
            fillOpacity: 0.35
        });
        poly.setMap(map);

Then we do do the hiding/showing of the markers. Using d3 this way is really silly and defeats the purpose. You need to add the google geometry library to your url to use this (&libraries=geometry). I'm sure there are faster ways and if you're dealing with large datasets you'll want to make this better.

for (var i = 0; i < data.length; i++) {
            if (!google.maps.geometry.poly.containsLocation(new google.maps.LatLng(data[i]['lat'], data[i]['lng']), poly)) {
                d3.select("#" + data[i]['name']).classed({'hide': true});
            } else {
                d3.select("#" + data[i]['name']).classed({'hide': false});
            }
        }

This works because when we appended the markers we added their name as the id on the marker element. The only reason I can see to do this is because the svg gives you better control over styling. Last:

        svg.select(".selection").remove()
        d3.select("#canvas1").classed({'front': false});
        $('.draw').removeClass('highlight');
    },

We remove the shape we drew from the drawing layer. If we don't do this, if the user moves the map and then turns the drawing layer back on, the shape will be in the wrong place. Then we move the canvas to the back and turn off the highlighting on the drawing button.

The edit function was taken from your most recent code. If the edit button or polygon is clicked the editing function is turned on on the polygon.

I would also recommend taking a look at Leaflet. The integration with d3 is a bit easier and you can have multiple svg layers, which would allow you to put the drawing layer as a map overlay instead of a separate div.

Solution 2:

geojson-utils is a node/browser javascript package that has a bunch of utilities for dealing with geojson paths.

One of the many things that it has is a very solid point in polygon algorithm designed for dealing with geojson paths.

You also might want to consider using Leaflet.js instead of Google Maps, it has a few more tools for going to and from geojson based data. It also has a lot of really useful tools already written like Leaflet.draw which has the code already needed to "draw" these paths on top of the maps.

Post a Comment for "D3.js Shape Scaling/google Map Controls And Showing Markers Inside A Shape Area"