0

enter image description here

Trying to build a location search app, that displays a google map - on the user drawing on the map it reveals any users that are located within that region.

I've also found this example - but it seems clunky/unsmooth - http://jsfiddle.net/pPMqQ/34/

http://jsfiddle.net/4xXQT/156/

var width = 960,
    height = 500;

var points = d3.range(1, 5).map(function(i) {
  return [i * width / 5, 50 + Math.random() * (height - 100)];
});

var dragged = null,
    selected = points[0];

var line = d3.svg.line();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("tabindex", 1);

svg.append("rect")
    .attr("width", width)
    .attr("height", height)
    .on("mousedown", mousedown);

svg.append("path")
    .datum(points)
    .attr("class", "line")
    .call(redraw);

d3.select(window)
    .on("mousemove", mousemove)
    .on("mouseup", mouseup)
    .on("keydown", keydown);

d3.select("#interpolate")
    .on("change", change)
  .selectAll("option")
    .data([
      "linear",
      "step-before",
      "step-after",
      "basis",
      "basis-open",
      "basis-closed",
      "cardinal",
      "cardinal-open",
      "cardinal-closed",
      "monotone"
    ])
  .enter().append("option")
    .attr("value", function(d) { return d; })
    .text(function(d) { return d; });

svg.node().focus();

function redraw() {
  svg.select("path").attr("d", line);

  var circle = svg.selectAll("circle")
      .data(points, function(d) { return d; });

  circle.enter().append("circle")
      .attr("r", 1e-6)
      .on("mousedown", function(d) { selected = dragged = d; redraw(); })
    .transition()
      .duration(750)
      .ease("elastic")
      .attr("r", 6.5);

  circle
      .classed("selected", function(d) { return d === selected; })
      .attr("cx", function(d) { return d[0]; })
      .attr("cy", function(d) { return d[1]; });

  circle.exit().remove();

  if (d3.event) {
    d3.event.preventDefault();
    d3.event.stopPropagation();
  }
}

function change() {
  line.interpolate(this.value);
  redraw();
}

function mousedown() {
  points.push(selected = dragged = d3.mouse(svg.node()));
  redraw();
}

function mousemove() {
  if (!dragged) return;
  var m = d3.mouse(svg.node());
  dragged[0] = Math.max(0, Math.min(width, m[0]));
  dragged[1] = Math.max(0, Math.min(height, m[1]));
  redraw();
}

function mouseup() {
  if (!dragged) return;
  mousemove();
  dragged = null;
}

function keydown() {
  if (!selected) return;
  switch (d3.event.keyCode) {
    case 8: // backspace
    case 46: { // delete
      var i = points.indexOf(selected);
      points.splice(i, 1);
      selected = points.length ? points[i > 0 ? i - 1 : 0] : null;
      redraw();
      break;
    }
  }
}
The Old County
  • 89
  • 13
  • 59
  • 129
  • I've found this example to, but it doesn't appear to work - http://gmaps-samples.googlecode.com/svn/trunk/poly/mymapstoolbar.html – The Old County Mar 15 '14 at 12:28
  • I've created a basic version of the demo - http://jsfiddle.net/pPMqQ/38/ - this allows the user to drag and draw a shape. I need to then conform the shape into a simpler polygon. – The Old County Mar 17 '14 at 16:08
  • The latest code - with no bugs - http://jsfiddle.net/pPMqQ/40/ – The Old County Mar 17 '14 at 16:15
  • It would be great if the drawn shape could then morph into a more basic polygon shape - resembling the drawn shape. - http://bl.ocks.org/mbostock/3081153 – The Old County Mar 17 '14 at 17:05
  • I've added a clear button and an edit button. The clear button works - but how to a) simplify the shape after the path is completed and b) to edit the shape - http://jsfiddle.net/pPMqQ/42/ - I have copied the code in place from this example to see how to reverse engineer the edit spline - http://bl.ocks.org/mbostock/4342190 – The Old County Mar 17 '14 at 17:20
  • Need a shape simplifier - something like this - but its not a geo map though - http://bl.ocks.org/mbostock/5732029 – The Old County Mar 18 '14 at 10:35
  • Another shape simplifier - http://bl.ocks.org/mbostock/6905926 – The Old County Mar 18 '14 at 10:40
  • I've cleaned up the drawing code - http://jsfiddle.net/pPMqQ/48/ – The Old County Mar 18 '14 at 10:53
  • I've tried to merge the codes together - so the shape simplifies after creation - http://jsfiddle.net/pPMqQ/52/ – The Old County Mar 18 '14 at 11:21

