Google Maps API v3 add shadow on clicked marker - javascript

I am aware that officially google removed shadows on markers in v3 of the google maps API. With this is in mind i have a project where marker shadows are required. I would like to place a shadow on a marker when the marker is clicked. Its essentially add an event listener to a marker and when its clicked add a shadow to the marker as a way to show that the clicked marker is the active marker.
I read through some pages e.g. marker shadows in google maps v3 which put shadows on all markers but I would like to borrow on such an example and have the shadows added when a marker is clicked and have the shadows removed when the marker loses focus i.e. when another marker is clicked.
My jsfiddle with two markers to play with is here and code is below: jsfiddle is here
var marker;
var locations = [["6","43.683","9.58","3002: Location 1",1],["7","45.149","9.44","3003: Location",2]];
function initialize() {
var mapProp = {
center: new google.maps.LatLng(43.683, 9.44),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position:new google.maps.LatLng(locations[i][1], locations[i][2]),
icon:'https://maps.gstatic.com/mapfiles/ms2/micons/purple.png',
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
alert(locations[i][3] + " was clicked");
}
})(marker, i));
marker.setMap(map);
}
}
google.maps.event.addDomListener(window, 'load', initialize);
If anyone can help with coming up with a strategy or even a code snippet to place shadows on a marker when its clicked I would be very happy. Please feel free to fork the jsfiddle and add to it and post the link back here.

