Cibul Tech Blog - Fiddling with PHP, javascript and things

Drag and Drop two Markers linked with a line using Google Maps v3

ShareThis

In this article we’ll use the google maps v3 API to show two draggable markers on a map linked with a line. As the markers are dragged, we want the line position to be updated so that it appears to always be linked and we also want to an updated indicator displaying the distance between the two markers in kilometers.

To achieve this, we will use the Markers MVCObject properties to bind their positions to a method which will update the line and indicator as the Markers are dragged around the map.

Getting started by creating a Map

We start with an empty html page in which we will write our script. This page shows a full page map with over it a box in which we’ll keep an updated value of the distance between the markers. Here we go:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Distance widget</title>
    <style type="text/css">
      html, body { height: 100%; margin: 0; padding:0; }
      #map-canvas { height: 100%; width: 100%; }
      #distance-display { position: absolute; bottom: 0; left: 0; width: 100px; height: 20px; z-index: 1; background: white; text-align: center; padding: 10px;}
    </style>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
    <script type"text/javascript">
      $(function(){
       
        var map = new google.maps.Map($('#map-canvas'), {
          center: new google.maps.LatLng(48.860932,2.335925),
          zoom: 13,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });

      });
    </script>
  </head>
  <body>
    <div id="distance-display">distance</div>
    <div id="map-canvas"></div>
  </body>
</html>

With this we have a working full page map ready to receive some markers and a polyline. The libraries we are using are the google maps v3 (obviously) and the jquery library which we use to handle things on the page (like $(‘#map-canvas’)) and also to ensure that the javascript is not executed before the page is fully loaded (that is what the $(function(){}) is for).

Add two markers and a line

Now we add our two markers. One on the Louvre Museum and the second on the Eiffel Tower. Add this after the map declaration:

        var marker = new google.maps.Marker({
          map: map,
          position: new google.maps.LatLng(48.860932,2.335925),
          draggable: true,
          raiseOnDrag: false
        });

        var marker2 = new google.maps.Marker({
          map: map,
          position: new google.maps.LatLng(48.858221,2.29449),
          draggable: true,
          raiseOnDrag: false
        });

We also create the line, which is a Polyline with only two positions, one for each marker:

        var line = new google.maps.Polyline({
          path: [marker.getPosition(), marker2.getPosition()],
          map: map
        });

Calculate the distance between two markers

Before we start binding the markers with the line, we need to be able to calculate the distance between the markers. There used to be a practical method to do this in a previous version the the google maps API but it does not exist in the latest version (last time I checked anyways). So we will add it to the LatLng class so that we can easily determine the distance between two points. This methods uses the Haversine formula to calculate the distance. Add it before the $(function(){… line:

      google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
        if (newLatLng==undefined) return false;

        var dLat = (newLatLng.lat()-this.lat()) * Math.PI / 180;
        var dLon = (newLatLng.lng()-this.lng()) * Math.PI / 180;
        var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(this.lat() * Math.PI / 180 ) * Math.cos(newLatLng.lat() * Math.PI / 180 )* Math.sin(dLon/2) * Math.sin(dLon/2);
        return 6371000 * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
      }

With this, we can now simply determine the distance between two points. We apply it on the position of our markers at the end of the script:

$('#distance-display').html(Math.round(marker.getPosition().distanceFrom(marker2.getPosition())/10)/100 + ' km');

Here we are calculating the distance, rounding it up to have something in kilometers and we put it in our display

Tie everything up using MVCObject properties

For the time being, everything is initialized, the two markers are displayed with a line in between them, the distance between the two markers is displayed as well at the bottom of the screen, but nothing happens when one of the markers is dragged. What we need is to update the position of the line and update the distance display as the drag occurs. This is where the MVCObject properties of our objects are useful. Using them, we can bind attributes (in our case, the position of the markers) to methods which will update the line position and the distance display any time the attributes are changed.

First we create the method that will update the line and the display (before the $(function(){ again):

      var update_line_and_display = function(line, display, position1, position2){

        // update the line
        line.getPath().setAt(0, position1);
        line.getPath().setAt(1, position2);
       
        // update the display
       
        $(display).html(Math.round(position1.distanceFrom(position2)/10)/100 + ' km');
      }

We want that function to be called whenever the position of the markers change. As markers inherit the MVCObject, their attributes are bound to methods which if defined are triggered any time the attribute is changed. The names of these methods derive from the attribute. In our case, we use the position_changed method for each marker. We add this at the end of the script and we are done!

        marker.position_changed = function() {
          update_line_and_display(line, '#distance-display', this.get('position'), marker2.getPosition());
        }

        marker2.position_changed = function() {
          update_line_and_display(line, '#distance-display', marker.getPosition(), this.get('position'));
        }

You can see it working here.

Tags: , ,

6 Responses to “Drag and Drop two Markers linked with a line using Google Maps v3”

Thijs August 23rd, 2011 @ 12:32

Hi!

Thanks for this tut!

Would it not be nice to store such markers in a MySQL DB and create some sort of point to point travel from it ?

This should be possible I think.

Cheers,

Harpreet November 28th, 2012 @ 21:20

Hello,
I have a question and i could not find any answer or reference online.
I was wondering if i create two google maps with markers side by side in two div’s , can i drag one marker from first google map and drop it to the second google map.

I know we can create dragable markers but is it possible to drag them to the next googlemap div.

kaore November 28th, 2012 @ 22:42

You need to write a specific drag and drop script to do that, I don’t think google maps will allow you to take a marker out of a map.

location vacances guadeloupe gosier particulier May 16th, 2013 @ 21:57

It’s wonderful that you are getting ideas from this piece of writing as well as from our discussion made at this time.

bondage hog tied November 12th, 2013 @ 14:01

Heya! I just wanted to ask if you ever have any problems with hackers?
My last blog (wordpress) was hacked and I ended up losing several weeks of
hard work due to no backup. Do you have any solutions to
prevent hackers?

what is true love February 11th, 2014 @ 21:14

Wonderful article! We will be linking to this great article on our
website. Keep up the good writing.

Leave a Reply


RSS 2.0You can follow any responses to this entry through You can leave a response, ou trackback from your own site.