Converting Google maps dynamic and resizing circle v2 to v3 - google-maps

http://web3o.blogspot.in/2010/05/google-maps-dynamically-movable-and.html
From the above link i got V2 google maps code which is working fine, but not able to import V3 beach markers so i convert the draw circle, circle resize and circle center marker function to V3 and i am not getting the circle in the maps where as i am getting all the marker, beach marker flags etc.
Following is the code, Kindly help me in fixing this, save the code as HTML file and execute in the browser.
I am having issue in the drawCircle function were the circle is not drawn on the Map.
<!--<script src="http://maps.google.com/maps?file=api&v=2&key=AIzaSyDAAkI8Q59oV68_F8r8hL66vlhCu9cWNQM&sensor=true" type="text/javascript"></script>-->
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&v=3&libraries=geometry"></script>
<script type="text/javascript">
/* Developed by: Abhinay Rathore [web3o.blogspot.com] */
//Global variables
var map;
var circle = [];
//circle[0] = {map_center: new GLatLng(38.903843, -94.680096),
// };
var Cobj = [];//{'mp_center':
var frndmap = [];
var bounds = new google.maps.LatLngBounds; //Circle Bounds
var map_center = new google.maps.LatLng(12.9735597, 77.6410402);
frndmap = [['Mahesh Pusala', 12.9735521, 77.6410431, 1], ['Bala Sundar', 12.9735567, 77.6410489, 2]];
var Circle=[];//null,null];//Circle object
var CirclePoints = []; //Circle drawing points
var CircleCenterMarker, CircleResizeMarker = [];//null,null];
var circle_moving = false; //To track Circle moving
var circle_resizing = false; //To track Circle resizing
var radius = []; //1 km
//var min_radius = 0.5; //0.5km
//var max_radius = 50; //5km
//Circle Marker/Node icons
/*var redpin = new google.maps.MarkerImage(); //Red Pushpin Icon
redpin.image = "http://maps.google.com/mapfiles/ms/icons/red-pushpin.png";
redpin.iconSize = new google.maps.Size(32, 32);
redpin.iconAnchor = new google.maps.Point(10, 32);*/
var redpin = new google.maps.MarkerImage('http://maps.google.com/mapfiles/ms/icons/red-pushpin.png',
// This marker is 20 pixels wide by 32 pixels tall.
new google.maps.Size(32, 32),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is the base of the flagpole at 0,32.
new google.maps.Point(10, 32));
/*var bluepin = new google.maps.MarkerImage(); //Blue Pushpin Icon
bluepin.image = "http://maps.google.com/mapfiles/ms/icons/blue-pushpin.png";
bluepin.iconSize = new google.maps.Size(32, 32);
bluepin.iconAnchor = new google.maps.Point(10, 32);*/
var bluepin = new google.maps.MarkerImage('http://maps.google.com/mapfiles/ms/icons/blue-pushpin.png',
// This marker is 20 pixels wide by 32 pixels tall.
new google.maps.Size(32, 32),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is the base of the flagpole at 0,32.
new google.maps.Point(10, 32));
function initialize() { //Initialize Google Map
//for(c in circle) {
//map = new GMap2(document.getElementById("map_canvas")); //New GMap object
var myOptions = {
zoom: 14,
center: map_center,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
/*addCircleResizeMarker(map_center[0], '0');
addCircleCenterMarker(map_center[0],'0');
drawCircle(map_center[0], radius, '0');
addCircleCenterMarker(map_center[1],'1');
addCircleResizeMarker(map_center[1], '1');
drawCircle(map_center[1], radius, '1');
*/
for(i=0; i<3; i++) {
Cobj[i] = {'map_center':new google.maps.LatLng(12.9735597+i, 77.6410402+i),
'Circle':null,
'CircleResizeMarker':null,
'radius':24+i
};
addCircleCenterMarker(i);
addCircleResizeMarker(i);
drawCircle(Cobj[i].map_center,Cobj[i].radius, i);
}
map.setCenter(map_center);
setMarkers(map, frndmap);
}
// Adds Circle Center marker
//radius
function addCircleCenterMarker(iii) {
point = Cobj[iii].map_center;
var markerOptions = { icon: bluepin, draggable: true };
CircleCenterMarker = new google.maps.Marker(point, markerOptions);
CircleCenterMarker.setMap(map); //Add marker on the map
//X= new google.maps.event();
google.maps.event.addListener(CircleCenterMarker, 'dragstart', function() { //Add drag start event
circle_moving = true;
});
google.maps.event.addListener(CircleCenterMarker, 'drag', function(point) { //Add drag event
drawCircle(point,Cobj[iii].radius, iii);
});
google.maps.event.addListener(CircleCenterMarker, 'dragend', function(point) { //Add drag end event
console.log(point.lng());
circle_moving = false;
drawCircle(point, Cobj[iii].radius, iii);
});
}
// Adds Circle Resize marker
// map_center
function addCircleResizeMarker(iii) {
point = Cobj[iii].map_center;
var resize_icon = new google.maps.MarkerImage(redpin);
resize_icon.maxHeight = 0;
var markerOptions = { icon: resize_icon, draggable: true };
Cobj[iii].CircleResizeMarker = new google.maps.Marker(point, markerOptions);
Cobj[iii].CircleResizeMarker.setMap(map); //Add marker on the map
google.maps.event.addListener(Cobj[iii].CircleResizeMarker, 'dragstart', function() { //Add drag start event
circle_resizing = true;
});
google.maps.event.addListener(Cobj[iii].CircleResizeMarker, 'drag', function(point) { //Add drag event
var new_point = new google.maps.LatLng(Cobj[iii].map_center.lat(), point.lng()); //to keep resize marker on horizontal line
var new_radius = new_point.distanceFrom(Cobj[iii].map_center) / 1000; //calculate new radius
//if (new_radius < min_radius) new_radius = min_radius;
//if (new_radius > max_radius) new_radius = max_radius;
drawCircle(Cobj[iii].map_center, new_radius, iii);
});
google.maps.event.addListener(Cobj[iii].CircleResizeMarker, 'dragend', function(point) { //Add drag end event
circle_resizing = false;
var new_point = new google.maps.LatLng(Cobj[iii].map_center.lat(), point.lng()); //to keep resize marker on horizontal line
var new_radius = new_point.distanceFrom(Cobj[iii].map_center) / 1000; //calculate new radius
//if (new_radius < min_radius) new_radius = min_radius;
//if (new_radius > max_radius) new_radius = max_radius;
console.log(new_radius);
drawCircle(Cobj[iii].map_center, new_radius, iii);
});
}
//Draw Circle with given radius and center
function drawCircle(center,new_radius, iii) {
//Circle = Circle[iii];
//Circle Drawing Algorithm from: http://koti.mbnet.fi/ojalesa/googlepages/circle.htm
//Number of nodes to form the circle
var nodes = new_radius * 40;
if(new_radius < 1) nodes = 40;
//calculating km/degree
xx = new google.maps.LatLng(center.lat() + 0.1, center.lng());
yy = new google.maps.LatLng(center.lat() , center.lng()+0.1);
var latConv = google.maps.geometry.spherical.computeDistanceBetween(center,xx)/100;//center.distanceFrom(new google.maps.LatLng(center.lat() + 0.1, center.lng())) / 100;
var lngConv = google.maps.geometry.spherical.computeDistanceBetween(center,yy)/100;//center.distanceFrom(new google.maps.LatLng(center.lat(), center.lng() + 0.1)) / 100;
CirclePoints = [];
var step = parseInt(360 / nodes) || 10;
var counter = 0;
for (var i = 0; i <= 360; i += step) {
var cLat = center.lat() + (new_radius / latConv * Math.cos(i * Math.PI / 180));
var cLng = center.lng() + (new_radius / lngConv * Math.sin(i * Math.PI / 180));
var point = new google.maps.LatLng(cLat, cLng);
CirclePoints.push(point);
counter++;
}
Cobj[iii].CircleResizeMarker.setPosition(CirclePoints[Math.floor(counter / 4)]); //place circle resize marker
CirclePoints.push(CirclePoints[0]); //close the circle polygon
if (Cobj[iii].Circle) {
//map.removeOverlay(Cobj[iii].Circle);
marker.setMap(null);
} //Remove existing Circle from Map
var fillColor = (circle_resizing || circle_moving) ? 'red' : 'blue'; //Set Circle Fill Color
console.log(CirclePoints);
Cobj[iii].Circle = new google.maps.Polygon(CirclePoints, '#FF0000', 2, 1, fillColor, 0.2); //New GPolygon object for Circle
//Cobj[iii].Circle.setMap(map); //Add Circle Overlay on the Map
//radius = new_radius; //Set global radius
//Cobj[iii].map_center = center; //Set global map_center
//if (!circle_resizing && !circle_moving)
//{
//Fit the circle if it is nor moving or resizing
// fitCircle(Cobj[iii].Circle);
//Circle drawing complete trigger function goes here
//}
}
//Fits the Map to Circle bounds
function fitCircle(Circle) {
bounds = Circle.getBounds();
map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
}
function setMarkers(map, locations) {
// Add markers to the map
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.
// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.
var image = {
url: 'images/beachflag.png',
// This marker is 20 pixels wide by 32 pixels tall.
size: new google.maps.Size(20, 32),
// The origin for this image is 0,0.
origin: new google.maps.Point(0,0),
// The anchor for this image is the base of the flagpole at 0,32.
anchor: new google.maps.Point(0, 32)
};
var shadow = {
url: 'images/beachflag_shadow.png',
// The shadow image is larger in the horizontal dimension
// while the position and offset are the same as for the main image.
size: new google.maps.Size(37, 32),
origin: new google.maps.Point(0,0),
anchor: new google.maps.Point(0, 32)
};
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var shape = {
coord: [1, 1, 1, 20, 18, 20, 18 , 1],
type: 'poly'
};
for (var i = 0; i < locations.length; i++) {
var beach = locations[i];
var myLatLng = new google.maps.LatLng(beach[1], beach[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
shadow: shadow,
icon: image,
shape: shape,
title: beach[0],
zIndex: beach[3]
});
}
}
</script>
<body onload="initialize()">
<div id="map_canvas" style="width:100%; height:450px"></div>
</body>

Your drawCircle function has
Cobj[iii].Circle = new google.maps.Polygon(CirclePoints, '#FF0000', 2, 1, fillColor, 0.2); //New GPolygon object for Circle
Personally I'd rather use google.maps.Circle instead, much simpler
https://developers.google.com/maps/documentation/javascript/reference#Circle

Related

Draw polyline whenever Animating the vehicle

Application running successfully with Animation features.
Below code animating a vehicle Icon through a polyline.
In below code, How to draw a poly line when vehicle animate through the route?Like this Jsfiddle
Red Line at the time of animating
I tried but always line is showing before start animation.
Need existing polylines and new line at vehicle movement.
var step = 50; // 5; // metres
var tick = 100; // milliseconds
var eol;
var k = 0;
var stepnum = 0;
var speed = "";
var lastVertex = 1;
//=============== animation functions ======================
function updatePoly(d) {
// Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow
if (poly2.getPath().getLength() > 20) {
poly2 = new google.maps.Polyline([polyline.getPath().getAt(lastVertex - 1)]);
// map.addOverlay(poly2)
}
if (polyline.GetIndexAtDistance(d) < lastVertex + 2) {
if (poly2.getPath().getLength() > 1) {
poly2.getPath().removeAt(poly2.getPath().getLength() - 1);
}
poly2.getPath().insertAt(poly2.getPath().getLength(), polyline.GetPointAtDistance(d));
} else {
poly2.getPath().insertAt(poly2.getPath().getLength(), endLocation.latlng);
}
}
function animate(d) {
if (d > eol) {
map.panTo(endLocation.latlng);
Animationmarker.setPosition(endLocation.latlng);
return;
}
var p = polyline.GetPointAtDistance(d);
map.panTo(p);
var lastPosn = Animationmarker.getPosition();
Animationmarker.setPosition(p);
var heading = google.maps.geometry.spherical.computeHeading(lastPosn, p);
icon.rotation = heading;
Animationmarker.setIcon(icon);
updatePoly(d);
tick = document.getElementById('<%= DrpAnimateSpeed.ClientID%>').value;
// alert(tick);
timerHandle = setTimeout("animate(" + (d + step) + ")", tick);
currentDistance = d + step;
}
function startAnimation() {
if (timerHandle) {
clearTimeout(timerHandle);
}
if (Animationmarker) {
Animationmarker.setMap(null);
}
eol = polyline.Distance();
map.setCenter(polyline.getPath().getAt(0));
Animationmarker = new google.maps.Marker({
position: polyline.getPath().getAt(0),
map: map,
icon: icon
});
poly2 = new google.maps.Polyline({
path: [polyline.getPath().getAt(0)],
strokeColor: "orange",
strokeWeight: 20
});
//map.addOverlay(poly2);
setTimeout("animate(50)", 2000); // Allow time for the initial map display
}
Red -Blue line difference Added this below code in animate() function and drawing another polyline when animated icon is moving.
Here the problem I am facing is, Some places red line is showing like image..In the image blue line is based on direction service route. and red is the one drawing based on the below code.How to solve this?
///Ad[enter image description here][1]ded
HighlightPoly = new google.maps.Polyline({
path: [],
strokeColor: 'red',
strokeWeight: 4
});
var codeStr = [];
const path = [lastPosn, p];
HighlightPoly.setPath(path);
HighlightPoly.setMap(map);
//////////////////////

Add custom background image to draggable polygons in google map?

I want to add custom background image to my draggable polygons in google Map. I've already used the Polygon class to make a draggable polygon that can also rotate. I want to add background image to it. I've read other posts and they mentioned "custom overlay" but that is a fixed image on the map which doesn't support dragging/rotation. How should I go about doing this?
Update:
I created a custom layer with my image and added it to the map with the same coordinates as the polygon. Whenever the bounds of my polygon change, I will also update my custom layer so they always overlap. However, as shown in the gif, https://imgur.com/3oaktIY, the polygon and the image are not in sync and there's a delay.
Is there any other way to do it?
Did not find solutions online so I figured it out myself with this working demo: draggable polygon with image. I made it with a combination of custom overlay and normal polygon library. You can click on the polygon to rotate and drag it around.
plz see jsfiddle
code snippet:
// This example adds hide() and show() methods to a custom overlay's prototype.
// These methods toggle the visibility of the container <div>.
// Additionally, we add a toggleDOM() method, which attaches or detaches the
// overlay to or from the map.
var overlay;
USGSOverlay.prototype = new google.maps.OverlayView();
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 20,
center: {
lat: 33.678,
lng: -116.243
},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
var rectangle = new google.maps.Rectangle({
strokeColor: 'red',
strokeOpacity: 0,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0,
map: map,
bounds: calcBounds(map.getCenter(), new google.maps.Size(2.7, 20))
});
var rectPoly = createPolygonFromRectangle(rectangle); //create a polygom from a rectangle
rectPoly.addListener('click', function(e) {
rotatePolygon(rectPoly, 10);
rectPoly.rotation += 10;
console.log(rectPoly.rotation)
overlay.div_.style.transform = 'rotate(' + rectPoly.rotation + 'deg)';
});
rectPoly.addListener('drag', function() {
console.log('Drag end!');
let bounds = new google.maps.LatLngBounds();
var i;
// The Bermuda Triangle
let polygonCoords = rectPoly.getPath().getArray();
for (i = 0; i < polygonCoords.length; i++) {
bounds.extend(polygonCoords[i]);
}
// The Center of the Bermuda Triangle - (25.3939245, -72.473816)
center = bounds.getCenter();
overlay.bounds_ = calcBounds(center, new google.maps.Size(2.7, 20))
overlay.draw();
});
function calcBounds(center, size) {
var n = google.maps.geometry.spherical.computeOffset(center, size.height / 2, 0).lat(),
s = google.maps.geometry.spherical.computeOffset(center, size.height / 2, 180).lat(),
e = google.maps.geometry.spherical.computeOffset(center, size.width / 2, 90).lng(),
w = google.maps.geometry.spherical.computeOffset(center, size.width / 2, 270).lng();
return new google.maps.LatLngBounds(new google.maps.LatLng(s, w),
new google.maps.LatLng(n, e))
}
var srcImage = 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/talkeetna.png';
overlay = new USGSOverlay(rectangle.bounds, srcImage, map, rectPoly);
// The custom USGSOverlay object contains the USGS image,
// the bounds of the image, and a reference to the map.
}
/** #constructor */
function USGSOverlay(bounds, image, map, rectPoly) {
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
this.rectPoly_ = rectPoly
// Define a property to hold the image's div. We'll
// actually create this div upon receipt of the onAdd()
// method so we'll leave it null for now.
this.div_ = null;
// Explicitly call setMap on this overlay
this.setMap(map);
}
/**
* onAdd is called when the map's panes are ready and the overlay has been
* added to the map.
*/
USGSOverlay.prototype.onAdd = function() {
var div = document.createElement('div');
div.style.border = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
rectPoly = this.rectPoly_;
// Create the img element and attach it to the div.
var img = document.createElement('img');
img.src = this.image_;
img.style.width = '100%';
img.style.height = '100%';
div.appendChild(img);
this.div_ = div;
// Add the element to the "overlayImage" pane.
var panes = this.getPanes();
panes.overlayImage.appendChild(this.div_);
};
USGSOverlay.prototype.draw = function() {
// We use the south-west and north-east
// coordinates of the overlay to peg it to the correct position and size.
// To do this, we need to retrieve the projection from the overlay.
var overlayProjection = this.getProjection();
// Retrieve the south-west and north-east coordinates of this overlay
// in LatLngs and convert them to pixel coordinates.
// We'll use these coordinates to resize the div.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's div to fit the indicated dimensions.
var div = this.div_;
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
};
USGSOverlay.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
};
// Set the visibility to 'hidden' or 'visible'.
function createPolygonFromRectangle(rectangle) {
var map = rectangle.getMap();
var coords = [{
lat: rectangle.getBounds().getNorthEast().lat(),
lng: rectangle.getBounds().getNorthEast().lng()
},
{
lat: rectangle.getBounds().getNorthEast().lat(),
lng: rectangle.getBounds().getSouthWest().lng()
},
{
lat: rectangle.getBounds().getSouthWest().lat(),
lng: rectangle.getBounds().getSouthWest().lng()
},
{
lat: rectangle.getBounds().getSouthWest().lat(),
lng: rectangle.getBounds().getNorthEast().lng()
}
];
// Construct the polygon.
var rectPoly = new google.maps.Polygon({
path: coords,
draggable: true,
rotation: 0
});
var properties = ["strokeColor", "strokeOpacity", "strokeWeight", "fillOpacity", "fillColor"];
//inherit rectangle properties
var options = {};
properties.forEach(function(property) {
if (rectangle.hasOwnProperty(property)) {
options[property] = rectangle[property];
}
});
rectPoly.setOptions(options);
rectangle.setMap(null);
rectPoly.setMap(map);
return rectPoly;
}
function rotatePolygon(polygon, angle) {
var map = polygon.getMap();
var prj = map.getProjection();
var bounds = new google.maps.LatLngBounds();
var i;
// The Bermuda Triangle
var polygonCoords = polygon.getPath().getArray();
for (i = 0; i < polygonCoords.length; i++) {
bounds.extend(polygonCoords[i]);
}
// The Center of the Bermuda Triangle - (25.3939245, -72.473816)
console.log(bounds.getCenter());
var origin = prj.fromLatLngToPoint(bounds.getCenter()); //rotate around first point
//var origin2 = prj.fromLatLngToPoint(polygon.getPath().getAt(1)); //rotate around first point
var coords = polygon.getPath().getArray().map(function(latLng) {
var point = prj.fromLatLngToPoint(latLng);
var rotatedLatLng = prj.fromPointToLatLng(rotatePoint(point, origin, angle));
return {
lat: rotatedLatLng.lat(),
lng: rotatedLatLng.lng()
};
});
polygon.setPath(coords);
}
function rotatePoint(point, origin, angle) {
var angleRad = angle * Math.PI / 180.0;
return {
x: Math.cos(angleRad) * (point.x - origin.x) - Math.sin(angleRad) * (point.y - origin.y) + origin.x,
y: Math.sin(angleRad) * (point.x - origin.x) + Math.cos(angleRad) * (point.y - origin.y) + origin.y
};
}
google.maps.event.addDomListener(window, 'load', initMap);
/* 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;
}
#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: 'Roboto', 'sans-serif';
line-height: 30px;
padding-left: 10px;
}
<!-- Add an input button to initiate the toggle method on the overlay. -->
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>

Google maps how to calculate south west and north east bound for overlay

While displaying an overlay over google maps using the API. I am googling for last three days how to calculate the South West and North east bounds for an overlay of size 100X100. I found millions of examples but the bounds were written hard coded.
My input is Center Latitude and Longitude and a 100x100 image.
The code I found is:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
center: {lat: 62.323907, lng: -150.109291},
mapTypeId: google.maps.MapTypeId.SATELLITE
});
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(SE),
new google.maps.LatLng(NE));
// The photograph is courtesy of the U.S. Geological Survey.
var srcImage = 'https://developers.google.com/maps/documentation/javascript/';
srcImage += 'examples/full/images/talkeetna.png';
overlay = new USGSOverlay(bounds, srcImage, map);
}
I am woundering how these bounds were calculated?
SE and NE
To calculate the bounds (specifically a google.maps.LatLngBounds object) that is 100px x 100px centered at the center of the bounds of that overlay:
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(62.281819, -150.287132),
new google.maps.LatLng(62.400471, -150.005608));
find the pixel position of the center:
var center = bounds.getCenter();
var centerPt = overlay.getProjection().fromLatLngToDivPixel(center);
find the pixel point 50px up and 50px right of it
var topRightPt = new google.maps.Point(centerPt.x+50, centerPt.y+50);
find the pixel point 50px down and 50px left of it
var botLeftPt = new google.maps.Point(centerPt.x-50, centerPt.y-50);
translate those back to latitude and longitude coordinates
var sw = overlay.getProjection().fromDivPixelToLatLng(botLeftPt);
var ne = overlay.getProjection().fromDivPixelToLatLng(topRightPt);
proof of concept fiddle
overlay = new USGSOverlay(bounds, srcImage, map);
google.maps.event.addListener(overlay, 'projection_changed', function() {
var centerPt = overlay.getProjection().fromLatLngToDivPixel(center);
var topRightPt = new google.maps.Point(centerPt.x+50, centerPt.y+50);
var botLeftPt = new google.maps.Point(centerPt.x-50, centerPt.y-50);
var sw = overlay.getProjection().fromDivPixelToLatLng(botLeftPt);
var ne = overlay.getProjection().fromDivPixelToLatLng(topRightPt);
var overlayBnds = new google.maps.LatLngBounds(sw,ne);
var rectangle = new google.maps.Rectangle({
map: map,
bounds: overlayBnds
})
});
code snippet:
google.maps.event.addDomListener(window, "load", initMap);
// This example creates a custom overlay called USGSOverlay, containing
// a U.S. Geological Survey (USGS) image of the relevant area on the map.
// Set the custom overlay object's prototype to a new instance
// of OverlayView. In effect, this will subclass the overlay class therefore
// it's simpler to load the API synchronously, using
// google.maps.event.addDomListener().
// Note that we set the prototype to an instance, rather than the
// parent class itself, because we do not wish to modify the parent class.
var overlay;
USGSOverlay.prototype = new google.maps.OverlayView();
// Initialize the map and the custom overlay.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
center: {
lat: 62.323907,
lng: -150.109291
},
mapTypeId: 'satellite'
});
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(62.281819, -150.287132),
new google.maps.LatLng(62.400471, -150.005608));
var center = bounds.getCenter();
// The photograph is courtesy of the U.S. Geological Survey.
var srcImage = 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/talkeetna.png';
// The custom USGSOverlay object contains the USGS image,
// the bounds of the image, and a reference to the map.
overlay = new USGSOverlay(bounds, srcImage, map);
google.maps.event.addListener(overlay, 'projection_changed', function() {
var centerPt = overlay.getProjection().fromLatLngToDivPixel(center);
var topRightPt = new google.maps.Point(centerPt.x + 50, centerPt.y + 50);
var botLeftPt = new google.maps.Point(centerPt.x - 50, centerPt.y - 50);
var sw = overlay.getProjection().fromDivPixelToLatLng(botLeftPt);
var ne = overlay.getProjection().fromDivPixelToLatLng(topRightPt);
var overlayBnds = new google.maps.LatLngBounds(sw, ne);
var rectangle = new google.maps.Rectangle({
map: map,
bounds: overlayBnds
})
});
}
/** #constructor */
function USGSOverlay(bounds, image, map) {
// Initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
// Define a property to hold the image's div. We'll
// actually create this div upon receipt of the onAdd()
// method so we'll leave it null for now.
this.div_ = null;
// Explicitly call setMap on this overlay.
this.setMap(map);
}
/**
* onAdd is called when the map's panes are ready and the overlay has been
* added to the map.
*/
USGSOverlay.prototype.onAdd = function() {
var div = document.createElement('div');
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
// Create the img element and attach it to the div.
var img = document.createElement('img');
img.src = this.image_;
img.style.width = '100%';
img.style.height = '100%';
img.style.position = 'absolute';
div.appendChild(img);
this.div_ = div;
// Add the element to the "overlayLayer" pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
};
USGSOverlay.prototype.draw = function() {
// We use the south-west and north-east
// coordinates of the overlay to peg it to the correct position and size.
// To do this, we need to retrieve the projection from the overlay.
var overlayProjection = this.getProjection();
// Retrieve the south-west and north-east coordinates of this overlay
// in LatLngs and convert them to pixel coordinates.
// We'll use these coordinates to resize the div.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's div to fit the indicated dimensions.
var div = this.div_;
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
};
// The onRemove() method will be called automatically from the API if
// we ever set the overlay's map property to 'null'.
USGSOverlay.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
};
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map"></div>