Another option, create the marker shadow object (from my answer to the question you reference) the first time a marker is clicked, move it to a newly clicked marker when that is clicked (add a .setPosition method to the MarkerShadow class).
var marker;
var locations = [
["6", "43.683", "9.58", "3002: Location 1", 1, true],
["7", "45.149", "9.44", "3003: Location", 2, false]
];
var markerShadow;
var infowindow = new google.maps.InfoWindow();
function initialize() {
var mapProp = {
center: new google.maps.LatLng(43.683, 9.44),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var iconShadow = {
url: 'http://www.geocodezip.com/mapIcons/marker_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, 34),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(10, 34)
};
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
icon: 'https://maps.gstatic.com/mapfiles/ms2/micons/purple.png',
title: locations[i][3]
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
if (markerShadow && markerShadow.setPosition) {
markerShadow.setPosition(this.getPosition());
} else if (!markerShadow) {
markerShadow = new MarkerShadow(marker.getPosition(), iconShadow, map);
}
}
})(marker, i));
marker.setMap(map);
}
}
google.maps.event.addDomListener(window, 'load', initialize);
// marker shadow code
MarkerShadow.prototype = new google.maps.OverlayView();
MarkerShadow.prototype.setPosition = function(latlng) {
this.posn_ = latlng;
this.draw();
}
/** #constructor */
function MarkerShadow(position, options, map) {
// Initialize all properties.
this.posn_ = position;
this.map_ = map;
if (typeof(options) == "string") {
this.image = options;
} else {
this.options_ = options;
if (!!options.size) this.size_ = options.size;
if (!!options.url) this.image_ = options.url;
}
// 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.
*/
MarkerShadow.prototype.onAdd = function() {
// if no url, return, nothing to do.
if (!this.image_) return;
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 = this.options_.size.x + 'px';
img.style.height = this.options_.size.y + 'px';
img.style.position = 'absolute';
div.appendChild(img);
this.div_ = div;
// Add the element to the "overlayLayer" pane.
var panes = this.getPanes();
panes.overlayShadow.appendChild(div);
};
MarkerShadow.prototype.draw = function() {
// if no url, return, nothing to do.
if (!this.image_) return;
// We use the coordinates of the overlay to peg it to the correct position
// To do this, we need to retrieve the projection from the overlay.
var overlayProjection = this.getProjection();
var posn = overlayProjection.fromLatLngToDivPixel(this.posn_);
// Resize the image's div to fit the indicated dimensions.
if (!this.div_) return;
var div = this.div_;
if (!!this.options_.anchor) {
div.style.left = Math.floor(posn.x - this.options_.anchor.x) + 'px';
div.style.top = Math.floor(posn.y - this.options_.anchor.y) + 'px';
}
if (!!this.options_.size) {
div.style.width = this.size_.x + 'px';
div.style.height = this.size_.y + 'px';
}
};
// The onRemove() method will be called automatically from the API if
// we ever set the overlay's map property to 'null'.
MarkerShadow.prototype.onRemove = function() {
if (!this.div_) return;
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
};
html,
body,
#googleMap {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="googleMap"></div>
fiddle showing result

Related

Google Map Overlays do not show when I dynamically load the map by create a <script> element in a HTML file

By reference to Goomap map overlays DEMO https://google-developers.gonglchuangl.net/maps/documentation/javascript/examples/overlay-hideshow,I modify from this to dynamically load the map by create a element in a HTML File. However, I can see that Map Tiles shows correctly, but missing the overlays.
Besides, when I click the button, a TypeError occurs: overlay.toggle is not a function: TypeErrorPic
How can I dynamic load a Element in a HTML file?
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Showing/Hiding Overlays</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;
}
#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;
}
</style>
<!-- <script src="https://maps.googleapis.com/maps/api/js?key=MY_KEY"></script> -->
<script>
var myscript = document.createElement("script");
myscript.type = "text/javascript";
myscript.src = "https://maps.googleapis.com/maps/api/js?key=MY_KEY&callback=init_callback";
document.getElementsByTagName('head')[0].appendChild(myscript);
</script>
<script>
// 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;
function init_callback()
{
USGSOverlay.prototype = new google.maps.OverlayView();
initMap();
}
function initMap() {
//alert("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));
// 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);
}
/** #constructor */
function USGSOverlay(bounds, image, map) {
// Now 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.border = '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%';
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'.
USGSOverlay.prototype.hide = function() {
if (this.div_) {
// The visibility property must be a string enclosed in quotes.
this.div_.style.visibility = 'hidden';
}
};
USGSOverlay.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = 'visible';
}
};
USGSOverlay.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility === 'hidden') {
this.show();
} else {
this.hide();
}
}
};
// Detach the map from the DOM via toggleDOM().
// Note that if we later reattach the map, it will be visible again,
// because the containing <div> is recreated in the overlay's onAdd() method.
USGSOverlay.prototype.toggleDOM = function() {
if (this.getMap()) {
// Note: setMap(null) calls OverlayView.onRemove()
this.setMap(null);
} else {
this.setMap(this.map_);
}
};
//google.maps.event.addDomListener(window, 'load', initMap);
</script>
</head>
<body>
<!-- Add an input button to initiate the toggle method on the overlay. -->
<div id="floating-panel">
<input type="button" value="Toggle visibility" onclick="overlay.toggle();"></input>
<input type="button" value="Toggle DOM attachment" onclick="overlay.toggleDOM();"></input>
</div>
<div id="map"></div>
</body>
</html>
It is an ordering issue. You need to define the entire USGSOverlay class inside the init_callback function (that runs once the API is loaded). The way the code in your question runs, the init_callback function runs after the rest of the USGSOverlay class is defined and overwrites it.
proof of concept fiddle
/* 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;
}
<script>
var myscript = document.createElement("script");
myscript.type = "text/javascript";
myscript.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=init_callback";
document.getElementsByTagName('head')[0].appendChild(myscript);
</script>
<script>
// 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;
/** #constructor */
function USGSOverlay(bounds, image, map) {
// Now 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);
}
function init_callback() {
USGSOverlay.prototype = new google.maps.OverlayView();
/**
* 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';
// 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'.
USGSOverlay.prototype.hide = function() {
if (this.div_) {
// The visibility property must be a string enclosed in quotes.
this.div_.style.visibility = 'hidden';
}
};
USGSOverlay.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = 'visible';
}
};
USGSOverlay.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility === 'hidden') {
this.show();
} else {
this.hide();
}
}
};
// Detach the map from the DOM via toggleDOM().
// Note that if we later reattach the map, it will be visible again,
// because the containing <div> is recreated in the overlay's onAdd() method.
USGSOverlay.prototype.toggleDOM = function() {
if (this.getMap()) {
// Note: setMap(null) calls OverlayView.onRemove()
this.setMap(null);
} else {
this.setMap(this.map_);
}
};
initMap();
}
function initMap() {
//alert("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));
// 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);
}
//google.maps.event.addDomListener(window, 'load', initMap);
</script>
<!-- Add an input button to initiate the toggle method on the overlay. -->
<div id="floating-panel">
<input type="button" value="Toggle visibility" onclick="overlay.toggle();" />
<input type="button" value="Toggle DOM attachment" onclick="overlay.toggleDOM();" />
</div>
<div id="map"></div>
can you uncomment this line in your code and try again?
google.maps.event.addDomListener(window, 'load', initMap);

Google map: Custom Overlay Image

I am using the OverlayView to create a simple image overlay on google maps. I want to repeat the image into different locations on the google map. Is it possible and if so how can I do this?
PS: I use the code from Google maps website documentation, but since I am new to coding I am not sure how to do this.
Here is my code
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Google Cam</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>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
<script>
var overlay;
USGSOverlay.prototype = new google.maps.OverlayView();
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: {
lat: 62.323907,
lng: -150.109291
},
gestureHandling: 'cooperative',
zoomControl: false,
scrollwheel: false,
disableDoubleClickZoom: true,
streetViewControl: false,
panControl: false,
mapTypeControl: false,
mapTypeId: 'satellite'
});
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(68.281819, -150.287132),
new google.maps.LatLng(68.400471, -150.005608));
var srcImage = 'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/talkeetna.png';
overlay = new USGSOverlay(bounds, srcImage, map);
}
/** #constructor */
function USGSOverlay(bounds, image, map) {
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
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 = '2000%';
img.style.height = '2000%';
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() {
var overlayProjection = this.getProjection();
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
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_);
this.div_ = null;
};
google.maps.event.addDomListener(window, 'load', initMap);
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
Sure you can. All you need to change from your code is to have 2 overlays declared as variables, and 2 LatLngBounds objects. Here I have created a second overlay below the one you are using in your code.
var overlay1;
// Declare a second overlay variable
var overlay2;
USGSOverlay.prototype = new google.maps.OverlayView();
function initMap() {
// Initialize the map and the custom overlay.
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: {
lat: 66.323907,
lng: -150.109291
},
gestureHandling: 'cooperative',
zoomControl: false,
scrollwheel: false,
disableDoubleClickZoom: true,
streetViewControl: false,
panControl: false,
mapTypeControl: false,
mapTypeId: 'satellite'
});
var bounds1 = new google.maps.LatLngBounds(
new google.maps.LatLng(68.281819, -150.287132),
new google.maps.LatLng(68.400471, -150.005608));
// Declared a second bounds object
var bounds2 = new google.maps.LatLngBounds(
new google.maps.LatLng(65.281819, -150.287132),
new google.maps.LatLng(65.400471, -150.005608));
// 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.
overlay1 = new USGSOverlay(bounds1, srcImage, map);
// Create a second overlay
overlay2 = new USGSOverlay(bounds2, srcImage, map);
}
/** #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 = '2000%';
img.style.height = '2000%';
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;
};
initMap();
#map {
height: 200px;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js"></script>
I renamed your initial variables to overlay1 and bounds1 for clarity, but you can use whatever variable names you want.

How to make overlay div in google map dragable?

I need to drag the position of the div. I used below code and but is not worked. I think i done some mistake over here.also i need to rotate the div so that i can place the image at right position
var overlay;
DebugOverlay.prototype = new google.maps.OverlayView();
function initialize() {
var mapOptions = {
zoom: 15,
center: new google.maps.LatLng(40.743388, -74.007592)
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var swBound = new google.maps.LatLng(40.73660837340877, -74.01852328);
var neBound = new google.maps.LatLng(40.75214181, -73.99661518216243);
var bounds = new google.maps.LatLngBounds(swBound, neBound);
var srcImage = 'http://library.marist.edu/pix/LibMap3.jpg';
overlay = new DebugOverlay(bounds, srcImage, map);
var markerA = new google.maps.Marker({
position: swBound,
map: map,
draggable: true
});
var markerB = new google.maps.Marker({
position: neBound,
map: map,
draggable: true
});
google.maps.event.addListener(markerA, 'drag', function () {
var newPointA = markerA.getPosition();
var newPointB = markerB.getPosition();
var newBounds = new google.maps.LatLngBounds(newPointA, newPointB);
overlay.updateBounds(newBounds);
});
google.maps.event.addListener(markerB, 'drag', function () {
var newPointA = markerA.getPosition();
var newPointB = markerB.getPosition();
var newBounds = new google.maps.LatLngBounds(newPointA, newPointB);
overlay.updateBounds(newBounds);
});
google.maps.event.addListener(markerA, 'dragend', function () {
var newPointA = markerA.getPosition();
var newPointB = markerB.getPosition();
console.log("point1" + newPointA);
console.log("point2" + newPointB);
});
google.maps.event.addListener(markerB, 'dragend', function () {
var newPointA = markerA.getPosition();
var newPointB = markerB.getPosition();
console.log("point1" + newPointA);
console.log("point2" + newPointB);
});
}
function DebugOverlay(bounds, image, map) {
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
this.div_ = null;
this.setMap(map);
}
DebugOverlay.prototype.onAdd = function () {
var div = document.createElement('div');
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
var img = document.createElement('img');
img.src = this.image_;
img.style.width = '100%';
img.style.height = '100%';
img.style.opacity = '0.5';
img.style.position = 'absolute';
div.appendChild(img);
this.div_ = div;
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
};
DebugOverlay.prototype.draw = function () {
debugger;
var overlayProjection = this.getProjection();
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
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';
};
DebugOverlay.prototype.updateBounds = function (bounds) {
this.bounds_ = bounds;
this.draw();
};
DebugOverlay.prototype.onRemove = function () {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
};
google.maps.event.addDomListener(window, 'load', initialize);
(I spent too many minutes than I expect at first...)
As far as I understand your question and your code, you want to drag the floor map image directly, and the corner markers are followed with it, correct?
HTML5 supports the drag events.
http://www.w3schools.com/html/html5_draganddrop.asp
However, in google maps v3, all mouse events are captured by Google Maps.
Here is the trick.
Capture the mouse event
In order to catch the mouse events, you need to insert a div (named mouseTarget in my code) into the overlayMouseTarget pane. The overlayMouseTarget is the most top layer in Google Maps v3.
But it sets .style.display=none in normal status (not dragging). It becomes .style.display=block only if you mouse down the mouseTarget div.
However, even if in normal status, the mouseTarget div have to catch up the position with the image.
Dragging events
When you mousedown on the mouseTarget, you have to cancel the event at once in order to prevent dragging the map.
Then, you need to handle dragstart, drag, and dragleave events by yourself.
It means you need to follow the mouse cursor position, then recalculate the image position, and marker positions.
Here is my answer for your first question I need to drag the position of the div.
https://jsfiddle.net/wf9a5m75/wj65aLrk/

Load GoogleMap Async with USGSOverlay

I'm currently working with Browserify for my JS Files. I got an error when i try to load GoogleMap Api aSync and apply USGSOverlay for custom image overlay.
I followed this https://developers.google.com/maps/documentation/javascript/examples/map-simple-async and https://developers.google.com/maps/documentation/javascript/customoverlays.
Everything work well for a simple GoogleMaps but as soon as i apply the USGSOverlay, i got multiple error like : Uncaught TypeError: this.draw is not a function WM15838:1
It must be how i call my function.. ? Here the code :
var $ = require('jquery');
var overlay;
var map;
var USGSOverlay;
//map_area is defined inline, but for this post...
var map_area = new Array('45.684994,-73.731739','45.684616,-73.732816','45.684450,-73.732558','45.684659,-73.732002','45.684832,-73.731602');
window.launchMap = function() {
initialize();
}
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);
};
// 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;
};
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);
}
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';
};
function initialize() {
USGSOverlay.prototype = new google.maps.OverlayView();
var mapOptions = {
zoom: 16,
scrollwheel: false,
center: new google.maps.LatLng(45.684163, -73.733305),
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var marker_pin = "/images/site/Pin.png";
var swBound = new google.maps.LatLng(45.678510, -73.747798);
var neBound = new google.maps.LatLng(45.692415, -73.718118);
var bounds = new google.maps.LatLngBounds(swBound, neBound);
// The photograph is courtesy of the U.S. Geological Survey.
var srcImage = 'map.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);
infowindow = new google.maps.InfoWindow({
content: "Chargement..."
});
var areaCoords = [];
if (map_area.length > 0) {
for (i = 0; i < map_area.length; i++) {
areaCoords[i] = new Array();
for (j = 0; j < map_area[i].length; j++) {
coord = map_area[i][j].split(',');
areaCoords[i][j] = new google.maps.LatLng(coord[0], coord[1]);
}
polygonMap = new google.maps.Polygon({
paths: areaCoords[i],
strokeColor: '#ff2205',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#ff2205',
fillOpacity: 0
});
polygonMap.setMap(map);
}
// Add a listener for the click event.
/*google.maps.event.addListener(polygonMap, 'click', function() {
}); */
}
$('.block_unit').each(function(index, element) {
var _lat = $(this).find('.address').data('lat');
var _lng = $(this).find('.address').data('lng');
latLng = new google.maps.LatLng(_lat, _lng)
$(this).next('.map_popup').find('.text').html($(this).find('.block__title').html());
var info = $(this).next('.map_popup').html();
//info.find('.text').html($(this).find('.block__title').html());
var marker = new google.maps.Marker({
map: map,
position: latLng,
icon: new google.maps.MarkerImage(marker_pin)
});
google.maps.event.addListener(marker, "click", function() {
if (infowindow) infowindow.close();
infowindow = new google.maps.InfoWindow({content: info});
infowindow.open(map, marker);
});
});
}
function loadScript() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp' +
'&signed_in=true&callback=launchMap';
document.body.appendChild(script);
}
window.onload = loadScript;
The USGSOverlay depends on the Google Maps Javascript API v3. You can't define it until after that code is loaded. Define it inside your launchMap or initialize functions.
proof of concept fiddle
code snippet:
var overlay;
var map;
var USGSOverlay;
//map_area is defined inline, but for this post...
var map_area = new Array('45.684994,-73.731739', '45.684616,-73.732816', '45.684450,-73.732558', '45.684659,-73.732002', '45.684832,-73.731602');
window.launchMap = function() {
/** #constructor */
USGSOverlay = function(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);
};
USGSOverlay.prototype = new google.maps.OverlayView();
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);
};
// 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;
};
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';
};
initialize();
};
function initialize() {
var mapOptions = {
zoom: 14,
scrollwheel: false,
center: new google.maps.LatLng(45.684163, -73.733305),
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var marker_pin = "/images/site/Pin.png";
var swBound = new google.maps.LatLng(45.678510, -73.747798);
var neBound = new google.maps.LatLng(45.692415, -73.718118);
var bounds = new google.maps.LatLngBounds(swBound, neBound);
// The photograph is courtesy of the U.S. Geological Survey.
// var srcImage = 'map.png';
var srcImage = 'https://developers.google.com/maps/documentation/javascript/';
srcImage += '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);
infowindow = new google.maps.InfoWindow({
content: "Chargement..."
});
var areaCoords = [];
if (map_area.length > 0) {
for (i = 0; i < map_area.length; i++) {
areaCoords[i] = [];
for (j = 0; j < map_area[i].length; j++) {
coord = map_area[i][j].split(',');
areaCoords[i][j] = new google.maps.LatLng(coord[0], coord[1]);
}
polygonMap = new google.maps.Polygon({
paths: areaCoords[i],
strokeColor: '#ff2205',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#ff2205',
fillOpacity: 0
});
polygonMap.setMap(map);
}
// Add a listener for the click event.
/*google.maps.event.addListener(polygonMap, 'click', function() {
}); */
}
$('.block_unit').each(function(index, element) {
var _lat = $(this).find('.address').data('lat');
var _lng = $(this).find('.address').data('lng');
latLng = new google.maps.LatLng(_lat, _lng);
$(this).next('.map_popup').find('.text').html($(this).find('.block__title').html());
var info = $(this).next('.map_popup').html();
//info.find('.text').html($(this).find('.block__title').html());
var marker = new google.maps.Marker({
map: map,
position: latLng,
icon: new google.maps.MarkerImage(marker_pin)
});
google.maps.event.addListener(marker, "click", function() {
if (infowindow) infowindow.close();
infowindow = new google.maps.InfoWindow({
content: info
});
infowindow.open(map, marker);
});
});
}
function loadScript() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp' +
'&signed_in=true&callback=launchMap';
document.body.appendChild(script);
}
window.onload = loadScript;
html,
body,
#map-canvas {
height: 500px;
width: 500px;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="map-canvas" style="border: 2px solid #3872ac;"></div>
<div id="order_list"></div>
<div id="product-list-display"></div>

