Google Maps - Animated Polyline -- Stop / Remove Animation - google-maps

I'm plotting a polyline on Google Maps API V3, from a GPX file.
On mouseover of that polyline, I have an animated dot, moving along the polyline, using function animateRoute();
Currently however, I don't have a way to remove the animated dot on mouseout, and as a result, if you mouseover, mouseout, mouseover etc, you end up with multiple animated dots moving along the same line.
Code snippet: (see full working URL below too)
var gmarkers = [];
function loadGPXFileIntoGoogleMap(map, filename,recordNum, name, hex_code) {
$.ajax({
type: "GET",
url: filename,
dataType: "xml",
success: function(xml) {
var points = [];
var bounds = new google.maps.LatLngBounds ();
$(xml).find("trkpt").each(function() {
var lat = $(this).attr("lat");
var lon = $(this).attr("lon");
if((lat != 0) && (lon != 0))
{
var p = new google.maps.LatLng(lat, lon);
points.push(p);
bounds.extend(p);
}
});
var strokeColor = "#ff0000";
var poly = new google.maps.Polyline({
path: points,
strokeColor: strokeColor,
strokeOpacity: 1,
strokeWeight: 4,
recordNum: recordNum,
});
poly.setMap(map);
google.maps.event.addListener(poly, 'mouseover', function() {
var start = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#00ff00',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var end = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var markerStart = new google.maps.Marker({
position: poly.getPath().getAt(0),
icon: start,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerStart);
var markerEnd = new google.maps.Marker({
position: poly.getPath().getAt(poly.getPath().getLength() - 1),
icon: end,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerEnd);
var icons = this.setOptions({
icons: [{
icon: {
path: google.maps.SymbolPath.CIRCLE,
strokeOpacity: 1,
strokeColor: "#000000",
strokeWeight: 2,
scale: 4
},
}]});
animateRoute(poly);
});
function animateRoute(line) {
var count = 0;
window.setInterval(function() {
count = (count + 1) % 200;
var icons = poly.get('icons');
icons[0].offset = (count / 2) + '%';
poly.set('icons', icons);
}, 60);
}
google.maps.event.addListener(poly, 'mouseout', function() {
removeMarkers();
});
// fit bounds to track
map.fitBounds(bounds);
}
});
}
function removeMarkers(){
for(i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
$(document).ready(function() {
var mapOptions = {
zoom: 17,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById("map"),
mapOptions);
loadGPXFileIntoGoogleMap(map, "cmsAdmin/uploads/blue_and_green_not_comfortable_.gpx","724","Example A","FFFF00");
loadGPXFileIntoGoogleMap(map, "cmsAdmin/uploads/taraweratrailrouterecce.gpx","431","Example B","4F4CBE");
});
Full working example:
https://www.wildthings.club/mapStack.php
Hover over the blue line and you'll see the animated dot.
Mouse off, and then after a few seconds hover again - a second dot will appear, and the first dot is still going.
Repeat and you'll soon have a bunch of jittery dots.
Ideally I'd like to remove all animated dots on mouseout.
Second option would be to not add a subsequent animated dot icon if there is already one on that polyLine (note there are multiple polyLines on the map).
Third option failing that would be to have the animated dot stop and remove once it reaches the end (position markerEnd) so at least it doesn't loop.
I have tried placing the icons into an array and then removing from there (like I have done with the gmarkers array and removeMarkers(), but no luck.
I also had a play with Animate google maps polyline but this just works with straight line point to point, rather than following a series of points from a GPX file.
Any help, most appreciated
Cheers

You should use the window.clearInterval() function to remove the interval you are using to animate the icon on the polyline. You should save the id when call window.setInterval() in animateRoute(). Here is a simple JSBin proof of concept adapted from the code on that website. In my code, I'm just simply using a global id variable, and updating that variable in animateRoute():
<!DOCTYPE html>
<html>
<head>
<title>Polyline path</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map {
height: 100%;
width: 100%;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var map;
var id;
var gmarkers = [];
var gmarkersicons = [];
function initMap() {
var mapOptions = {
zoom: 3,
mapTypeId: google.maps.MapTypeId.TERRAIN,
center: {lat: 9.291, lng: -157.821}
};
map = new google.maps.Map(document.getElementById("map"),
mapOptions);
var points = [
{lat: 37.772, lng: -122.214},
{lat: 21.291, lng: -157.821},
{lat: -18.142, lng: 178.431},
{lat: -27.467, lng: 153.027}
];
var poly = new google.maps.Polyline({
path: points,
strokeColor: "red",
strokeOpacity: 1,
strokeWeight: 4,
recordNum: "test"
});
poly.setMap(map);
google.maps.event.addListener(poly, 'mouseover', function() {
var start = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#00ff00',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var end = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var go = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#000000',
fillOpacity: 1,
strokeColor:'#fff',
strokeWeight: 4,
scale: 0.5
}
var markerStart = new google.maps.Marker({
position: poly.getPath().getAt(0),
icon: start,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerStart);
var markerEnd = new google.maps.Marker({
position: poly.getPath().getAt(poly.getPath().getLength() - 1),
icon: end,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerEnd);
var icons = this.setOptions({
icons: [{
icon: {
path: google.maps.SymbolPath.CIRCLE,
strokeOpacity: 1,
strokeColor: "#000000",
strokeWeight: 2,
scale: 4
},
}]});
this.setOptions({
strokeColor: "red",
scale: 1,
strokeWeight:15,
strokeOpacity:.6
});
var contentString = "Testing";
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, markerStart);
id = animateRoute(poly);
});
function animateRoute(line) {
var count = 0;
var id = window.setInterval(function() {
count = (count + 1) % 200;
var icons = poly.get('icons');
icons[0].offset = (count / 2) + '%';
poly.set('icons', icons);
}, 60);
return id;
}
google.maps.event.addListener(poly, 'mouseout', function() {
removeMarkers();
this.setOptions({strokeColor:"red",strokeWeight:4,strokeOpacity:1});
this.setOptions( { suppressMarkers: true } );
this.setOptions({
icons: [{}]});
window.clearInterval(id);
});
function removeMarkers(){
for(i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
}
$(document).ready(function() {
initMap();
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>

Related

draw route and automatically Zoom in/out Google map based on the path drawn in angular 6

I have plotted the map with latitude and longitude and drawn path between them and the map returns as follows:
but the expected result as follows:
following is the code is used to draw the route
for (var i = 0; i < mapData.length; i++) {
var latLng = new google.maps.LatLng(mapData[i].lat, mapData[i].lng);
myTrip.push(latLng);
// Push the 1st datapoint but don't draw the flightpath. Flightpath must be drawn only if more than one datapoint
if (i === 0) {
latLngPath.push(latLng);
}
if (i > 0) { // Push the datapoint and draw the flightpath.
latLngPath.push(latLng);
var flightPath = new google.maps.Polyline({
path: latLngPath,
strokeColor: "#F1575A",
strokeOpacity: 1,
strokeWeight: 4,
zIndex: 300,
icons: [{
icon: {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
strokeColor: "",
fillOpacity: 1,
scale: 3,
//offset: '100%'
},
repeat: '100px'
}]
});
flightPath.setMap(this.map);
// get the new datapoint
var lastLatLng = latLngPath.slice(-1)[0];
latLngPath = [];
latLngPath.push(lastLatLng);
}
}
Calculate the bounds of the polyline. Call map.fitBounds(bounds); with that bounds.
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < mapData.length; i++) {
var latLng = new google.maps.LatLng(mapData[i].lat, mapData[i].lng);
bounds.extend(latLng);
myTrip.push(latLng);
// Push the 1st datapoint but don't draw the flightpath. Flightpath must be drawn only if more than one datapoint
if (i === 0) {
latLngPath.push(latLng);
}
if (i > 0) { // Push the datapoint and draw the flightpath.
latLngPath.push(latLng);
var flightPath = new google.maps.Polyline({
path: latLngPath,
strokeColor: "#F1575A",
strokeOpacity: 1,
strokeWeight: 4,
zIndex: 300,
icons: [{
icon: {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
strokeColor: "",
fillOpacity: 1,
scale: 3,
},
repeat: '100px'
}]
});
flightPath.setMap(this.map);
// get the new datapoint
var lastLatLng = latLngPath.slice(-1)[0];
latLngPath = [];
latLngPath.push(lastLatLng);
}
}
map.fitBounds(bounds);
proof of concept fiddle
code snippet:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 3,
center: {
lat: 0,
lng: -180
},
mapTypeId: 'terrain'
});
var mapData = [
{lat: 36.7377981,lng: -119.78712469999999},
{lat: 36.1626638,lng: -86.78160159999999},
{lat: 32.7766642,lng: -96.79698789999998}
];
var myTrip = [];
var latLngPath = [];
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < mapData.length; i++) {
var latLng = new google.maps.LatLng(mapData[i].lat, mapData[i].lng);
bounds.extend(latLng);
myTrip.push(latLng);
// Push the 1st datapoint but don't draw the flightpath. Flightpath must be drawn only if more than one datapoint
if (i === 0) {
latLngPath.push(latLng);
}
if (i > 0) { // Push the datapoint and draw the flightpath.
latLngPath.push(latLng);
var flightPath = new google.maps.Polyline({
path: latLngPath,
strokeColor: "#F1575A",
strokeOpacity: 1,
strokeWeight: 4,
zIndex: 300,
icons: [{
icon: {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
strokeColor: "",
fillOpacity: 1,
scale: 3,
//offset: '100%'
},
repeat: '100px'
}]
});
flightPath.setMap(map);
// get the new datapoint
var lastLatLng = latLngPath.slice(-1)[0];
latLngPath = [];
latLngPath.push(lastLatLng);
}
}
map.fitBounds(bounds);
}
html,
body,
#map {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"></script>

Google Maps Changing Opacity of custom Line

This should have a simple answer but I can't seem to find it right now.
I have a polyline depicting a route as follows:
var lineSymbol2 = {
path: 'M 0,-1 0,1',
strokeOpacity: 1,
scale: 2
};
ORoute = new google.maps.Polyline({
path: ORouteLine,
strokeOpacity: 0,
strokeWeight: 1,
geodesic: true,
strokeColor: '#00FFFF',
zIndex: -10,
visible: false,
icons: [{
icon: lineSymbol2,
offset: '0',
repeat: '10px'
}],
map: map
});
It displays perfectly, but is there a way to change the opacity of the dashed line, eg to make it fade in over time, going from transparent to opaque? I have many lines showing the same dashed appearance. I should know the answer to this but I'm in a bit of a mind fog at present.
Btw, I've set the visible field to true elsewhere as I'm toggling the line
If you want to dynamically change the opacity of the symbol on the polyline, you need a setTimeout or setInterval function that does that.
var opacity = 0;
var intervalHandler = setInterval(function() {
if (opacity >= 1) {
opacity = 1;
var icons = ORoute.get("icons");
icons[0].icon.strokeOpacity = opacity;
ORoute.setOptions({icons:icons});
clearInterval(intervalHandler);
} else {
opacity += 0.01;
if (opacity >= 1) opacity = 1;
var icons = ORoute.get("icons");
icons[0].icon.strokeOpacity = opacity;
ORoute.setOptions({icons:icons});
}
}, 100)
proof of concept fiddle
code snippet:
var map;
var ORoute;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 3,
center: {
lat: 0,
lng: -180
},
mapTypeId: 'terrain'
});
var ORouteLine = [
{lat: 37.772, lng: -122.214},
{lat: 21.291, lng: -157.821},
{lat: -18.142, lng: 178.431},
{lat: -27.467, lng: 153.027}
];
var lineSymbol2 = {
path: 'M 0,-1 0,1',
strokeOpacity: 0,
scale: 2
};
ORoute = new google.maps.Polyline({
path: ORouteLine,
strokeOpacity: 0,
strokeWeight: 1,
geodesic: true,
strokeColor: '#000000',
zIndex: -10,
visible: true,
icons: [{
icon: lineSymbol2,
offset: '0',
repeat: '10px'
}],
map: map
});
var opacity = 0;
var intervalHandler = setInterval(function() {
if (opacity >= 1) {
opacity = 1;
var icons = ORoute.get("icons");
icons[0].icon.strokeOpacity = opacity;
ORoute.setOptions({icons:icons});
clearInterval(intervalHandler);
} else {
opacity += 0.01;
if (opacity >= 1) opacity = 1;
var icons = ORoute.get("icons");
icons[0].icon.strokeOpacity = opacity;
ORoute.setOptions({icons:icons});
}
}, 100)
}
html,
body, #map {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"></script>

