GeoJason

Open source geo, web maps, etc.

Line Length and Polygon Area With Google Maps API V3

This is just a demo page showing how to use the geometry library for the Google Maps API. For more information, check out the blog post with details.

Click the map below to start drawing lines and polygons and to start measuring. Distance and area measurements are below the map as well as a link to reset the measurements.

Length (red line): 0 mt - Area (grey area): 0 mt² - Reset Measure

How it works

The relevant bits of code are below.

First and foremost, be sure that you’re requesting the geometry library from the Google Maps API by adding the &libraries=geometry URL parameter in your script tag. This library is not included with the default script download.

http://maps.googleapis.com/maps/api/js?v=3.6&sensor=false&libraries=geometry

We’ll create a global variable for our map and a measure object to keep things in order.

1
2
3
4
5
6
7
8
9
10
var map;

// Create a meausure object to store our markers, MVCArrays, lines and polygons
var measure = {
    mvcLine: new google.maps.MVCArray(),
    mvcPolygon: new google.maps.MVCArray(),
    mvcMarkers: new google.maps.MVCArray(),
    line: null,
    polygon: null
};

Now, we’ll create the map and listen for map clicks, sending these coordinates to a measureAdd function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// When the document is ready, create the map and handle clicks on it
jQuery(document).ready(function() {

    map = new google.maps.Map(document.getElementById("map"), {
        zoom: 15,
        center: new google.maps.LatLng(39.57592, -105.01476),
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        draggableCursor: "crosshair" // Make the map cursor a crosshair so the user thinks they should click something
    });

    google.maps.event.addListener(map, "click", function(evt) {
        // When the map is clicked, pass the LatLng obect to the measureAdd function
        measureAdd(evt.latLng);
    });

});

The measureAdd function does most of the heavy lifing here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
function measureAdd(latLng) {

    // Add a draggable marker to the map where the user clicked
    var marker = new google.maps.Marker({
        map: map,
        position: latLng,
        draggable: true,
        raiseOnDrag: false,
        title: "Drag me to change shape",
        icon: new google.maps.MarkerImage("/images/demos/markers/measure-vertex.png", new google.maps.Size(9, 9), new google.maps.Point(0, 0), new google.maps.Point(5, 5))
    });

    // Add this LatLng to our line and polygon MVCArrays
    // Objects added to these MVCArrays automatically update the line and polygon shapes on the map
    measure.mvcLine.push(latLng);
    measure.mvcPolygon.push(latLng);

    // Push this marker to an MVCArray
    // This way later we can loop through the array and remove them when measuring is done
    measure.mvcMarkers.push(marker);

    // Get the index position of the LatLng we just pushed into the MVCArray
    // We'll need this later to update the MVCArray if the user moves the measure vertexes
    var latLngIndex = measure.mvcLine.getLength() - 1;

    // When the user mouses over the measure vertex markers, change shape and color to make it obvious they can be moved
    google.maps.event.addListener(marker, "mouseover", function() {
        marker.setIcon(new google.maps.MarkerImage("/images/demos/markers/measure-vertex-hover.png", new google.maps.Size(15, 15), new google.maps.Point(0, 0), new google.maps.Point(8, 8)));
    });

    // Change back to the default marker when the user mouses out
    google.maps.event.addListener(marker, "mouseout", function() {
        marker.setIcon(new google.maps.MarkerImage("/images/demos/markers/measure-vertex.png", new google.maps.Size(9, 9), new google.maps.Point(0, 0), new google.maps.Point(5, 5)));
    });

    // When the measure vertex markers are dragged, update the geometry of the line and polygon by resetting the
    //     LatLng at this position
    google.maps.event.addListener(marker, "drag", function(evt) {
        measure.mvcLine.setAt(latLngIndex, evt.latLng);
        measure.mvcPolygon.setAt(latLngIndex, evt.latLng);
    });

    // When dragging has ended and there is more than one vertex, measure length, area.
    google.maps.event.addListener(marker, "dragend", function() {
        if (measure.mvcLine.getLength() > 1) {
            measureCalc();
        }
    });

    // If there is more than one vertex on the line
    if (measure.mvcLine.getLength() > 1) {

        // If the line hasn't been created yet
        if (!measure.line) {

            // Create the line (google.maps.Polyline)
            measure.line = new google.maps.Polyline({
                map: map,
                clickable: false,
                strokeColor: "#FF0000",
                strokeOpacity: 1,
                strokeWeight: 3,
                path:measure. mvcLine
            });

        }

        // If there is more than two vertexes for a polygon
        if (measure.mvcPolygon.getLength() > 2) {

            // If the polygon hasn't been created yet
            if (!measure.polygon) {

                // Create the polygon (google.maps.Polygon)
                measure.polygon = new google.maps.Polygon({
                    clickable: false,
                    map: map,
                    fillOpacity: 0.25,
                    strokeOpacity: 0,
                    paths: measure.mvcPolygon
                });

            }

        }

    }

    // If there's more than one vertex, measure length, area.
    if (measure.mvcLine.getLength() > 1) {
        measureCalc();
    }

}

The measureCalc function is doing the actual length and area measurements with the help of the Google Maps geometry library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function measureCalc() {

    // Use the Google Maps geometry library to measure the length of the line
    var length = google.maps.geometry.spherical.computeLength(measure.line.getPath());
    jQuery("#span-length").text(length.toFixed(1))

    // If we have a polygon (>2 vertexes in the mvcPolygon MVCArray)
    if (measure.mvcPolygon.getLength() > 2) {
        // Use the Google Maps geometry library to measure the area of the polygon
        var area = google.maps.geometry.spherical.computeArea(measure.polygon.getPath());
        jQuery("#span-area").text(area.toFixed(1));
    }

}

Lastly, we’ll want to wire up a link or button to clear the measurement objects and reset the values to 0.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function measureReset() {

    // If we have a polygon or a line, remove them from the map and set null
    if (measure.polygon) {
        measure.polygon.setMap(null);
        measure.polygon = null;
    }
    if (measure.line) {
        measure.line.setMap(null);
        measure.line = null
    }

    // Empty the mvcLine and mvcPolygon MVCArrays
    measure.mvcLine.clear();
    measure.mvcPolygon.clear();

    // Loop through the markers MVCArray and remove each from the map, then empty it
    measure.mvcMarkers.forEach(function(elem, index) {
        elem.setMap(null);
    });
    measure.mvcMarkers.clear();

    jQuery("#span-length,#span-area").text(0);

}

Comments