6 Answers6

3

enter image description here

The latest code "http://jsfiddle.net/Cbk9J/188/"


This demonstrates how to draw polygons and freehand shapes.

$(".drawfreehand").click(function(e) {
    e.preventDefault();
    console.log("drawfreehand");

    function drawFreeHand(){

        //the polygon
        that.newShape= new google.maps.Polyline({map:that.map,clickable:false});

        //move-listener
        var move = google.maps.event.addListener(that.map,'mousemove',function(e){
            that.newShape.getPath().push(e.latLng);
        });

        //mouseup-listener
        google.maps.event.addListenerOnce(that.map,'mouseup',function(e){


            google.maps.event.removeListener(move);

            var path= that.newShape.getPath();

            that.newShape.setMap(null);

            that.newShape=new google.maps.Polygon({map:that.map,path:path});


            google.maps.event.clearListeners(that.map.getDiv(), 'mousedown');

            enable()

            that.newShape.setEditable(false);
            that.revealInsidePolygon(that.newShape);

        });
    }

    function disable(){
        that.map.setOptions({
            draggable: false, 
            zoomControl: false, 
            scrollwheel: false, 
            disableDoubleClickZoom: false
        });
    }

    function enable(){
        that.map.setOptions({
            draggable: true, 
            zoomControl: true, 
            scrollwheel: true, 
            disableDoubleClickZoom: true
        });
    }

    disable()

    google.maps.event.addDomListener(that.map.getDiv(),'mousedown',function(e){
        drawFreeHand()
    });


});
The Old County
  • 89
  • 13
  • 59
  • 129
0

I've cleaned up the drawing code - and I've placed a function to try and simplify the shape. Having trouble though trying to achieve this though. The path becomes corrupt and becomes empty leaving just a single line.

Here is the code - http://jsfiddle.net/pPMqQ/53/

 simplifyShape: function(svg){
            console.log("simplifier");

            var area = 1,
                simplify = d3.geo.transform({
                    point: function(x, y, z) {
                        if (z >= area){
                            this.stream.point(x, y);
                        }
                    }
                });

            var path = d3.geo.path()
                .projection(simplify);          

            var shape = d3.select('.selection');
            var coordinates = shape.attr("d");

            area = 1.3;

            shape.attr("d", path)

        }
The Old County
  • 89
  • 13
  • 59
  • 129
  • I've tried to copy down the snowflake sample - but when the mouse goes over it - it disappears - http://jsfiddle.net/pPMqQ/54/ – The Old County Mar 18 '14 at 12:01
  • Here is a basic google map script. http://jsfiddle.net/pPMqQ/60/ – The Old County Mar 18 '14 at 12:18
  • Another lasso marker tool - http://www.daftlogic.com/sandbox-google-maps-marker-lasso-search-tool.htm – The Old County Mar 18 '14 at 12:36
  • I've merged the lasso and google map together - http://jsfiddle.net/pPMqQ/62/ – The Old County Mar 19 '14 at 10:28
  • Latest code - http://jsfiddle.net/pPMqQ/67/ – The Old County Mar 19 '14 at 10:47
  • Latest code with less bugs - http://jsfiddle.net/pPMqQ/71/ – The Old County Mar 19 '14 at 11:16
  • This is what I need - but how to implement it - http://stackoverflow.com/questions/13897556/how-do-i-reduce-the-coordinate-count-of-an-arbitrary-svg-path-without-losing-mu – The Old County Mar 19 '14 at 16:27
  • Integrated the simplifier code - http://jsfiddle.net/pPMqQ/77/ – The Old County Mar 19 '14 at 21:15
  • If I could merge all the code on to this as a base - that will be great. http://jsfiddle.net/Vjxpr/25/ - I've tried compiling the basic shape concept onto here - but its not showing up correctly – The Old County Mar 20 '14 at 16:23
  • This is the example that shows how its possible to create an overlay area and then append d3.js objects to it. But I am unsure how to append the generic drawing shapes to the map and get them to zoom/pan together as one unit - http://jsfiddle.net/Vjxpr/14/ – The Old County Mar 20 '14 at 16:25
  • If only I could use this as a base and merge the drawing code into place - I've started again - this time with just the markers on the map - in an overlay mode - but I am struggling to add the shape to the region - http://jsfiddle.net/Vjxpr/40/ – The Old County Mar 21 '14 at 11:36