Intersection of two polygons in google map

I am trying to draw multiple polygons using google shapes API. I need to get the intersection of two polygons.
Here I can draw the background polygon(in black) by giving the array of path of each polygon.
Below is my code, here I am giving MVC Array as paths for polygon.
I just want the intersection area to be in separate color. Please check the screen shot link attached after the code.
var bgAreaCoordinates = [];
var bgbounds = map.getBounds(); // Boundary coordinates of the visible area of map
var NE = bgbounds.getNorthEast();
var SW = bgbounds.getSouthWest();
var bgPathCoordinates = [NE, new google.maps.LatLng(NE.lat(),SW.lng()),
SW, new google.maps.LatLng(SW.lat(),NE.lng())];
// Array of boundary coordinates of the visible part of the map
bgAreaCoordinates.push(bgPathCoordinates);
for (var key in flightPlanCoordinates) {
for (var k in flightPlanCoordinates[key]) {
bgAreaCoordinates.push(flightPlanCoordinates[key][k]);// Getting array of coordinates of each polygon
}
}
if (bgPath['bg']) {
bgPath['bg'].setMap(null); // remove the previous bg
}
console.info(bgAreaCoordinates);
bgPath['bg'] = new google.maps.Polygon({
// paths: [bgPathCoordinates, bgAreaCoordinates],
paths:bgAreaCoordinates,
geodesic: true,
strokeColor: '',
strokeOpacity: 0,
strokeWeight: 0,
fillColor: '#687472',
fillOpacity: 0.7
});
bgPath['bg'].setMap(map); // Draw the bg polygon : Google shapes Api
http://i.stack.imgur.com/VjTZe.png
Thanks in advance!
Here is an example that does what I think you want to do (make a hole in a polygon that covers the earth and cover that hole with a polygon with a different color). The example polygon happens to be a circle.
code snippet
// This example creates circles on the map, representing
// populations in the United States.
// First, create an object containing LatLng and population for each city.
var citymap = {};
citymap['chicago'] = {
center: new google.maps.LatLng(41.878113, -87.629798),
population: 2842518
};
citymap['newyork'] = {
center: new google.maps.LatLng(40.714352, -74.005973),
population: 8143197
};
citymap['losangeles'] = {
center: new google.maps.LatLng(34.052234, -118.243684),
population: 3844829
};
var cityCircle;
var bounds = new google.maps.LatLngBounds();
function drawCircle(point, radius, dir) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 3963; // 3963 is the radius of the earth in miles
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(point.lat() * d2r);
var extp = new Array();
if (dir == 1) {
var start = 0;
var end = points + 1
} // one extra here makes sure we connect the ends
else {
var start = points + 1;
var end = 0
}
for (var i = start;
(dir == 1 ? i < end : i > end); i = i + dir) {
var theta = Math.PI * (i / (points / 2));
ey = point.lng() + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point.lat() + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push(new google.maps.LatLng(ex, ey));
bounds.extend(extp[extp.length - 1]);
}
return extp;
}
function initialize() {
// Create the map.
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(37.09024, -95.712891),
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var outerbounds = [
new google.maps.LatLng(85, 180),
new google.maps.LatLng(85, 90),
new google.maps.LatLng(85, 0),
new google.maps.LatLng(85, -90),
new google.maps.LatLng(85, -180),
new google.maps.LatLng(0, -180),
new google.maps.LatLng(-85, -180),
new google.maps.LatLng(-85, -90),
new google.maps.LatLng(-85, 0),
new google.maps.LatLng(-85, 90),
new google.maps.LatLng(-85, 180),
new google.maps.LatLng(0, 180),
new google.maps.LatLng(85, 180)
];
var populationOptions = {
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
paths: [outerbounds, drawCircle(citymap['newyork'].center, 10, -1)]
};
// Add the circle for this city to the map.
cityCircle = new google.maps.Polygon(populationOptions);
map.fitBounds(bounds);
var coverHole = new google.maps.Polygon({
strokeColor: '#FFFF00',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#0000FF',
fillOpacity: 0.35,
map: map,
paths: [drawCircle(citymap['newyork'].center, 10, -1)]
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map-canvas"></div>

HTML Canvas As Overlayview In Google Maps That Is Fixed Relative to the Map Canvas

I'm trying to create an HTML5 canvas as an OverlayView the size of a map, position it to top:0; left:0;, draw some stuff on it, and add it to the map. Whenever the map zooms or pans I want to remove the old canvas from the map and create a new canvas draw on it position it to 0,0 and add it to the map. However the map never reposition to top:0; left:0. Can someone help?
function CustomLayer(map){
this.latlngs = new Array();
this.map_ = map;
this.addMarker = function(position){
this.latlngs.push(position);
}
this.drawCanvas = function(){
this.setMap(this.map_);
//google.maps.event.addListener(this.map_, 'bounds_changed',this.reDraw());
}
}
function defineOverlay() {
CustomLayer.prototype = new google.maps.OverlayView();
CustomLayer.prototype.onAdd = function() {
console.log("onAdd()");
if(this.canvas){
var panes = this.getPanes();
panes.overlayLayer.appendChild(this.canvas);
}
}
CustomLayer.prototype.remove = function() {
console.log("onRemove()");
if(this.canvas)
this.canvas.parentNode.removeChild(this.canvas);
}
CustomLayer.prototype.draw = function() {
console.log("draw()");
this.remove();
this.canvas = document.createElement("canvas");
this.canvas.setAttribute('width', '800px');
this.canvas.setAttribute('height', '480px');
this.canvas.setAttribute('top', '30px');
this.canvas.setAttribute('left', '30px');
this.canvas.setAttribute('position', 'absolute');
this.canvas.setAttribute('border', '1px solid red');
this.canvas.style.border = '1px solid red';
//using this way for some reason scale up the images and mess up the positions of the markers
/*this.canvas.style.position = 'absolute';
this.canvas.style.top = '0px';
this.canvas.style.left = '0px';
this.canvas.style.width = '800px';
this.canvas.style.height = '480px';
this.canvas.style.border = '1px solid red';*/
//get the projection from this overlay
overlayProjection = this.getProjection();
//var mapproj = this.map_.getProjection();
if(this.canvas.getContext) {
var context = this.canvas.getContext('2d');
context.clearRect(0,0,800,480);
for(i=0; i<this.latlngs.length; i++){
p = overlayProjection.fromLatLngToDivPixel(this.latlngs[i]);
//p = mapproj.fromLatLngToPoint(this.latlngs[i]);
img = new Image();
img.src = "standardtick.png";
console.log(Math.floor(p.x)+","+Math.floor(p.y));
context.drawImage(img,p.x,p.y);
}
}
this.onAdd();
console.log("canvas width:"+this.canvas.width+" canvas height: "+this.canvas.height);
console.log("canvas top:"+this.canvas.getAttribute("top")+" left: "+this.canvas.getAttribute("left"));
}
}
In this example - I think it is important to draw attention to the difference between projection.fromLatLngToDivPixel and projection.fromLatLngToContainerPixel. In this context, DivPixel is used to keep the position of the canvas centered over the map view - while ContainerPixel is used to find the positions of the shapes you are drawing to the canvas.
What follows is a complete working example I worked out while playing around with this problem myself.
Required CSS Properties for the Overlay:
.GMAPS_OVERLAY
{
border-width: 0px;
border: none;
position:absolute;
padding:0px 0px 0px 0px;
margin:0px 0px 0px 0px;
}
Initialize the Map and Create a Test based on Google Markers
var mapsize = { width: 500, height: 500 };
var mapElement = document.getElementById("MAP");
mapElement.style.height = mapsize.width + "px";
mapElement.style.width = mapsize.width + "px";
var map = new google.maps.Map(document.getElementById("MAP"), {
mapTypeId: google.maps.MapTypeId.TERRAIN,
center: new google.maps.LatLng(0, 0),
zoom: 2
});
// Render G-Markers to Test Proper Canvas-Grid Alignment
for (var lng = -180; lng < 180; lng += 10)
{
var marker = new google.maps.Marker({
position: new google.maps.LatLng(0, lng),
map: map
});
}
Define the Custom Overlay
var CanvasOverlay = function(map) {
this.canvas = document.createElement("CANVAS");
this.canvas.className = "GMAPS_OVERLAY";
this.canvas.height = mapsize.height;
this.canvas.width = mapsize.width;
this.ctx = null;
this.map = map;
this.setMap(map);
};
CanvasOverlay.prototype = new google.maps.OverlayView();
CanvasOverlay.prototype.onAdd = function() {
this.getPanes().overlayLayer.appendChild(this.canvas);
this.ctx = this.canvas.getContext("2d");
this.draw();
};
CanvasOverlay.prototype.drawLine = function(p1, p2) {
this.ctx.beginPath();
this.ctx.moveTo( p1.x, p1.y );
this.ctx.lineTo( p2.x, p2.y );
this.ctx.closePath();
this.ctx.stroke();
};
CanvasOverlay.prototype.draw = function() {
var projection = this.getProjection();
// Shift the Canvas
var centerPoint = projection.fromLatLngToDivPixel(this.map.getCenter());
this.canvas.style.left = (centerPoint.x - mapsize.width / 2) + "px";
this.canvas.style.top = (centerPoint.y - mapsize.height / 2) + "px";
// Clear the Canvas
this.ctx.clearRect(0, 0, mapsize.width, mapsize.height);
// Draw Grid with Canvas
this.ctx.strokeStyle = "#000000";
for (var lng = -180; lng < 180; lng += 10)
{
this.drawLine(
projection.fromLatLngToContainerPixel(new google.maps.LatLng(-90, lng)),
projection.fromLatLngToContainerPixel(new google.maps.LatLng( 90, lng))
);
}
};
Initializing the Canvas
I find that I like to add an additional call to draw on the "dragend" event - but test it out to see what you think on your needs.
var customMapCanvas = new CanvasOverlay(map);
google.maps.event.addListener(map, "drawend", function() {
customMapCanvas.draw();
};
In cases where Canvas Drawing is Slowing Down Map
On the applications I work with, I find that the Map Framework calls the 'draw' method far too often on canvas's which are drawing something that takes a second or so to complete. In this case I define the 'draw' prototype function to be simply an empty function while naming my real draw function as 'canvasDraw' - then add event listeners for "zoomend" and "dragend". What you get here is a canvas that updates only after a user changes the zoom level or at the end of a map drag action.
CanvasOverlay.prototype.draw = function() { };
...
google.maps.event.addListener(map, "dragend", function() {
customMapCanvas.canvasDraw();
});
google.maps.event.addListener(map, "zoom_changed", function() {
customMapCanvas.canvasDraw();
});
Live Demo: Complete Example - All Inline Source
Once your map moves, the drawing context needs to know it has moved.
CustomOverlayView.prototype.alignDrawingPane = function(force) {
window.mapProjection = this.getProjection();
var center = window.mapProjection.fromLatLngToDivPixel(map.getCenter());
//My drawing container is dragged along with the map when panning
//this.drawPane refers to any node in MapPanes retrieved via this.getPanes()
this.drawPane.css({left:center.x - (mapWidth/2), top:center.y-(mapHeight/2)});
};
Call this in your draw() method. Make sure your draw gets called when you're done dragging:
google.maps.event.addListener(map, 'dragend', function() {
myCustomOverlay.draw();
});