Google map event listener for "grouped" polyline and markers

I am creating a google map for hiking. Each individual hike is displayed by a polyline. Each individual hike also has a start location and end location (at either end of the polyline). The start and end locations are each displayed by a marker (NOT a symbol). I have spent hours trying to add functionality such that when there is a mouseover event over EITHER the polyline OR either of the markers then both the polyline and both markers will "react" (in this case the opacity will change).
I have spent hours trying to find the solution. The closest I have got is the code below. In the code below, only if the mouse moves over the polyline will the polyline and markers react. But if the mouse moves over either marker, the polyline and markers do not react. I do understand my code is incorrect, but I cannot get closer to the solution.
I guess I somehow need to "group" each polyline and the respective 2 markers to one "object", "variable" or "layer" - but I simply cannot work this out.
Please note, the code below is simplified for only one marker (start location) per polyline (hike).
(At top of the code below is the gpx file from which the polyline and markers are created. Copy the gpx data into file and name google.gpx)
//start of the trimmed gpx data. Copy to new file and save as google.gpx
<lines>
<trkseg>
<trkpt lat="-33.879843" lng="151.225769"/>
<trkpt lat="-33.869843" lng="151.245769"/>
<trkpt lat="-33.859843" lng="151.255769"/>
</trkseg>
<trkseg>
<trkpt lat="-33.869843" lng="151.265769"/>
<trkpt lat="-33.869843" lng="151.275769"/>
</trkseg>
</lines>
//end of the trimmed gpx data
<style>
#map {
height: 100%;
}
</style>
<div id="map"></div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(-33.863276, 151.207977),
zoom: 12
});
downloadUrl('google.gpx', function(data) {
var xml = data.responseXML;
var trkseg = xml.querySelectorAll("trkseg");
for (var l = 0; l < trkseg.length; l++) {
var path = [],
trkPoints = trkseg[l].querySelectorAll('trkpt');
for (var p = 0; p < trkPoints.length; p++) {
var trkpt = trkPoints[p],
lat = parseFloat(trkpt.getAttribute("lat")),
lng = parseFloat(trkpt.getAttribute("lng")),
point = new google.maps.LatLng(lat, lng);
path.push(point);
}
var trkptMarker = trkPoints[0];
var startMarkerLat = parseFloat(trkptMarker.getAttribute("lat"));
var startMarkerLng = parseFloat(trkptMarker.getAttribute("lng"));
var startMarkerLatLng = {lat: startMarkerLat, lng: startMarkerLng};
var startIcon = 'https://stunninghikes.com/wp-content/uploads/2018/08/hike_start_pin_circular-e1534182115238.png';
var startIconImage = new google.maps.MarkerImage(startIcon);
var polyline = new google.maps.Polyline({
path: path,
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2,
startMarker: new google.maps.Marker({
position: startMarkerLatLng,
map: map,
opacity: 0.5,
icon: startIconImage,
zIndex: 10
}),
});
polyline.setMap(map);
google.maps.event.addListener(polyline, 'mouseover', function(event) {
this.get('startMarker').setOptions({
opacity: 1.0,
});
this.setOptions({
strokeColor: '#128934',
strokeOpacity: 1,
strokeWeight: 5,
});
});
google.maps.event.addListener(polyline, 'mouseout', function(event) {
this.get('startMarker').setOptions({
opacity: 0.5,
});
this.setOptions({
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2
});
});
}
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=GOOGLEKEY&&callback=initMap">
</script>
The simplest option given your existing code is to add the equivalent mouseover/mouseout listeners to the marker:
var startMarker = new google.maps.Marker({
position: startMarkerLatLng,
map: map,
opacity: 0.5,
icon: startIconImage,
zIndex: 10
});
var polyline = new google.maps.Polyline({
path: path,
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2,
map: map,
startMarker: startMarker
});
startMarker.set("polyline", polyline);
google.maps.event.addListener(polyline, 'mouseover', function(event) {
this.get('startMarker').setOptions({
opacity: 1.0,
});
this.setOptions({
strokeColor: '#128934',
strokeOpacity: 1,
strokeWeight: 5,
});
});
google.maps.event.addListener(polyline, 'mouseout', function(event) {
this.get('startMarker').setOptions({
opacity: 0.5,
});
this.setOptions({
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2
});
});
google.maps.event.addListener(startMarker, 'mouseover', function(event) {
this.setOptions({
opacity: 1.0,
});
this.get("polyline").setOptions({
strokeColor: '#128934',
strokeOpacity: 1,
strokeWeight: 5,
});
});
google.maps.event.addListener(startMarker, 'mouseout', function(event) {
this.setOptions({
opacity: 0.5,
});
this.get("polyline").setOptions({
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2
});
});
proof of concept fiddle
code snippet:
function initialize() {
var map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var bounds = new google.maps.LatLngBounds();
var xml = parseXml(xmlStr);
var trkseg = xml.querySelectorAll("trkseg");
for (var l = 0; l < trkseg.length; l++) {
var path = [],
trkPoints = trkseg[l].querySelectorAll('trkpt');
for (var p = 0; p < trkPoints.length; p++) {
var trkpt = trkPoints[p],
lat = parseFloat(trkpt.getAttribute("lat")),
lng = parseFloat(trkpt.getAttribute("lng")),
point = new google.maps.LatLng(lat, lng);
path.push(point);
bounds.extend(point);
}
var trkptMarker = trkPoints[0];
var startMarkerLat = parseFloat(trkptMarker.getAttribute("lat"));
var startMarkerLng = parseFloat(trkptMarker.getAttribute("lng"));
var startMarkerLatLng = {
lat: startMarkerLat,
lng: startMarkerLng
};
var startIcon = 'https://stunninghikes.com/wp-content/uploads/2018/08/hike_start_pin_circular-e1534182115238.png';
var startIconImage = new google.maps.MarkerImage(startIcon);
var startMarker = new google.maps.Marker({
position: startMarkerLatLng,
map: map,
opacity: 0.5,
icon: startIconImage,
zIndex: 10
});
var polyline = new google.maps.Polyline({
path: path,
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2,
map: map,
startMarker: startMarker
});
startMarker.set("polyline", polyline);
google.maps.event.addListener(polyline, 'mouseover', function(event) {
this.get('startMarker').setOptions({
opacity: 1.0,
});
this.setOptions({
strokeColor: '#128934',
strokeOpacity: 1,
strokeWeight: 5,
});
});
google.maps.event.addListener(polyline, 'mouseout', function(event) {
this.get('startMarker').setOptions({
opacity: 0.5,
});
this.setOptions({
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2
});
});
google.maps.event.addListener(startMarker, 'mouseover', function(event) {
this.setOptions({
opacity: 1.0,
});
this.get("polyline").setOptions({
strokeColor: '#128934',
strokeOpacity: 1,
strokeWeight: 5,
});
});
google.maps.event.addListener(startMarker, 'mouseout', function(event) {
this.setOptions({
opacity: 0.5,
});
this.get("polyline").setOptions({
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2
});
});
}
map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, "load", initialize);
function parseXml(str) {
if (window.ActiveXObject) {
var doc = new ActiveXObject('MicrosoftXMLDOM');
doc.loadXML(str);
return doc;
} else if (window.DOMParser) {
return (new DOMParser()).parseFromString(str, 'text/xml');
}
}
var xmlStr = '<lines><trkseg><trkpt lat="-33.879843" lng="151.225769"/><trkpt lat="-33.869843" lng="151.245769"/><trkpt lat="-33.859843" lng="151.255769"/></trkseg><trkseg><trkpt lat="-33.869843" lng="151.265769"/><trkpt lat="-33.869843" lng="151.275769"/></trkseg></lines>';
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>

After marker drag even polygon line doesn't change as per marker

I am working on google map polygon marker, I have predefined lat long array, and need to set polygon area, It is working fine for me, but when i drag the marker polygon line doesn't change, it should have to be change as i drag the marker, can anyone please help me how can i resolve this issue ? Here i have added my code, can anyone please help me ?
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Polygon Arrays</title>
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<input type="text" name="estimated_area" id="estimated_area" value="">
<input type="text" name="field_fj0d6" id="field_fj0d6" value="">
<script>
// This example creates a simple polygon representing the Bermuda Triangle.
// When the user clicks on the polygon an info window opens, showing
// information about the polygon's coordinates.
var map;
var infoWindow;
var markers = []; // Store Marker in an Array
function initMap() {
var lM = 't';
map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: {lat: 24.886, lng: -70.268},
mapTypeId: 'terrain'
});
// Define the LatLng coordinates for the polygon.
var triangleCoords = [
{lat: 25.774, lng: -80.190},
{lat: 18.466, lng: -66.118},
{lat: 32.321, lng: -64.757}
];
// Add Markers to Coordinates
for (var i = 0; i < triangleCoords.length; i++) {
var pos = triangleCoords[i];
var marker = new google.maps.Marker({
map: map,
position: pos,
draggable: true,
});
marker.setMap(map);
markers.push(marker);
var measure = {
mvcLine: new google.maps.MVCArray(),
mvcPolygon: new google.maps.MVCArray(),
mvcMarkers: new google.maps.MVCArray(),
line: null,
polygon: null
};
var latLng = pos;
var dot = marker;
/************** New Code ****************/
measure.mvcLine.push(latLng);
measure.mvcPolygon.push(latLng);
measure.mvcMarkers.push(dot);
var latLngIndex = measure.mvcLine.getLength() - 1;
google.maps.event.addListener(dot, "drag", function (evt) {
measure.mvcLine.setAt(latLngIndex, evt.latLng);
measure.mvcPolygon.setAt(latLngIndex, evt.latLng);
});
google.maps.event.addListener(dot, "dragend", function () {
console.log('<p>Marker dropped: Current Lat: ' + this.getPosition().lat() + ' Current Lng: ' + this.getPosition().lng() + '</p>');
drag = true;
setTimeout(function () {
drag = false;
}, 250);
if (measure.mvcLine.getLength() > 1) {
mC();
}
});
if (measure.mvcLine.getLength() > 1) {
if (!measure.line) {
measure.line = new google.maps.Polyline({
map: map,
clickable: false,
strokeColor: "#ff5b06",
strokeOpacity: 1,
strokeWeight: 3,
path: measure.mvcLine
});
}
if (measure.mvcPolygon.getLength() > 2) {
if (!measure.polygon) {
if (lM) {
measure.polygon = new google.maps.Polygon({
clickable: false,
map: map,
fillOpacity: 0.6,
fillColor: '#000000',
strokeOpacity: 0,
paths: measure.mvcPolygon
});
} else {
measure.polygon = new google.maps.Polygon({
clickable: false,
map: map,
fillOpacity: 0.6,
fillColor: '#000000',
strokeOpacity: 0,
paths: measure.mvcPolygon
});
}
}
}
}
if (measure.mvcLine.getLength() > 1) {
mC();
}
}
// Construct the polygon.
var bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: '#ff5b06',
strokeOpacity: 1,
strokeWeight: 3,
fillColor: '#000000',
fillOpacity: 0.6
});
bermudaTriangle.setMap(map);
}
function mR() {
if (measure.polygon) {
measure.polygon.setMap(null);
measure.polygon = null;
}
if (measure.line) {
measure.line.setMap(null);
measure.line = null
}
measure.mvcLine.clear();
measure.mvcPolygon.clear();
measure.mvcMarkers.forEach(function (elem, index) {
elem.setMap(null);
});
measure.mvcMarkers.clear();
document.getElementById('estimated_area').value = '';
document.getElementById('field_fj0d6').value = '';
}
function mC() {
var l = 0;
if (measure.mvcPolygon.getLength() > 1) {
l = google.maps.geometry.spherical.computeLength(measure.line.getPath());
}
var a = 0;
if (measure.mvcPolygon.getLength() > 2) {
a = google.maps.geometry.spherical.computeArea(measure.polygon.getPath());
}
if (a) {
var km = a / (1000 * 1000);
var feet = a * 10.7639104;
var yards = a * 1.19599005;
var acres = a * 0.000247105381;
var unit = " meters²";
var unit1 = " acres";
var unit2 = " km²";
var unit3 = " sq. ft.";
var unit4 = " yards²";
var area = feet.toFixed(0) + unit3;
//This is for update details in review tab
document.getElementById('estimated_area').value = parseFloat(area);
document.getElementById('field_fj0d6').value = String(area);
}
}
function rL() {
var test = measure.mvcLine.pop();
if (test) {
measure.mvcPolygon.pop();
var dot = measure.mvcMarkers.pop();
dot.setMap(null);
mC();
}
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYeDBDl-8Wx98Az55EbVnpvRfSIBbwxyE&callback=initMap">
</script>
</body>
</html>
You need to bind the vertices of the polygon to the markers.
var bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: '#ff5b06',
strokeOpacity: 1,
strokeWeight: 3,
fillColor: '#000000',
fillOpacity: 0.6
});
bermudaTriangle.setMap(map);
bermudaTriangle.binder = new MVCArrayBinder(bermudaTriangle.getPath());
for (var j = 0; j < bermudaTriangle.getPath().getLength(); j++) {
var mark = new google.maps.Marker({
position: bermudaTriangle.getPath().getAt(),
map: map,
draggable: true
});
mark.bindTo('position', bermudaTriangle.binder, (j).toString());
}
online example
proof of concept fiddle
code snippet:
var map;
var markers = []; // Store Marker in an Array
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: {
lat: 24.886,
lng: -70.268
},
mapTypeId: 'terrain'
});
// Define the LatLng coordinates for the polygon.
var triangleCoords = [{
lat: 25.774,
lng: -80.190
},
{
lat: 18.466,
lng: -66.118
},
{
lat: 32.321,
lng: -64.757
}
];
// Add Markers to Coordinates
// Construct the polygon.
var bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: '#ff5b06',
strokeOpacity: 1,
strokeWeight: 3,
fillColor: '#000000',
fillOpacity: 0.6
});
bermudaTriangle.setMap(map);
bermudaTriangle.binder = new MVCArrayBinder(bermudaTriangle.getPath());
for (var j = 0; j < bermudaTriangle.getPath().getLength(); j++) {
var mark = new google.maps.Marker({
position: bermudaTriangle.getPath().getAt(),
map: map,
draggable: true
});
mark.bindTo('position', bermudaTriangle.binder, (j).toString());
}
}
google.maps.event.addDomListener(window, 'load', initMap);
/*
* Use bindTo to allow dynamic drag of markers to refresh poly.
*/
function MVCArrayBinder(mvcArray) {
this.array_ = mvcArray;
}
MVCArrayBinder.prototype = new google.maps.MVCObject();
MVCArrayBinder.prototype.get = function(key) {
if (!isNaN(parseInt(key))) {
return this.array_.getAt(parseInt(key));
} else {
this.array_.get(key);
}
}
MVCArrayBinder.prototype.set = function(key, val) {
if (!isNaN(parseInt(key))) {
this.array_.setAt(parseInt(key), val);
} else {
this.array_.set(key, val);
}
}
html,
body,
#map {
height: 100%;
margin: 0;
padding: 0;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map"></div>