0

Bringing it all together. A challenge.

  • The desired result waiting to happen

enter image description here enter image description here

Ok so I have the drawing and simplifying shape code merged.

I've also found a google map, d3 example - which places down markers in an overlay state on a google map. The markers appear to pan/zoom with the map accordingly.

I would like to bring the drawing shape code into place with the markers - so everything is zoomable/pannable as expected.

Once this is complete then I would like to work on - editing the shape - highlighting markers only inside the shape area.

http://jsfiddle.net/Vjxpr/49/

shapeSelector = {
        invoke: function(){
            var that = this;

            var width = 500;
            var height = 400;

            // An array to hold the coordinates
            // of the line drawn on each svg.
            var  coords = []
            this.line = d3.svg.line();

            this.drag = this.getDragBehaviours()

            this.svg = d3.select("#canvas1").append("svg")
            .attr({
                width: width,
                height: height
            }).call(that.drag);

            this.bindEvents();            

        }

handles the shape drawing features

googleMapHandler.invoke is handling the generate of the google map - and the marker positions/overlay settings.

The Old County
  • 89
  • 13
  • 59
  • 129
  • I'm able to draw on top of the map - but its not apart of it - if I place the div on the level of the markers. http://jsfiddle.net/Vjxpr/62/ can anyone supervise on this/come across similar problems? – The Old County Mar 21 '14 at 16:44
  • I've added the editing code from here -- http://stackoverflow.com/questions/22520620/d3-js-edit-existing-shape-path -- into here for now. http://jsfiddle.net/Vjxpr/75/ - its now possible to draw the shape and edit it, clear it - but I need it to be generated and interactive as part of the map - react if the map is scaled/zoomed/panned. – The Old County Mar 21 '14 at 17:11
  • Still struggling on this - http://jsfiddle.net/uF9PV/76/ – The Old County Mar 26 '14 at 17:09
0

enter image description here

In this example - I've ADDED a dummy shape to the map - similar way to the markers - but I am unsure at this stage - if its possible for the user to draw or edit/engage with the polygon.

I am trying to just move the polygon and rescale it in reference to the map.

http://jsfiddle.net/Cbk9J/91/

var shapelayer = d3.select(this.getPanes().overlayLayer).append("div")
                .attr("class", "shape");

^ add shape layer div

        //** shape area **//
        var paths = "M184,174L209,266L345,247L364,143L256,144 L184,174L256,144";

        var shapeArea = shapelayer.append("svg:svg")
        .attr("width", "100%") 
        .attr("height", "100%")   
        .append("path")
        .attr("d", paths)
        .each(transformshape)
        .attr("class", "selectioncomplete")


        function transformshape(d) {
            //d = new google.maps.LatLng(d.value.coordinates[1], d.value.coordinates[0]);
            //d = projection.fromLatLngToDivPixel(d);
            return d3.select(this)
            //.style("left", (d.x-25) + "px")
            //.style("top", (d.y-25) + "px");
        }

        //** shape area **//

add the shape area with dummy path data.

The Old County
  • 89
  • 13
  • 59
  • 129
  • I've found this example that doesn't use d3.js at all - http://jsfiddle.net/Cbk9J/95/ - but not familiar with creating polygons in this fashion – The Old County Mar 27 '14 at 16:23
  • Ok I've got it working with clear/edit polygon shape - http://jsfiddle.net/Cbk9J/102/ – The Old County Mar 27 '14 at 17:00
  • I've added a drawing shape feature - but it won't close when trying to click onto the last node - why is this. http://jsfiddle.net/Cbk9J/106/ – The Old County Mar 27 '14 at 17:18
  • Here is the add polygon code I've found - but still not sure how markers will be highlighted within the region - http://developers.cartodb.com/examples/editing-polygons.html – The Old County Mar 27 '14 at 17:20
  • Trying to initialize this - http://jsfiddle.net/Cbk9J/110/ -- using this as a base - http://gmaps-samples-v3.googlecode.com/svn/trunk/drawing/drawing-tools.html – The Old County Mar 27 '14 at 17:28
0

enter image description here

I am now using the general Google map drawing tools for this. As the panning/zooming is handled with the UI.

My outstanding issue now - is to show ONLY the markers in a given shape area. I've started to incorporate code that should hide/show markers - but I need some help to get this working.

http://jsfiddle.net/Cbk9J/139/

    setAllMap: function(map) {
        for (var i = 0; i < this.markers.length; i++) {
            this.markers[i].setMap(map);
        }
    },
    clearMarkers: function() {
        this.setAllMap(null);
    },
    showMarkers: function() {
        this.setAllMap(map);
    },
The Old County
  • 89
  • 13
  • 59
  • 129
  • Fixed the code to show/hide ALL markers - http://jsfiddle.net/Cbk9J/147/ - need to figure out - how to hide ALL markers - and SHOW only the ones inside the shape area... need to splice off the array somehow – The Old County Mar 28 '14 at 13:01
  • Found these examples that could be useful - http://jsfiddle.net/kaiser/wzcst/light/ http://stackoverflow.com/questions/6522484/google-maps-v3-check-if-point-exists-in-polygon http://stackoverflow.com/questions/5030127/marker-visibility-in-google-maps https://developers.google.com/maps/documentation/javascript/examples/marker-simple – The Old County Mar 28 '14 at 13:28
  • stackoverflow.com/questions/5030127/marker-visibility-in-google-maps – The Old County Mar 28 '14 at 15:49
  • ******* here is the latest demo - http://jsfiddle.net/Cbk9J/168/ - can now edit/add/clear - it highlights the markers only visible in the polygon region. - Would like to clean it up - so the user draws freehand first and then it morphs into a polygon. – The Old County Mar 28 '14 at 17:09
  • referencing this code to find markers inside a polygon -stackoverflow.com/questions/5030127/marker-visibility-in-google-maps – The Old County Mar 28 '14 at 17:10
  • Is it possible to use d3.js to create the freehand shape - it then gets converted into a polygon and then gets transcribed into a googlemap shape polygon - or is there a way to create a freehand shape that gets converted into a polygon directly on google maps? – The Old County Mar 28 '14 at 17:20
  • Here is some freehand example - need to apply it to my example now - http://jsfiddle.net/YsQdh/74/ – The Old County Mar 31 '14 at 11:53
  • http://jsfiddle.net/YsQdh/80/ - latest example of just the freehand drawing – The Old County Mar 31 '14 at 14:16
  • Improved listener - http://jsfiddle.net/YsQdh/88/ – The Old County Mar 31 '14 at 14:37
0

A working example of drawing freehand and converting to a polygon: http://jsfiddle.net/PDf9G/1/

Basically, you do the drawing the way you were already doing it. Keep the canvas div for drawing in back, when the button is clicked, move it to the front. When dragend is called convert the array of pixel coordinates you were keeping to lat and lng like this:

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]))));

Still needs a lot of cleanup. I was going to continue getting the d3 marker hiding working, but looks like you figured that out.

davkutalek
  • 396
  • 2
  • 14