Animate a curved path/route between two geo-localized points markers using the Google map js v3 API. Here is the relevant part of the path animation. Modify based on your requirements. Hope it helps.
// ... init the google maps as usual then:
maps.setTwinMarker(
{ id: "a", lat: 34.0380, lng: -118.3086, bubble: 'a div defining your marker' },
{ id: "b", lat: 34.0224, lng: -118.4871, bubble: 'a div defining your marker' }
);
// ...
setTwinMarker = function( ma, mb )
{
this.clear();
this.addMarker( ma.lat, ma.lng, ma.id, ma.bubble, true );
this.addMarker( mb.lat, mb.lng, mb.id, mb.bubble, true );
this.fit();
function larp( a, b, t )
{
return { lat: a.lat + ( b.lat - a.lat ) * t, lng: a.lng + ( b.lng - a.lng ) * t };
}
function getBezier( points, t )
{
var ab = larp( points[ 0 ], points[ 1 ], t );
var bc = larp( points[ 1 ], points[ 2 ], t );
var cd = larp( points[ 2 ], points[ 3 ], t );
var abbc = larp( ab, bc, t );
var bccd = larp( bc, cd, t );
return larp( abbc, bccd, t );
}
function getBezierHandles( p0, p1 )
{
// a, b points are perpendicular to q1, q3 which are on line connecting p0 and p1.
// slope between two points : ( y2 - y1 ) / (x2 - x1 ).
// to get perpendicular slope use, reciprocal slope function: -(x2 - x1 ) / ( y2 - y1 )
// curvature is distance between q1 and a; q3 and b;
//
// a b
// | |
// | |
// p0-----q1-----q2-----q3-----p1
var q2 = { lat: (p0.lat + p1.lat) / 2, lng: (p0.lng + p1.lng) / 2 };
var q1 = { lat: (p0.lat + q2.lat) / 2, lng: (p0.lng + q2.lng) / 2 };
var q3 = { lat: (q2.lat + p1.lat) / 2, lng: (q2.lng + p1.lng) / 2 };
var dLat = p1.lat - p0.lat;
var dLng = p1.lng - p0.lng;
var curvature = 0.15;
if( p0.lng > p1.lng )
{
return {
a: { lat: q1.lat + ( -dLng * curvature ), lng: q1.lng + ( dLat * curvature ) },
b: { lat: q3.lat + ( -dLng * curvature ), lng: q3.lng + ( dLat * curvature ) }
};
}
else
{
return {
a: { lat: q1.lat - ( -dLng * curvature ), lng: q1.lng + ( dLat * curvature ) },
b: { lat: q3.lat - ( -dLng * curvature ), lng: q3.lng + ( dLat * curvature ) }
};
}
}
function getLatLngPath( p0, p1 )
{
var handles = getBezierHandles( p0, p1 );
var points = [ p0, handles.a, handles.b, p1 ];
var path = [];
var sections = 40;
for( var t = 0; t <= sections; ++t )
{
var b = getBezier( points, t / sections );
path.push( new google.maps.LatLng( b.lat, b.lng ) );
}
return path;
}
var path = getLatLngPath( { lat: ma.lat, lng: ma.lng }, { lat: mb.lat, lng: mb.lng } );
var dotIcon = {
path: 'M -1,1 0,0 1,1',
scale: 5,
strokeWeight: 1.5,
strokeColor: '#232e40'
};
_polyDot = new google.maps.Polyline( {
path: path,
map: _map,
geodesic: false,
strokeOpacity: 1,
strokeWeight: 0,
strokeColor: 'transparent',
icons: [ { icon: dotIcon, repeat: '80px' } ]
} );
this.animate();
};
// ...
animate = function()
{
var count = 0;
_polyDotAnimTimerId = window.setInterval( function()
{
count = ++count % 80;
if( _polyDot )
{
var icons = _polyDot.get( 'icons' );
icons[ 0 ].offset = count + 'px';
_polyDot.set( 'icons', icons );
}
}, 40 );
};
// ...
.bubble {
background:#232e40;
border-radius:50%;
height:20px;
width:20px;
position:relative;
bottom:-10px;
}