Pravin Kumar
Pravin Kumar

Reputation: 693

Animated Marker Positions on PolyLine

I am using google maps API V3 and created some Animation of a Icon over a PolyLine.

My Code

var line;

function initialize() {
    var mapOptions = {
        center: new google.maps.LatLng(2.881766, 101.626877),
        zoom: 12,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    var map = new google.maps.Map(document.getElementById('map-canvas'),
        mapOptions);

    var lineCoordinates = [
        new google.maps.LatLng(2.86085, 101.6437),
        new google.maps.LatLng(2.87165, 101.6362),
        new google.maps.LatLng(2.880783, 101.6273),

        new google.maps.LatLng(2.891517, 101.6201),
        new google.maps.LatLng(2.8991, 101.6162), new google.maps.LatLng(2.915067, 101.6079)
    ];
    map.setCenter(lineCoordinates[0]);

    var lineSymbol = {
        path: google.maps.SymbolPath.CIRCLE,
        scale: 6,
        strokeColor: '#393'
    };

    line = new google.maps.Polyline({
        path: lineCoordinates,
        strokeColor: '#FF0000',
        strokeOpacity: 1.0,
        strokeWeight: 2,
        icons: [{
            icon: lineSymbol,
            offset: '100%'
        }],

        map: map
    });

    for (var i = 0; i < line.getPath().getLength(); i++) {
        var marker = new google.maps.Marker({
            icon: {
                url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle_blue.png",
                size: new google.maps.Size(7, 7),
                anchor: new google.maps.Point(4, 4)
            },
            position: line.getPath().getAt(i),
            title: line.getPath().getAt(i).toUrlValue(6),
            map: map
        });
    }

    animateCircle();
}


var id;

function animateCircle() {
    var count = 0;
    id = window.setInterval(function () {
        count = (count + 1) % 200;
        var icons = line.get('icons');
        icons[0].offset = (count / 2) + '%';
        line.set('icons', icons);
        if (line.get('icons')[0].offset == "99.5%") {
            icons[0].offset = '100%';
            line.set('icons', icons);
            window.clearInterval(id);
        }

    }, 20);
}

google.maps.event.addDomListener(window, 'load', initialize);

Fiddle Link here

There I have 6 points in the polyline. I want to create a Marker at each Point once the Animated Marker reaches the point.

Can anyone help me out in this context.

Thank you.

Upvotes: 3

Views: 5141

Answers (2)

seb
seb

Reputation: 123

I found @Anto Jurković's answer very useful, but the only issue of his solution is that it only works well with fairly straight lines (as he himself says at the end of his answer). I'd like to share my improvement to make it work with any type of line.

var lineSymbol = {
    path: google.maps.SymbolPath.CIRCLE,
    scale: 8,
    strokeColor: '#393'
};

// point distances from beginning in %
var sphericalLib = google.maps.geometry.spherical;

pointDistances = [];
var wholeDist = 0; 
// calculating the wholeDistance from point to point
for (var i = 0; i < lineCoordinates.length-1; i++) {
    wholeDist +=  sphericalLib.computeDistanceBetween(
        lineCoordinates[i+1], lineCoordinates[i]);
}

var currentDist = 0;

// <optional> to create a marker in the start point position
pointDistances[0] = 0;
// </optional>

for (var i = 0; i < lineCoordinates.length-1; i++) {
    // calculating the currentDistance from point to point
    currentDist +=  sphericalLib.computeDistanceBetween(
              lineCoordinates[i+1], lineCoordinates[i])

    // calculating the pointDistance as a percentage to compare it later with the offset
    pointDistances[i+1] = 100 * currentDist / wholeDist;
    console.log('pointDistances[' + i + ']: ' + pointDistances[i]);
}  

var myPolyline = new google.maps.Polyline({
    path: lineCoordinates,
    icons: [{
        icon: lineSymbol,
        offset: '100%'
    }],
    map: map,
    visible: true
});

var count = 0;
var offset;
var sentiel = -1;
var id;

id = window.setInterval(function() {
    count = (count + 1) % 200;
    offset = count /2;

    for (var i = pointDistances.length - 1; i > sentiel; i--) {
        if (offset > pointDistances[i]) {
            console.log('create marker');
            var marker = new google.maps.Marker({
                position: myPolyline.getPath().getAt(i),
                title: myPolyline.getPath().getAt(i).toUrlValue(6),
                map: map
            });

            sentiel++;
            break;
        }
    }

    // <optional> to create a marker in the last point position
    // Note: 99.5 is the last calculated offset, when the counter is 199
    if(offset == 99.5){
        var lastLinePoint = myPolyline.getPath().length - 1;
            var marker = new google.maps.Marker({
                position: myPolyline.getPath().getAt(lastLinePoint),
                title: myPolyline.getPath().getAt(lastLinePoint).toUrlValue(6),
                map: map
            });
        // to reset the sentinel if you want to repeat the iteration at its end 
        sentiel = -1;
    }
    // </optional>

    var icons = myPolyline.get('icons');
    icons[0].offset = (count / 2) + '%';
    myPolyline.set('icons', icons);
}, 150);

the edited example at jsbin

Upvotes: 0

Anto Jurković
Anto Jurković

Reputation: 11258

Here is one of possible solution using google.maps.geometry.spherical namespace method computeDistanceBetween(from:LatLng, to:LatLng, radius?:number). You have to include geometry library:

<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=geometry"></script>

computeDistanceBetween() is used to calculate distance between points and convert them to percentages of whole distance:

// point distances from beginning in %
var sphericalLib = google.maps.geometry.spherical;

pointDistances = [];
var pointZero = lineCoordinates[0];
var wholeDist = sphericalLib.computeDistanceBetween(
                    pointZero,
                    lineCoordinates[lineCoordinates.length - 1]);

for (var i = 0; i < lineCoordinates.length; i++) {
    pointDistances[i] = 100 * sphericalLib.computeDistanceBetween(
                                    lineCoordinates[i], pointZero) / wholeDist;
    console.log('pointDistances[' + i + ']: ' + pointDistances[i]);
}

Function animateCircle() is changed so that marker is created when offset is greater then offset of specific point:

var id;
function animateCircle() {
    var count = 0;
    var offset;
    var sentiel = -1;

    id = window.setInterval(function () {
        count = (count + 1) % 200;
        offset = count /2;

        for (var i = pointDistances.length - 1; i > sentiel; i--) {
            if (offset > pointDistances[i]) {
                console.log('create marker');
                var marker = new google.maps.Marker({
                    icon: {
                        url:"https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle_blue.png",
                        size: new google.maps.Size(7,7),
                        anchor: new google.maps.Point(4,4)
                    },
                    position: line.getPath().getAt(i),
                    title: line.getPath().getAt(i).toUrlValue(6),
                    map: map
                });

                sentiel++;
                break;
            }
        }
...

See example at jsbin.

Note: this example uses almost straight line. If you have different example then it would be better to calculate distance from point to point and get the sum of all of them. So, offset calculation should be little different: see example at jsbin.

Upvotes: 3

Related Questions