Is it possible to write a custom text on Google Maps API v3 next to the marker, or I can use only the info window to do that?
To show custom text you need to create a custom overlay. Below is an example adapted from official Google documentation. You could also use this library for more "stylish" info windows
<html>
<head>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<script>
//adapded from this example http://code.google.com/apis/maps/documentation/javascript/overlays.html#CustomOverlays
//text overlays
function TxtOverlay(pos, txt, cls, map) {
// Now initialize all properties.
this.pos = pos;
this.txt_ = txt;
this.cls_ = cls;
this.map_ = map;
// We define a property to hold the image's
// div. We'll actually create this div
// upon receipt of the add() method so we'll
// leave it null for now.
this.div_ = null;
// Explicitly call setMap() on this overlay
this.setMap(map);
}
TxtOverlay.prototype = new google.maps.OverlayView();
TxtOverlay.prototype.onAdd = function() {
// Note: an overlay's receipt of onAdd() indicates that
// the map's panes are now available for attaching
// the overlay to the map via the DOM.
// Create the DIV and set some basic attributes.
var div = document.createElement('DIV');
div.className = this.cls_;
div.innerHTML = this.txt_;
// Set the overlay's div_ property to this DIV
this.div_ = div;
var overlayProjection = this.getProjection();
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
div.style.left = position.x + 'px';
div.style.top = position.y + 'px';
// We add an overlay to a map via one of the map's panes.
var panes = this.getPanes();
panes.floatPane.appendChild(div);
}
TxtOverlay.prototype.draw = function() {
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels coordinates.
// We'll use these coordinates to resize the DIV.
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
var div = this.div_;
div.style.left = position.x + 'px';
div.style.top = position.y + 'px';
}
//Optional: helper methods for removing and toggling the text overlay.
TxtOverlay.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
TxtOverlay.prototype.hide = function() {
if (this.div_) {
this.div_.style.visibility = "hidden";
}
}
TxtOverlay.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = "visible";
}
}
TxtOverlay.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility == "hidden") {
this.show();
} else {
this.hide();
}
}
}
TxtOverlay.prototype.toggleDOM = function() {
if (this.getMap()) {
this.setMap(null);
} else {
this.setMap(this.map_);
}
}
var map;
function init() {
var latlng = new google.maps.LatLng(37.9069, -122.0792);
var myOptions = {
zoom: 4,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), myOptions);
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: "Hello World!"
});
customTxt = "<div>Blah blah sdfsddddddddddddddd ddddddddddddddddddddd<ul><li>Blah 1<li>blah 2 </ul></div>"
txt = new TxtOverlay(latlng, customTxt, "customBox", map)
}
</script>
<style>
.customBox {
background: yellow;
border: 1px solid black;
position: absolute;
}
</style>
</head>
<body onload="init()">
<div id="map" style="width: 600px; height: 600px;">
</div>
</body>
</html>
By far the easiest way to add a Text Overlay is to use the MapLabel class from https://github.com/googlemaps/js-map-label
var mapLabel = new MapLabel({
text: 'Test',
position: new google.maps.LatLng(50,50),
map: map,
fontSize: 20,
align: 'right'
});
To add custom text to google maps, you can use a marker with an empty pixel for the icon:
new google.maps.Marker({
position: { lat: 0, lng: 0 },
map: map,
icon: '../res/img/empty.png',
label: {
color: '#FF0000',
fontWeight: 'bold',
text: 'Hello World',
fontSize: '20px',
},
});
Style options are listed here
It the text is static, you can use a marker and an image :
var label = new google.maps.Marker({
position: new google.maps.LatLng(50,50),
map: map,
icon: "/images/mytextasanimage.png"
});
The latest (v3) API recommends using async defer and a callback when the Maps API is loaded.
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>
To make this work you need to define the overlay class from within (or after) the initialization when the google class has been defined. Otherwise you will get google not defined errors.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 40, lng: -30 },
zoom: 3
});
TxtOverlay.prototype = new google.maps.OverlayView();
var overlay = new TxtOverlay(new google.maps.LatLng(0, 0),
"<div>Have a wonderful overlay day</div>",
"customCSSClass",
map);
}
...
//adapded from answer above
function TxtOverlay(pos, txt, cls, map) {
// Now initialize all properties.
this.pos = pos;
this.txt_ = txt;
this.cls_ = cls;
this.map_ = map;
// We define a property to hold the image's
// div. We'll actually create this div
// upon receipt of the add() method so we'll
// leave it null for now.
this.div_ = null;
this.onAdd = function() {
// Note: an overlay's receipt of onAdd() indicates that
// the map's panes are now available for attaching
// the overlay to the map via the DOM.
// Create the DIV and set some basic attributes.
var div = document.createElement('DIV');
div.className = this.cls_;
div.innerHTML = this.txt_;
// Set the overlay's div_ property to this DIV
this.div_ = div;
var overlayProjection = this.getProjection();
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
div.style.left = position.x + 'px';
div.style.top = position.y + 'px';
// We add an overlay to a map via one of the map's panes.
var panes = this.getPanes();
panes.floatPane.appendChild(div);
}
this.draw = function() {
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels coordinates.
// We'll use these coordinates to resize the DIV.
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
var div = this.div_;
div.style.left = position.x + 'px';
div.style.top = position.y + 'px';
}
this.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
this.hide = function() {
if (this.div_) {
this.div_.style.visibility = "hidden";
}
}
this.show = function() {
if (this.div_) {
this.div_.style.visibility = "visible";
}
}
this.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility == "hidden") {
this.show();
} else {
this.hide();
}
}
}
this.toggleDOM = function() {
if (this.getMap()) {
this.setMap(null);
} else {
this.setMap(this.map_);
}
}
// Explicitly call setMap() on this overlay
this.setMap(map);
}
Here is working code:
#map {
height: 500px;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="content">
<div id="map"></div>
<div class="centered">
<h1>Text Over Maps</h1>
</div>
</div>
Related
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>
I am trying to add custom overlay & Kml layer. The custom layer is working, but the KML layer is not showing at all. What would cause this?
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: 16,
center: {lat: 31.1917, lng: 27.56553},
mapTypeId: 'satellite'
});
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(31.18954, 27.56144),
new google.maps.LatLng(31.19277, 27.56806));
var srcImage = 'https://travcop.zohosites.com/selc02.png';
overlay = new USGSOverlay(bounds, 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 = '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() {
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';
};
var kmlLayer = new google.maps.KmlLayer({
url: 'https://travcop.zohosites.com/sel.kml',
suppressInfoWindows: true,
map: map
});
function showInContentWindow(text) {
var sidediv = document.getElementById('content-window');
sidediv.innerHTML = text;
}
// 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;
};
google.maps.event.addDomListener(window, 'load', initMap);
I am not sure why the KML layer is not loading. Could be the two layers loading in the same time?
Trying to create a real estate portal where data is marked in KML and the map is for a future project that is not yet displayed on Google Maps
I get a javascript error with the posted code: Uncaught ReferenceError: map is not defined.
The map variable is local to your initMap function, you need to instantiate the KmlLayer inside your initMap method.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: {lat: 31.1917, lng: 27.56553},
mapTypeId: 'satellite'
});
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(31.18954, 27.56144),
new google.maps.LatLng(31.19277, 27.56806));
var srcImage = 'https://travcop.zohosites.com/selc02.png';
overlay = new USGSOverlay(bounds, srcImage, map);
var kmlLayer = new google.maps.KmlLayer({
url: 'https://travcop.zohosites.com/sel.kml',
suppressInfoWindows: true,
preserveViewport: true,
map: map
});
}
Once I fix that, there is another error: Uncaught ReferenceError: overlayProjection is not defined, because overlayProjection isn't defined. Taking the definition from Google's example fixes that.
proof of concept fiddle
code snippet:
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: 16,
center: {
lat: 31.1917,
lng: 27.56553
},
mapTypeId: 'satellite'
});
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(31.18954, 27.56144),
new google.maps.LatLng(31.19277, 27.56806));
var srcImage = 'https://travcop.zohosites.com/selc02.png';
overlay = new USGSOverlay(bounds, srcImage, map);
var kmlLayer = new google.maps.KmlLayer({
url: 'https://travcop.zohosites.com/sel.kml',
suppressInfoWindows: true,
preserveViewport: true,
map: map
});
google.maps.event.addListener(kmlLayer, 'status_changed', function() {
console.log(kmlLayer.getStatus());
})
map.fitBounds(bounds);
}
/** #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() {
var overlayProjection = this.getProjection();
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 showInContentWindow(text) {
var sidediv = document.getElementById('content-window');
sidediv.innerHTML = text;
}
// 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;
};
google.maps.event.addDomListener(window, 'load', initMap);
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>
I am trying to change the title of the marker style
This is the HTML i am constructing and passing
But its not applying style
Could you please let em know how to resolve this
function createMarker(latlng, html) {
var tooltiponclcik = 'Company Name : 1 , <br> ' + 'Sales Off Name : 2 , <br>' + 'Warehouse Name : 3 ';
var marker = new google.maps.Marker({
position: latlng,
map: map,
zIndex: Math.round(latlng.lat() * -100000) << 5,
title:tooltiponclcik
});
markerArray.push(marker); //push local var marker into global array
}
This is my fiddle
http://jsfiddle.net/6wp7enot/16/
The title property of the Marker is used to create rollover text. That text cannot be styled with HTML formatting tags (it can only be straight text).
If you want to create formatted text the appears on mouseover you can, but you need to code that yourself.
proof of concept fiddle, using the code from my answer to: title of a marker of google map marker API
code snippet:
function createMarker(latlng, html) {
var tooltiponclcik = 'Company Name : 1 , <br> ' + 'Sales Off Name : 2 , <br>' + 'Warehouse Name : 3 ';
var marker = new google.maps.Marker({
position: latlng,
map: map,
zIndex: Math.round(latlng.lat() * -100000) << 5,
tooltip: tooltiponclcik
});
var tooltip = new Tooltip({
map: map
}, marker);
tooltip.bindTo("text", marker, "tooltip");
google.maps.event.addListener(marker, 'mouseover', function() {
tooltip.addTip();
tooltip.getPos2(marker.getPosition());
});
google.maps.event.addListener(marker, 'mouseout', function() {
tooltip.removeTip();
});
markerArray.push(marker); //push local var marker into global array
}
var geocoder;
var map;
var markerArray = [];
function initialize() {
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 normalMarker = new google.maps.Marker({
position: {
lat: 37.43,
lng: -122.14
},
title: "normal tooltip",
map: map
});
// from https://stackoverflow.com/questions/19279199/title-of-a-marker-of-google-map-marker-api/
var marker = new google.maps.Marker({
position: new google.maps.LatLng(37.442, -122.142),
map: map,
tooltip: '<B>This is a customized tooltip</B>'
});
var tooltip = new Tooltip({
map: map
}, marker);
tooltip.bindTo("text", marker, "tooltip");
google.maps.event.addListener(marker, 'mouseover', function() {
tooltip.addTip();
tooltip.getPos2(marker.getPosition());
});
google.maps.event.addListener(marker, 'mouseout', function() {
tooltip.removeTip();
});
//your code
createMarker(new google.maps.LatLng(37.45, -122.162), "stuff for infowindow");
}
google.maps.event.addDomListener(window, "load", initialize);
// The custom tooltip class
// Constructor function
function Tooltip(opts, marker) {
// Initialization
this.setValues(opts);
this.map_ = opts.map;
this.marker_ = marker;
var div = this.div_ = document.createElement("div");
// Class name of div element to style it via CSS
div.className = "tooltip";
this.markerDragging = false;
}
Tooltip.prototype = {
// Define draw method to keep OverlayView happy
draw: function() {},
visible_changed: function() {
var vis = this.get("visible");
this.div_.style.visibility = vis ? "visible" : "hidden";
},
getPos: function(e) {
var projection = this.getProjection();
// Position of mouse cursor
var pixel = projection.fromLatLngToDivPixel(e.latLng);
var div = this.div_;
// Adjust the tooltip's position
var gap = 15;
var posX = pixel.x + gap;
var posY = pixel.y + gap;
var menuwidth = div.offsetWidth;
// Right boundary of the map
var boundsNE = this.map_.getBounds().getNorthEast();
boundsNE.pixel = projection.fromLatLngToDivPixel(boundsNE);
if (menuwidth + posX > boundsNE.pixel.x) {
posX -= menuwidth + gap;
}
div.style.left = posX + "px";
div.style.top = posY + "px";
if (!this.markerDragging) {
this.set("visible", true);
}
},
getPos2: function(latLng) { // This is added to avoid using listener (Listener is not working when Map is quickly loaded with icons)
var projection = this.getProjection();
// Position of mouse cursor
var pixel = projection.fromLatLngToDivPixel(latLng);
var div = this.div_;
// Adjust the tooltip's position
var gap = 5;
var posX = pixel.x + gap;
var posY = pixel.y + gap;
var menuwidth = div.offsetWidth;
// Right boundary of the map
var boundsNE = this.map_.getBounds().getNorthEast();
boundsNE.pixel = projection.fromLatLngToDivPixel(boundsNE);
if (menuwidth + posX > boundsNE.pixel.x) {
posX -= menuwidth + gap;
}
div.style.left = posX + "px";
div.style.top = posY + "px";
if (!this.markerDragging) {
this.set("visible", true);
}
},
addTip: function() {
var me = this;
var g = google.maps.event;
var div = me.div_;
div.innerHTML = me.get("text").toString();
// Tooltip is initially hidden
me.set("visible", false);
// Append the tooltip's div to the floatPane
me.getPanes().floatPane.appendChild(this.div_);
// In IE this listener gets randomly lost after it's been cleared once.
// So keep it out of the listeners array.
g.addListener(me.marker_, "dragend", function() {
me.markerDragging = false;
});
// Register listeners
me.listeners = [
// g.addListener(me.marker_, "dragend", function() {
// me.markerDragging = false; }),
g.addListener(me.marker_, "position_changed", function() {
me.markerDragging = true;
me.set("visible", false);
}),
g.addListener(me.map_, "mousemove", function(e) {
me.getPos(e);
})
];
},
removeTip: function() {
// Clear the listeners to stop events when not needed.
if (this.listeners) {
for (var i = 0, listener; listener = this.listeners[i]; i++) {
google.maps.event.removeListener(listener);
}
delete this.listeners;
}
// Remove the tooltip from the map pane.
var parent = this.div_.parentNode;
if (parent) parent.removeChild(this.div_);
}
};
function inherit(addTo, getFrom) {
var from = getFrom.prototype; // prototype object to get methods from
var to = addTo.prototype; // prototype object to add methods to
for (var prop in from) {
if (typeof to[prop] == "undefined") to[prop] = from[prop];
}
}
// Inherits from OverlayView from the Google Maps API
inherit(Tooltip, google.maps.OverlayView);
html,
body,
#map_canvas {
height: 500px;
width: 500px;
margin: 0px;
padding: 0px
}
.tooltip {
position: absolute;
width: 145px;
padding: 5px;
border: 1px solid gray;
font-size: 9pt;
font-family: Verdana;
background-color: #fff;
color: #000;
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map_canvas" style="width:750px; height:450px; border: 2px solid #3872ac;"></div>
$(document).ready(function () {
var a = 10.109240;
var b = 76.354261;
var c = '<div style="font-weight: 500;"><dd style="color: #2196F3;">change text color <i class="fa fa-map-marker"></i></dd><dd style="color: red;">change text color <i class="fa fa-check"></i></dd></div>';
var map;
var host = window.location.origin;
var host0 = window.location.hostname;
var host1 = window.location.pathname;
var icon = "/images/map-icon.png";
map = new google.maps.Map(document.getElementById('map_canvas'),{
center: { lat: a, lng: b },
zoom: 8,
icon : icon
});
var infowindow = new google.maps.InfoWindow();
var latLng = new google.maps.LatLng(a, b);
var marker = new google.maps.Marker({
position: latLng,
map: map,
icon: icon,
title: c
});
infowindow.setContent(c);
infowindow.open(map, marker);
});
[my work][1][1]: https://i.stack.imgur.com/BlSuP.png
Below I have a snippet which generates a marker and a mapLabel (which extends the overlay class) on a google map.
I have tried to implement an event listener which deletes the overlay by right clicking, the same way I do with the marker, but it does not work!!!
I am not sure how to make it work, I have tried using "DomListener" and various iterations, but it doesn't even seem to hit that line of code when I debug.
How do I make it so that I can right click to delete my mapLabel object???
var map;
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13
});
addPlace();
placeLabel();
}
function addPlace() {
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(37.4419, -122.1419)
});
google.maps.event.addListener(marker, 'rightclick', function() {
this.setMap(null);
});
}
function placeLabel() {
var mapLabel = new MapLabel({
text: 'Right click to delete??',
position: new google.maps.LatLng(37.4419, -122.1419),
map: map,
fontSize: 21,
align: 'center'
});
google.maps.event.addListener(mapLabel, 'rightclick', function() {
this.setMap(null);
});
}
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#map_canvas {
height: 250px;
width: 500px;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://googlemaps.github.io/js-map-label/src/maplabel-compiled.js"></script>
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>
MapLabel doesn't have event listeners, but MarkerWithLabel does. The way it's done there is they have a almost-transparent div laying over the label. Any listeners are added to this div.
Something similar can be done with the MapLabel. Have a look at the source code of MarkerWithLabel here: http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerwithlabel/src/markerwithlabel.js
Here are a few code snippets from my own MapLabel alternative. It's not complete and untested, but it should get you started.
MapLabel.prototype.onAdd = function() {
var eventDiv = this.eventDiv_ = document.createElement('div');
// ...
this.drawCanvas_();
this.drawEventDiv_();
var panes = this.getPanes();
if (panes) {
panes.overlayMouseTarget.appendChild(eventDiv);
panes.overlayImage.appendChild(canvas);
}
// ...
};
Add the div to overlayMouseTarget, the uppermost layer.
MapLabel.prototype.drawEventDiv_ = function() {
var eventDiv = this.eventDiv_;
if (!eventDiv) return;
var canvasWidth = this.canvas_.getContext('2d').measureText(this.get('text')).width;
var canvasHeight = this.get('fontSize');
eventDiv.innerHTML = this.get('text');
// This is needed for proper behavior on MSIE:
eventDiv.setAttribute("onselectstart", "return false;");
eventDiv.setAttribute("ondragstart", "return false;");
var eventDivStyle = this.eventDiv_.style;
eventDivStyle.width = canvasWidth + 'px';
eventDivStyle.height = canvasHeight + 'px';
eventDivStyle.cssText = this.get('text');
eventDivStyle.font = this.get('fontSize') + 'px ' + this.get('fontFamily');
eventDivStyle.position = 'absolute';
eventDivStyle.opacity = 0.01; // Don't use 0; DIV won't be clickable on MSIE
eventDivStyle.MsFilter = "\"progid:DXImageTransform.Microsoft.Alpha(opacity=1)\"";
eventDivStyle.filter = "alpha(opacity=1)"; // For MSIE
eventDivStyle.marginLeft = this.getMarginLeft_(canvasWidth) + 'px';
eventDivStyle.zIndex = /** #type number */(this.get('zIndex'));
};
To add an event listener do this:
google.maps.event.addDomListener(this.eventDiv_, 'click', function (e) {
//..
this_.cAbortEvent(e); // Prevent click from being passed on to map
});
cAbortEvent prevents bubbling.
MapLabel.prototype.cAbortEvent = function(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.cancelBubble = true;
if (e.stopPropagation) {
e.stopPropagation();
}
};
Try using 'mousedown' instead of 'rightclick', then distinguish which type of click it was.
google.maps.event.addListener(mapLabel, 'mousedown', function(e) {
if(e.which === 3)
{
this.setMap(null);
}
});
Mouse Click Codes MSDN API:
0: No button
1: Left button
2: Middle button (if present)
3: Right button
I have an event listener for mousedown. The event fires the same result on left and right button press. How do I determine which mouse button has been pressed ?
google.maps.event.addListener(map, 'mousedown', function (e) {
console.log(e);
}
The event (e) returns Dm Class object and has only the properties:
Z, latLng, pixel.
It also returns prototype function stop().
After much of head banging, I think I have a workaround for this solution. Any better ideas and suggestions would be very much appreciated.
I was trying to mimic the Google Earth's creating path feature in Google Maps. Here is my experimental code:
function PolylineMarker(bounds, image, map) {
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
// We define a property to hold the image's
// div. We'll actually create this div
// upon receipt of the add() method so we'll
// leave it null for now.
this.div_ = null;
// Explicitly call setMap() on this overlay
this.setMap(map);
}
PolylineMarker.prototype = new google.maps.OverlayView();
PolylineMarker.prototype.onAdd = function() {
// Note: an overlay's receipt of onAdd() indicates that
// the map's panes are now available for attaching
// the overlay to the map via the DOM.
// Create the DIV and set some basic attributes.
var div = document.createElement('div');
div.style.border = "none";
div.style.borderWidth = "0px";
div.style.position = "absolute";
// Create an 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);
// Set the overlay's div_ property to this DIV
this.div_ = div;
// We add an overlay to a map via one of the map's panes.
// We'll add this overlay to the overlayImage pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
}
PolylineMarker.prototype.draw = function() {
// Size and position the overlay. We use a southwest and northeast
// position of the overlay to peg it to the correct position and size.
// We need to retrieve the projection from this overlay to do this.
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels 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 - 3 ) + 'px';
div.style.top = (ne.y - 3 ) + 'px';
div.style.width = (ne.x - sw.x + 6) + 'px';
div.style.height = (sw.y - ne.y + 6) + 'px';
div.style.background = 'red';
div.style.margin = '0 auto';
}
PolylineMarker.prototype.onRemove = function() {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
// Note that the visibility property must be a string enclosed in quotes
PolylineMarker.prototype.hide = function() {
if (this.div_) {
this.div_.style.visibility = "hidden";
}
}
PolylineMarker.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = "visible";
}
}
PolylineMarker.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility == "hidden") {
this.show();
} else {
this.hide();
}
}
}
PolylineMarker.prototype.toggleDOM = function() {
if (this.getMap()) {
this.setMap(null);
} else {
this.setMap(this.map_);
}
}
function initialize() {
var map = new google.maps.Map(document.getElementById("map-canvas"), {
zoom: 15,
center: new google.maps.LatLng(27.703744, 85.333729),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var polyOptions = {
strokeColor: '#000000',
strokeOpacity: 1.0,
strokeWeight: 1,
map: map,
clickable: false,
icons: [{
'icon': {
path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
strokeOpacity: 0.8,
strokeWeight: 2,
strokeColor: '#000'
},
'offset': '100%',
'repeat': '100px'
}]
};
var polyline = null;
var mouseMoveHandler = null;
var button = '';
var isMouseReleased = false;
google.maps.event.addDomListener(document.getElementById("map-canvas"), 'mousedown', function(e) {
button = e.button;
isMouseReleased = false;
return false;
});
var mouseDownHandler = google.maps.event.addListener(map, 'mousedown', function (e) {
map.setOptions({
'draggable': false
});
if (!polyline) {
polyline = new google.maps.Polyline(polyOptions);
}
isMouseReleased = false;
setTimeout(function() {
if (! isMouseReleased) {
mouseMoveHandler = google.maps.event.addListener(map, 'mousemove', function (e) {
if (button == 0) {
var path = polyline.getPath();
/**
* Add new overlay
*/
var image = '';
var bounds = new google.maps.LatLngBounds(e.latLng, e.latLng);
var overlay = new PolylineMarker(bounds, image, map);
path.push(e.latLng);
}
e.stop();
});
}
}, 100);
e.stop();
});
google.maps.event.addListener(map, 'mouseup', function (e) {
isMouseReleased = true;
google.maps.event.clearListeners(map, 'mousemove');
google.maps.event.removeListener(mouseMoveHandler);
if (button == 0) {
polyline.getPath().push(e.latLng);
/**
* Add new overlay
*/
var image = '';
var bounds = new google.maps.LatLngBounds(e.latLng, e.latLng);
var overlay = new PolylineMarker(bounds, image, map);
map.setOptions({
'draggable': true
});
}
e.stop();
});
} // end of initialize function
google.maps.event.addDomListener(window, 'load', initialize);
Here is my demo : http://jsfiddle.net/himal/C6jMU/2/
which is a property of the event object, which most people label as e
in their event handlers. It contains the key code of the key which was
pressed to trigger the event.
As per your code add which to it.
google.maps.event.addListener(map, 'mousedown', function (e) {
console.log(e.which);
}
Check console:
left Click: 1
middle button click: 2
right click: 3
After checking Google docs, instead of getting the mouse keyCodes you can directly use their mouse event.
Go right to its object. BUT google for a reason I dont know change the object var name (xa,ta,ha...), so get it by its position is much more safe and will prevent you from having to change it from time to time. This works for me:
google.maps.event.addListener(map, 'mousedown', function (e) {
console.log('Button: ' + Object.value(e)[1].which);
}
Console:
Button: 1