Hover on FusionTablesLayer in google maps

I have a FusionTablesLayer on my google map and it works great, but now I have to add a hover to it and I can figure out if it's possible. I've seen examples with a hover on different polygons, but I can't use this.
My layer:
layer = new google.maps.FusionTablesLayer({
map: map,
suppressInfoWindows: true,
heatmap: { enabled: false },
query: {
select: "col0",
from: key,
where: CreateQuery(shownMunicipalities)
},
styles: [{
polygonOptions: {
fillColor: '#eeeeee',
fillOpacity: 0.5,
strokeColor: '#000000',
strokeOpacity: 0.2,
strokeWeight: 2
}
}, {
where: CreateQuery(activeMunicipalities),
polygonOptions: {
fillColor: '#00FF00',
fillOpacity: 0.3
}
}],
options: {
styleId: 2,
templateId: 2
}
});
I've tried add a listener of the mouseover event, but this doesn't seem to do anythin.
google.maps.event.addListener(layer, 'mouseover', function (event) {
alert('hover');
});
Am I trying to do the impossible?
FusionTablesLayers don't support mouseover events, only click events.
(see this enhancement request)
There are implementations that add mouseover support (fusiontips) and this example from the FusionTables documentation.
code snippet (example from documentation):
var colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00'];
var map;
function initialize() {
var myOptions = {
zoom: 2,
center: new google.maps.LatLng(10, 0),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map-canvas'),
myOptions);
// Initialize JSONP request
var script = document.createElement('script');
var url = ['https://www.googleapis.com/fusiontables/v1/query?'];
url.push('sql=');
var query = 'SELECT name, kml_4326 FROM ' +
'1foc3xO9DyfSIF6ofvN0kp2bxSfSeKog5FbdWdQ';
var encodedQuery = encodeURIComponent(query);
url.push(encodedQuery);
url.push('&callback=drawMap');
url.push('&key=AIzaSyAm9yWCV7JPCTHCJut8whOjARd7pwROFDQ');
script.src = url.join('');
var body = document.getElementsByTagName('body')[0];
body.appendChild(script);
}
function drawMap(data) {
var rows = data['rows'];
for (var i in rows) {
if (rows[i][0] != 'Antarctica') {
var newCoordinates = [];
var geometries = rows[i][1]['geometries'];
if (geometries) {
for (var j in geometries) {
newCoordinates.push(constructNewCoordinates(geometries[j]));
}
} else {
newCoordinates = constructNewCoordinates(rows[i][1]['geometry']);
}
var randomnumber = Math.floor(Math.random() * 4);
var country = new google.maps.Polygon({
paths: newCoordinates,
strokeColor: colors[randomnumber],
strokeOpacity: 0,
strokeWeight: 1,
fillColor: colors[randomnumber],
fillOpacity: 0.3
});
google.maps.event.addListener(country, 'mouseover', function() {
this.setOptions({
fillOpacity: 1
});
});
google.maps.event.addListener(country, 'mouseout', function() {
this.setOptions({
fillOpacity: 0.3
});
});
country.setMap(map);
}
}
}
function constructNewCoordinates(polygon) {
var newCoordinates = [];
var coordinates = polygon['coordinates'][0];
for (var i in coordinates) {
newCoordinates.push(
new google.maps.LatLng(coordinates[i][1], coordinates[i][0]));
}
return newCoordinates;
}
google.maps.event.addDomListener(window, 'load', initialize);
#map-canvas {
height: 500px;
width: 600px;
}
<script src="https://maps.google.com/maps/api/js"></script>
<div id="map-canvas"></div>