Customizing an InfoWindow

Is it possible to change the color of the border, the alignment, padding and other attributes of an InfoWindow? I've been looking for this for a week but I always end up here. And it does not provide a code.
Here's my code.
//Declare an infoWindow variable - shows when a marker is tapped/clicked
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("outputXML.php", function(data)
{
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b> <br/>" + address;
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
title:name
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
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);
}//END FUNCTION BINDINFOWINDOW
function doNothing() {} //For request.onreadystatechange
By the way, I'm catching those values from an online database, we don't have to mind that, they're all working fine, the only problem is how to customize an infoWindow.
Please help me. Thanks.
ADD: I forgot to say that I will insert this into an android application. I'm using webview.
The content that you pass to an InfoWindow may be: text, HTML, or a DOM element. The InfoWindow is by default sized to fit whataver content you pass, so the best way to control the content the way you describe is to create a div, assign a CSS class to the div, and then you will have complete control over the appearance of your InfoWindow content.
Also, if you want to have more control over the actual appearance of the window structure itself, you may want to consider using the InfoBubble Utility Library as a stylable drop-in replacement for the standard InfoWindow.
Checkout the sample code of this url,
In this code, InfoBox extends GOverlay class from the Google Maps API and creating div dynamically and drawing into the map.
Another Example page
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Info Window Custom</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
/* An InfoBox is like an info window, but it displays
* under the marker, opens quicker, and has flexible styling.
* #param {GLatLng} latlng Point to place bar at
* #param {Map} map The map on which to display this InfoBox.
* #param {Object} opts Passes configuration options - content,
* offsetVertical, offsetHorizontal, className, height, width
*/
function InfoBox(opts) {
google.maps.OverlayView.call(this);
this.latlng_ = opts.latlng;
this.map_ = opts.map;
this.offsetVertical_ = -195;
this.offsetHorizontal_ = 0;
this.height_ = 165;
this.width_ = 266;
var me = this;
this.boundsChangedListener_ =
google.maps.event.addListener(this.map_, "bounds_changed", function() {
return me.panMap.apply(me);
});
// Once the properties of this OverlayView are initialized, set its map so
// that we can display it. This will trigger calls to panes_changed and
// draw.
this.setMap(this.map_);
}
/* InfoBox extends GOverlay class from the Google Maps API
*/
InfoBox.prototype = new google.maps.OverlayView();
/* Creates the DIV representing this InfoBox
*/
InfoBox.prototype.remove = function() {
if (this.div_) {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
/* Redraw the Bar based on the current projection and zoom level
*/
InfoBox.prototype.draw = function() {
// Creates the element if it doesn't exist already.
this.createElement();
if (!this.div_) return;
// Calculate the DIV coordinates of two opposite corners of our bounds to
// get the size and position of our Bar
var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
if (!pixPosition) return;
// Now position our DIV based on the DIV coordinates of our bounds
this.div_.style.width = this.width_ + "px";
this.div_.style.left = (pixPosition.x + this.offsetHorizontal_) + "px";
this.div_.style.height = this.height_ + "px";
this.div_.style.top = (pixPosition.y + this.offsetVertical_) + "px";
this.div_.style.display = 'block';
};
/* Creates the DIV representing this InfoBox in the floatPane. If the panes
* object, retrieved by calling getPanes, is null, remove the element from the
* DOM. If the div exists, but its parent is not the floatPane, move the div
* to the new pane.
* Called from within draw. Alternatively, this can be called specifically on
* a panes_changed event.
*/
InfoBox.prototype.createElement = function() {
var panes = this.getPanes();
var div = this.div_;
if (!div) {
// This does not handle changing panes. You can set the map to be null and
// then reset the map to move the div.
div = this.div_ = document.createElement("div");
div.style.border = "0px none";
div.style.position = "absolute";
div.style.background = "url('http://gmaps-samples.googlecode.com/svn/trunk/images/blueinfowindow.gif')";
div.style.width = this.width_ + "px";
div.style.height = this.height_ + "px";
var contentDiv = document.createElement("div");
contentDiv.style.padding = "30px"
contentDiv.innerHTML = "<b>Hello World! </b>";
var topDiv = document.createElement("div");
topDiv.style.textAlign = "right";
var closeImg = document.createElement("img");
closeImg.style.width = "32px";
closeImg.style.height = "32px";
closeImg.style.cursor = "pointer";
closeImg.src = "http://gmaps-samples.googlecode.com/svn/trunk/images/closebigger.gif";
topDiv.appendChild(closeImg);
function removeInfoBox(ib) {
return function() {
ib.setMap(null);
};
}
google.maps.event.addDomListener(closeImg, 'click', removeInfoBox(this));
div.appendChild(topDiv);
div.appendChild(contentDiv);
div.style.display = 'none';
panes.floatPane.appendChild(div);
this.panMap();
} else if (div.parentNode != panes.floatPane) {
// The panes have changed. Move the div.
div.parentNode.removeChild(div);
panes.floatPane.appendChild(div);
} else {
// The panes have not changed, so no need to create or move the div.
}
}
/* Pan the map to fit the InfoBox.
*/
InfoBox.prototype.panMap = function() {
// if we go beyond map, pan map
var map = this.map_;
var bounds = map.getBounds();
if (!bounds) return;
// The position of the infowindow
var position = this.latlng_;
// The dimension of the infowindow
var iwWidth = this.width_;
var iwHeight = this.height_;
// The offset position of the infowindow
var iwOffsetX = this.offsetHorizontal_;
var iwOffsetY = this.offsetVertical_;
// Padding on the infowindow
var padX = 40;
var padY = 40;
// The degrees per pixel
var mapDiv = map.getDiv();
var mapWidth = mapDiv.offsetWidth;
var mapHeight = mapDiv.offsetHeight;
var boundsSpan = bounds.toSpan();
var longSpan = boundsSpan.lng();
var latSpan = boundsSpan.lat();
var degPixelX = longSpan / mapWidth;
var degPixelY = latSpan / mapHeight;
// The bounds of the map
var mapWestLng = bounds.getSouthWest().lng();
var mapEastLng = bounds.getNorthEast().lng();
var mapNorthLat = bounds.getNorthEast().lat();
var mapSouthLat = bounds.getSouthWest().lat();
// The bounds of the infowindow
var iwWestLng = position.lng() + (iwOffsetX - padX) * degPixelX;
var iwEastLng = position.lng() + (iwOffsetX + iwWidth + padX) * degPixelX;
var iwNorthLat = position.lat() - (iwOffsetY - padY) * degPixelY;
var iwSouthLat = position.lat() - (iwOffsetY + iwHeight + padY) * degPixelY;
// calculate center shift
var shiftLng =
(iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) +
(iwEastLng > mapEastLng ? mapEastLng - iwEastLng : 0);
var shiftLat =
(iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) +
(iwSouthLat < mapSouthLat ? mapSouthLat - iwSouthLat : 0);
// The center of the map
var center = map.getCenter();
// The new map center
var centerX = center.lng() - shiftLng;
var centerY = center.lat() - shiftLat;
// center the map to the new shifted center
map.setCenter(new google.maps.LatLng(centerY, centerX));
// Remove the listener after panning is complete.
google.maps.event.removeListener(this.boundsChangedListener_);
this.boundsChangedListener_ = null;
};
function initialize() {
var myOptions = {
zoom: 8,
center: new google.maps.LatLng(-33.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP,
sensor: 'true'
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(-34, 150),
map: map
});
google.maps.event.addListener(marker, "click", function(e) {
var infoBox = new InfoBox({latlng: marker.getPosition(), map: map});
});
google.maps.event.trigger(marker, "click");
}
</script>
</head>
<body style="margin:0px; padding:0px;" onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>

Categories

Resources