I need to create a a text box between the route directions like in here :
For start i was thinking to add tooltip...but i can't place them in the middle of the route like in the picture, or set it's position to be relative.
You can create a custom overlay as described in the documentation:
https://developers.google.com/maps/documentation/javascript/customoverlays
The sample code snippet might be
function routeOverlay(point, map, content) {
this._point = point;
this._map = map;
this.div_ = null;
this._cnt = content;
this.setMap(map);
}
routeOverlay.prototype = new google.maps.OverlayView();
routeOverlay.prototype.onAdd = function () {
var div = document.createElement('div');
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.backgroundColor = 'white';
div.style.position = 'absolute';
div.style.padding = '4px';
div.style.zIndex = 1000;
div.innerHTML = this._cnt;
this.div_ = div;
// Add the element to the "overlayLayer" pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
}
routeOverlay.prototype.draw = function () {
var overlayProjection = this.getProjection();
var p = overlayProjection.fromLatLngToDivPixel(this._point);
this.div_.style.left = p.x + 'px';
this.div_.style.top = p.y + 'px';
}
routeOverlay.prototype.onRemove = function () {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
routeOverlay.prototype.hide = function() {
if (this.div_) {
// The visibility property must be a string enclosed in quotes.
this.div_.style.visibility = 'hidden';
}
};
routeOverlay.prototype.show = function() {
if (this.div_) {
this.div_.style.visibility = 'visible';
}
};
Later in you code you should create this overlay. For example:
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var ind = (response.routes[0].overview_path.length - response.routes[0].overview_path.length % 2) / 2;
var rover = new routeOverlay(response.routes[0].overview_path[ind], map, 'Add your HTML here');
rover.show();
} else {
window.alert('Directions request failed due to ' + status);
}
I have modified your jsfiddle: http://jsfiddle.net/h54tmmcb/14/
You should create corresponding styles and corresponding content for the overlay.
Hope this helps!
Related
Question One: When closing an "infobox" how can I make it maps zoom back out?
Question Two: How would I make it so that only one "infobox" is open at a time?
I have tried adding:
google.maps.event.addListener(map, 'zoom_changed', function(){
if (! markers.length) { return; }
for (i in markers) {
markers[i].infoBox.close();
}
});
However the code dose not seem to work. Any thoughts?
function InfoBox(opts) {
google.maps.OverlayView.call(this);
this.latlng_ = opts.latlng;
this.map_ = opts.map;
this.content = opts.content;
this.offsetVertical_ = -195;
this.offsetHorizontal_ = 5;
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);
});
this.setMap(this.map_);
}
InfoBox.prototype = new google.maps.OverlayView();
InfoBox.prototype.remove = function () {
if (this.div_) {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
this.createElement();
if (!this.div_) return;
var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
if (!pixPosition) return;
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';
};
InfoBox.prototype.createElement = function () {
var panes = this.getPanes();
var div = this.div_;
if (!div) {
div = this.div_ = document.createElement("div");
div.className = "infobox"
var contentDiv = document.createElement("div");
contentDiv.className = "content"
contentDiv.innerHTML = this.content;
var closeBox = document.createElement("div");
closeBox.className = "close";
closeBox.innerHTML = "x";
div.appendChild(closeBox);
function removeInfoBox(ib) {
return function () {
ib.setMap(null);
};
}
google.maps.event.addDomListener(closeBox, 'click', removeInfoBox(this));
div.appendChild(contentDiv);
div.style.display = 'none';
panes.floatPane.appendChild(div);
this.panMap();
} else if (div.parentNode != panes.floatPane) {
div.parentNode.removeChild(div);
panes.floatPane.appendChild(div);
} else {
.
}
}
InfoBox.prototype.panMap = function () {
var map = this.map_;
var bounds = map.getBounds();
if (!bounds) return;
var position = this.latlng_;
var iwWidth = this.width_;
var iwHeight = this.height_;
var iwOffsetX = this.offsetHorizontal_;
var iwOffsetY = this.offsetVertical_;
var padX = 40;
var padY = 40;
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;
var mapWestLng = bounds.getSouthWest().lng();
var mapEastLng = bounds.getNorthEast().lng();
var mapNorthLat = bounds.getNorthEast().lat();
var mapSouthLat = bounds.getSouthWest().lat();
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;
var shiftLng =
(iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) +
(iwEastLng > mapEastLng ? mapEastLng - iwEastLng : 0);
var shiftLat =
(iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) +
(iwSouthLat < mapSouthLat ? mapSouthLat - iwSouthLat : 0);
var center = map.getCenter();
var centerX = center.lng() - shiftLng;
var centerY = center.lat() - shiftLat;
map.setCenter(new google.maps.LatLng(centerY, centerX));
google.maps.event.removeListener(this.boundsChangedListener_);
this.boundsChangedListener_ = null;
};
function initialize() {
var markers = [];
var myOptions = {
zoom: 3,
center: new google.maps.LatLng(-5.646, 20.0611),
mapTypeId: google.maps.MapTypeId.ROADMAP,
sensor: 'true'
}
var map = new google.maps.Map(document.getElementById("canvas-map"), myOptions);
var data = [
{
'id':1,
'content':'Hello my name is marker, I\'m from Google',
'position': {
'lat':-33,
'lng':150
}
},
{
'id':2,
'content':'I am the content of this infobox. Wow, what a text.<br><br>The good thing is: Tags are also possible',
'position': {
'lat':-34,
'lng':150
}
},
]
for (var i = 0; i < data.length; i++) {
var current = data[i];
var marker = new google.maps.Marker({
position: new google.maps.LatLng(current.position.lat, current.position.lng),
map: map,
content: current.content
});
markers.push(marker);
marker.addListener('click', function() {
map.setZoom(8);
map.setCenter(marker.getPosition());
});
google.maps.event.addListener(markers[i], "click", function (e) {
map.zoomOut();
map.setCenter(this.getPosition());
var infoBox = new InfoBox({
latlng: this.getPosition(),
map: map,
content: this.content
});
});
}
}
Answer to question 1
If you want the map to zoom out when the user closes an info window, you can listen for the closeclick event on the info window object.
infoWindow.addListener('closeclick', function() {
map.setZoom(3); // Set the desired zoom level
});
I couldn't get your code to work so I created a basic example of the above functionality in action. Clicking on the marker opens an info window and zooms the map in. Closing the info window, zooms the map back out.
Answer to question 2
Check out geocodezip's comments to your question. He provides links to previous questions that could help you figure out how to have only one info window open at a time.
in my google map I have added a control that shows zoom level. But it isn't updating the value. I am using map.getZoom() function.
var divRef = document.createElement('div');
var ref = document.createElement("div");
ref.setAttribute("id", "ref");
divRef.appendChild(ref);
var controlText1 = document.createElement('div');
controlText1.className = "zoom";
var label1 = document.createElement('LABEL');
var t = document.createTextNode("zoom level ");
label1.setAttribute = ("for", "zoom");
label1.appendChild(t);
controlText1.appendChild(label1);
ref.appendChild(controlText1);
var tzoom = document.createTextNode(map.getZoom());
controlText1.appendChild(tzoom);
ref.appendChild(controlText1);
map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(divRef);
When the map is loaded for the first time it shows the zoom level control correctly but if I scroll o change zoom with the buttons, the value isn't updated.
How can I refresh controls ? or should I set this control in a different way?
Here's a fiddle with the control in the left_bottom corner. When I zoom in-out the value isn't updated.
https://jsfiddle.net/3b31qfsm/
use a 'zoom_changed' event listener to update the content of the control:
google.maps.event.addListener(map, 'zoom_changed', function() {
tzoom.textContent = map.getZoom();
});
proof of concept fiddle
code snippet:
var map;
var chicago = {
lat: 41.85,
lng: -87.65
};
function CenterControl(controlDiv, map) {
var divRef = document.createElement('div');
var ref = document.createElement("div");
ref.setAttribute("id", "ref");
divRef.appendChild(ref);
var controlText1 = document.createElement('div');
controlText1.className = "zoom";
var label1 = document.createElement('LABEL');
controlText1.style.color = 'red';
controlText1.style.fontFamily = 'Roboto,Arial,sans-serif';
controlText1.style.fontSize = '16px';
controlText1.style.lineHeight = '38px';
controlText1.style.paddingLeft = '5px';
controlText1.style.paddingRight = '5px';
controlText1.style.backgroundColor = '#fff';
controlText1.style.border = '2px solid #fff';
controlText1.style.borderRadius = '3px';
controlText1.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
var t = document.createTextNode("zoom level ");
label1.setAttribute = ("for", "zoom");
label1.appendChild(t);
controlText1.appendChild(label1);
ref.appendChild(controlText1);
var tzoom = document.createTextNode(map.getZoom());
controlText1.appendChild(tzoom);
google.maps.event.addListener(map, 'zoom_changed', function() {
tzoom.textContent = map.getZoom();
})
ref.appendChild(controlText1);
map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(divRef);
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = '#fff';
controlUI.style.border = '2px solid #fff';
controlUI.style.borderRadius = '3px';
controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
controlUI.style.cursor = 'pointer';
controlUI.style.marginBottom = '22px';
controlUI.style.textAlign = 'center';
controlUI.title = 'Click to recenter the map';
controlDiv.appendChild(controlUI); // Set CSS for the control interior.
var controlText = document.createElement('div');
controlText.style.color = 'rgb(25,25,25)';
controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
controlText.style.fontSize = '16px';
controlText.style.lineHeight = '38px';
controlText.style.paddingLeft = '5px';
controlText.style.paddingRight = '5px';
controlText.innerHTML = 'Center Map';
controlUI.appendChild(controlText); // Setup the click event listeners: simply set the map to Chicago.
controlUI.addEventListener('click', function() {
map.setCenter(chicago);
});
}
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: chicago
});
var centerControlDiv = document.createElement('div');
var centerControl = new CenterControl(centerControlDiv, map);
centerControlDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);
}
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
I am having some difficulties where my listeners appear to cancel each other out only when I set a rectangle to the map, but not when I call an alert or anything else.
This works perfectly:
google.maps.event.addDomListener(document.getElementById("overlay" + me), 'click', function () {
displayMessage(me); //displays the current overlay index on screen (IE 1 of 30)
});
The above simply displays the index of the overlay on the map (IE 1 of 30). It works at every overlay clicked with the proper overlay index.
This not so much:
google.maps.event.addDomListener(document.getElementById("overlay" + me), 'click', function () {
alert("Called");
curOverlayRectangle.setOptions(overlayRectangleOptions); //defined by C# to js
curOverlayRectangle.setBounds(incomingOverlayBounds[me]);
curOverlayRectangle.setMap(map);
alert("Finished");
});
The above is supposed to add a rectangle over the overlay already on the map. What it actually does is add the rectangle for the first overlay clicked, but then if I click another overlay, nothing happens.
It appears that the listener is never called because once I click the first overlay, it goes through and says finished with the rectangle drawn. I then proceed to click another overlay and no alert occurs...
I have been working on this for quite some time, please help! Thanks!
EDIT1:
//get is simply the index
function tempAddListener(get) {
//alert("adding: " + get);
if (document.getElementById("overlay" + get) != null) { //check to see if div is there
google.maps.event.addDomListener(document.getElementById("overlay" + get), 'click', function () {
displayMessage("listener fired at overlay: " + get); //if enabled, works fine
//displayOverlayRectangle(incomingOverlayBounds[get]); //if enabled, listener fires but seems to delete all my other listeners for the overlays
});
} else {
//could not find the div
}
}
Edit2
//took out all defines
//#region geoObjs
var incomingOverlayBounds = [];
var incomingOverlaySourceURL = [];
var incomingOverlayRotation = [];
var incomingOverlayRectangle = [];
function initOverlays(){
//most of these are taken out
incomingOverlayBounds[0] = new google.maps.LatLngBounds( new google.maps.LatLng(29.7883456702236,-82.384843759249), new
incomingOverlayRotation[16] = 0;
incomingOverlayBounds[17] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4715356702236,-82.3839748493845), new google.maps.LatLng(29.51265,-82.33674));
incomingOverlaySourceURL[17] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_20.jpg";
incomingOverlayRotation[17] = 0;
incomingOverlayBounds[18] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4584356702236,-82.3840587432067), new google.maps.LatLng(29.49955,-82.33683));
incomingOverlaySourceURL[18] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_21.jpg";
incomingOverlayRotation[18] = 0;
incomingOverlayBounds[19] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4431556702236,-82.4158516259991), new google.maps.LatLng(29.48427,-82.36863));
incomingOverlaySourceURL[19] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_022.jpg";
incomingOverlayRotation[19] = 0;
incomingOverlayBounds[20] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4593656702236,-82.4157191765652), new google.maps.LatLng(29.50048,-82.36849));
incomingOverlaySourceURL[20] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_023.jpg";
incomingOverlayRotation[20] = 0;
incomingOverlayBounds[21] = new google.maps.LatLngBounds( new google.maps.LatLng(29.4736856702236,-82.4151858519302), new google.maps.LatLng(29.5148,-82.36795));
incomingOverlaySourceURL[21] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_024.jpg";
incomingOverlayRotation[21] = 0;
incomingOverlaySourceURL[51] = "http://ufdcimages.uflib.ufl.edu/UF/00/07/17/26/00027/12001_1968_2KK_054.jpg";
incomingOverlayRotation[51] = 0;
displayIncomingOverlays();
}
//#endregion
function initialize() {
//initialize google map objects
map = new google.maps.Map(document.getElementById(gmapPageDivId), gmapOptions); //initialize map
initOverlays(); //initialize all the incoming overlays
}
var incomingOverlayBounds = [];
var incomingOverlaySourceURL = [];
var incomingOverlayRotation = [];
var overlays = [];
function displayIncomingOverlays() {
for (var i = 0; i < incomingOverlayBounds.length; i++) {
overlaysOnMap[i] = new CustomOverlay(incomingOverlayBounds[i], incomingOverlaySourceURL[i], map, incomingOverlaySourceURL[i]);
overlaysOnMap[i].setMap(map);
//displayOverlayRectangle(incomingOverlayBounds[i]); //add all the rectangles
}
}
function CustomOverlay(bounds, image, map, rotation) {
//iterate here
overlayCount++;
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
preservedRotation = rotation;
if (overlayPrevious != null) {
overlayPrevious.setMap(null);
}
// We 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;
}
CustomOverlay.prototype.onAdd = function () {
if (overlayPrevious != null) {
overlayPrevious.setMap(null);
}
// 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.id = "overlay" + overlaysOnMap.indexOf(this);
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
div.style.opacity = preserveOpacity;
// Create an IMG element and attach it to the DIV.
var img = document.createElement('img');
img.src = incomingOverlaySourceURL[overlaysOnMap.indexOf(this)]; //this.image
img.style.width = '100%';
img.style.height = '100%';
img.style.position = 'absolute';
div.appendChild(img);
//get the index
var overlayIndex = overlaysOnMap.indexOf(this);
// 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 overlayLayer pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
//add the listener
tempAddListener(overlayIndex);
};
CustomOverlay.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 + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
//for a preserved rotation
if (preservedRotation != 0) {
//keepRotate(preservedRotation);
}
};
//CustomOverlay.prototype.onRemove = function () {
// this.div_.parentNode.removeChild(this.div_);
// this.div_ = null;
//};
function tempAddListener(get) {
alert("div: "+document.getElementById("overlay" + get).innerHTML);
alert("adding with index: " + get);
if (document.getElementById("overlay" + get) != null) { //check to see if div is there
google.maps.event.addDomListener(document.getElementById("overlay" + get), 'click', function () {
alert("listener fired at overlay: " + get);
displayOverlayRectangle(incomingOverlayBounds[get]);
//alert(incomingOverlayBounds[get]);
//overlayRectangles[get] = displayOverlayRectangle(incomingOverlayBounds[get]);
//overlayRectangles[get].setMap(map);
});
} else {
//could not find the div
}
}
function displayOverlayRectangle(bounds) {
//2do: set drawing manager, set mode, match listeners of rectangle
var tempOverlayRectangle = new google.maps.Rectangle();
var tempOverlayRectangleOptions = {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.1,
editable: true,
draggable: true,
//strokeOpacity: 0.2,
//strokeWeight: 1,
//fillOpacity: 0.0,
zindex: 5
};
tempOverlayRectangle.setOptions(tempOverlayRectangleOptions);
tempOverlayRectangle.setBounds(bounds);
tempOverlayRectangle.setMap(map);
google.maps.event.addListener(tempOverlayRectangle, "click", function () {
alert("can't touch this");
});
//return tempOverlayRectangle;
//tempOverlayRectangle.setOptions(tempOverlayRectangleOptions);
//tempOverlayRectangle.setBounds(bounds);
//tempOverlayRectangle.setMap(map);
}
//start this whole mess once
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<div id="googleMap"></div>
UPDATE
It appears that any map code on the listener will invalidate the other listeners. (IE I tried it with the following code and it still only ran once)
google.maps.event.addDomListener(document.getElementById("overlay" + get), 'click', function () {
if (map.getMapTypeId() == 'TERRAIN') {
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
} else {
map.setMapTypeId(google.maps.MapTypeId.TERRAIN);
}
});
SOLVED
Bottom line, the overlay I was creating could not be accessed appropriately by the DOM. Thus, I created an invisible rectangle to overlay on top of my overlay which can be accessed.
Snippet:
var incomingOverlayBounds = []; //defined in c# to js on page
var incomingOverlaySourceURL = []; //defined in c# to js on page
var incomingOverlayRotation = []; //defined in c# to js on page
var ghostOverlayRectangle = []; //holds ghost overlay rectangles (IE overlay hotspots)
var ghostOverlayRectangleOptions = { //define options for ghost rectangle
strokeColor: "#FF0000", //color doesnt matter
strokeOpacity: 0.0, //make border invisible
strokeWeight: 1, //should not matter?
fillColor: "#FF0000", //color doesnt matter
fillOpacity: 0.0, //make fill transparent
editable: false, //just to be sure?
draggable: false, //just to be sure?
zindex: 6 //perhaps higher?
};
var visibleOverlayRectangleOptions = { //define options for visible rectangle
strokeColor: "#FF0000", //for testing (red)
strokeOpacity: 0.8, //for testing
strokeWeight: 2, //for testing
fillColor: "#FF0000", //for testing (red)
fillOpacity: 0.1, //for testing
editable: true, //sobek standard
draggable: true, //sobek standard
//strokeOpacity: 0.2, //sobek standard
//strokeWeight: 1, //sobek standard
//fillOpacity: 0.0, //sobek standard
zindex: 5 //sobek standard
};
var visibleOverlayRectangle = new google.maps.Rectangle(); //init maybe move to array later
//Displays all the overlays sent from the C# code. Also calls displayGhostOverlayRectangle.
function displayIncomingOverlays() {
//go through and display overlays as long as there is an overlay to display
for (var i = 0; i < incomingOverlayBounds.length; i++) {
overlaysOnMap[i] = new CustomOverlay(incomingOverlayBounds[i], incomingOverlaySourceURL[i], map, incomingOverlayRotation[i]);
overlaysOnMap[i].setMap(map); //set the overlay to the map
displayGhostOverlayRectangle(incomingOverlayBounds[i],i); //add all the ghost rectangles
}
}
//Displays an invisible rectangle on top of the overlay div (creates a hotspot). This rectangle is used as a psuedo listener if the 'overlay div' is clicked. This solved issue of creating listener for overlay div directly.
//Supporting URL: http://stackoverflow.com/questions/17025240/google-maps-listener-only-running-once
function displayGhostOverlayRectangle(ghostBounds,ghostIndex) {
ghostOverlayRectangle[ghostIndex] = new google.maps.Rectangle(); //init rect
ghostOverlayRectangle[ghostIndex].setOptions(ghostOverlayRectangleOptions); //set options
ghostOverlayRectangle[ghostIndex].setBounds(ghostBounds); //set bounds
ghostOverlayRectangle[ghostIndex].setMap(map); //set to map
//create the listener for this ghost rectangle
google.maps.event.addListener(ghostOverlayRectangle[ghostIndex], 'click', function () {
displayVisibleOverlayRectangle(ghostBounds, ghostIndex); //add the visible rectangles
});
}
//Displays the visible rectangle which is used to edit an overlay. Called by the ghost listener.
function displayVisibleOverlayRectangle(bounds, overlayIndex) {
visibleOverlayRectangle.setOptions(visibleOverlayRectangleOptions);
visibleOverlayRectangle.setBounds(bounds);
visibleOverlayRectangle.setMap(map);
}
//Starts the creation of a custom overlay div which contains a rectangular image.
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
function CustomOverlay(bounds, image, map, rotation) {
overlayCount++; //iterate how many overlays have been drawn
this.bounds_ = bounds; //set the bounds
this.image_ = image; //set source url
this.map_ = map; //set to map
preservedRotation = rotation; //set the rotation
this.div_ = null; //defines 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.
}
//Continues support for adding an custom overlay
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
// 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.
CustomOverlay.prototype.onAdd = function () {
// Create the DIV and set some basic attributes.
var div = document.createElement("div");
div.id = "overlay" + overlaysOnMap.indexOf(this);
div.style.borderStyle = 'none';
div.style.borderWidth = '0px';
div.style.position = 'absolute';
div.style.opacity = preserveOpacity;
// Create an IMG element and attach it to the DIV.
var img = document.createElement('img');
img.src = incomingOverlaySourceURL[overlaysOnMap.indexOf(this)]; //this.image
img.style.width = '100%';
img.style.height = '100%';
img.style.position = 'absolute';
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 overlayLayer pane.
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
};
//Continues support for adding an custom overlay
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
CustomOverlay.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 + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
//for a preserved rotation
if (preservedRotation != 0) {
keepRotate(preservedRotation);
}
};
//Not currently used
//Supporting URL: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays
CustomOverlay.prototype.onRemove = function () {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
};
I'm working with a Google Maps example code , this : http://www.wolfpil.de/v3/drag-from-outside.html which has 3 draggable markers outside the map. All I want is to use the revert 'invalid' option to make the markers return to the original position in case the markers do not drop in the map but I've failed to put it in the right line. Could you please give me a hint where do I have to put it to make it work?
function initDrag(e) {
if(!e) var e = window.event;
// Drag image's parent div element
obj = e.target ? e.target.parentNode : e.srcElement.parentElement;
if(obj.className != "drag") {
if(e.cancelable) e.preventDefault();
obj = null;
return;
}
if (obj) {
// The currently dragged object always gets the highest z-index
z_index++;
obj.style.zIndex = z_index.toString();
xpos = e.clientX - obj.offsetLeft;
ypos = e.clientY - obj.offsetTop;
document.onmousemove = moveObj;
}
return false;
}
function moveObj(e) {
if(obj && obj.className == "drag") {
if(!e) var e = window.event;
obj.style.left = e.clientX - xpos + "px";
obj.style.top = e.clientY - ypos + "px";
obj.onmouseup = function() {
var gd = map.getDiv();
var mLeft = gd.offsetLeft;
var mTop = gd.offsetTop;
var mWidth = gd.offsetWidth;
var mHeight = gd.offsetHeight;
var areaLeft = drag_area.offsetLeft;
var areaTop = drag_area.offsetTop;
var oWidth = obj.offsetWidth;
var oHeight = obj.offsetHeight;
// The object's pixel position relative to the document
var x = obj.offsetLeft + areaLeft + oWidth/2;
var y = obj.offsetTop + areaTop + oHeight/2;
// Check if the cursor is inside the map div
if (x > mLeft && x < (mLeft + mWidth) && y > mTop && y < (mTop + mHeight)) {
// Difference between the x property of iconAnchor
// and the middle of the icon width
var anchorDiff = 1;
// Find the object's pixel position in the map container
var g = google.maps;
var pixelpoint = new g.Point(x - mLeft -anchorDiff, y - mTop + (oHeight/2));
// Corresponding geo point on the map
var proj = dummy.getProjection();
var latlng = proj.fromContainerPixelToLatLng(pixelpoint);
// Create a corresponding marker on the map
var src = obj.firstChild.getAttribute("src");
createDraggedMarker(latlng, src);
// Create dragged marker anew
fillMarker();
}
};
}
return false;
}
function fillMarker() {
var m = document.createElement("div");
m.style.position = "absolute";
m.style.width = "32px";
m.style.height = "32px";
var left;
if (obj.id == "m1") {
left = "0px";
} else if (obj.id == "m2") {
left = "50px";
} else if (obj.id == "m3") {
left = "100px";
}
m.style.left = left;
// Set the same id and class attributes again
// m.setAttribute("id", obj.id);
// m.setAttribute((document.all?"className":"class"), "drag");
m.id = obj.id;
m.className = "drag";
// Append icon
var img = document.createElement("img");
img.src = obj.firstChild.getAttribute("src");
img.style.width = "32px";
img.style.height = "32px";
m.appendChild(img);
drag_area.replaceChild(m, obj);
// Clear initial object
obj = null;
}
function highestOrder() {
/**
* The currently dragged marker on the map
* always gets the highest z-index too
*/
return z_index;
}
function createDraggedMarker(point, src) {
var g = google.maps;
var image = new g.MarkerImage(src,
new g.Size(32, 32),
new g.Point(0, 0),
new g.Point(15, 32));
var shadow = new g.MarkerImage("http://maps.gstatic.com/mapfiles/kml/paddle/A_maps.shadow.png",
new g.Size(59, 32),
new g.Point(0, 0),
new g.Point(15, 32));
var marker = new g.Marker({ position: point, map: map,
clickable: true, draggable: true,
raiseOnDrag: false,
icon: image, shadow: shadow, zIndex: highestOrder()
});
g.event.addListener(marker, "click", function() {
actual = marker;
var lat = actual.getPosition().lat();
var lng = actual.getPosition().lng();
iw.setContent(lat.toFixed(6) + ", " + lng.toFixed(6));
iw.open(map, this);
});
g.event.addListener(marker, "dragstart", function() {
// Close infowindow when dragging the marker whose infowindow is open
if (actual == marker) iw.close();
// Increment z_index
z_index++;
marker.setZIndex(highestOrder());
});
}
After the code snippet
fillMarker();
}
add an else statement like this:
fillMarker();
} else {
//if the marker does not land on the map reset marker location
var left;
if (obj.id == "m1") {
left = "0px";
} else if (obj.id == "m2") {
left = "50px";
} else if (obj.id == "m3") {
left = "100px";
}
obj.style.left = left;
obj.style.top = "70px";
}
jsFiddle to full code: http://jsfiddle.net/6ECVs/
I'm trying to create a control like the one on google maps to show different maps (Map, Satellite, Terrain). Basically, a button-like div that when I click it it displays a drop down list of checkboxes and a button. I can create the drop down list of checkboxes but I can't make the div to behave like that control of google maps.
What am I missing?
My list appears inside the "button" and not below.
Here is my code
function MyControl(controlDiv, map) {
controlDiv.style.padding = '5px';
var controlUI = document.createElement('DIV');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '2px';
controlUI.style.cursor = 'pointer';
controlUI.style.textAlign = 'left';
controlUI.title = 'Click to show';
controlDiv.appendChild(controlUI);
var dropdown = document.createElement('DIV');
dropdown.style.width = '100px';
var chkOne = document.createElement( "input" );
chkOne.type = "checkbox";
chkOne.id = "chkOne";
chkOne.value = "One";
chkOne.checked = false;
var lblOne = document.createElement('label')
lblOne.htmlFor = "chkOne";
lblOne.appendChild(document.createTextNode('One'));
var chkTwo = document.createElement( "input" );
chkTwo.type = "checkbox";
chkTwo.id = "chkTwo";
chkTwo.value = "Two";
chkTwo.checked = false;
var lblTwo = document.createElement('label')
lblTwo.htmlFor = "chkTwo";
lblTwo.appendChild(document.createTextNode('Two'));
var btnDone = document.createElement( "input" );
btnDone.type = "button";
btnDone.name = "btnDone";
btnDone.value = "Done";
dropdown.appendChild(chkOne);
dropdown.appendChild(lblOne);
dropdown.appendChild(document.createElement( "BR" ));
dropdown.appendChild(chkTwo);
dropdown.appendChild(lblTwo);
dropdown.appendChild(document.createElement( "BR" ));
dropdown.appendChild(btnDone);
controlUI.appendChild(dropdown);
google.maps.event.addDomListener(controlUI, 'click', function() {
dropdown.visible = true;
});
btnDone.addEventListener("click", showList, false);
function showList() {
dropdown.visible = false;
}
}
// Create the DIV to hold the control and call the HomeControl() constructor
// passing in this DIV.
var accidentsToShowDiv = document.createElement('DIV');
// Set CSS for the control border.
accidentsToShowDiv.style.backgroundColor = 'white';
accidentsToShowDiv.style.borderStyle = 'solid';
accidentsToShowDiv.style.borderWidth = '2px';
accidentsToShowDiv.style.cursor = 'pointer';
accidentsToShowDiv.style.textAlign = 'left';
accidentsToShowDiv.title = 'Accidents to Show';
var homeControl = new MyControl(accidentsToShowDiv, mainMap);
accidentsToShowDiv.index = 1;
mainMap.controls[google.maps.ControlPosition.TOP_RIGHT].push(accidentsToShowDiv);
You forgot to add boxshadow
controlUI.style.boxShadow = '0 1px 3px rgba(0,0,0,0.5)';