I'm working on a Google Maps app, and using the infobox plugin from Google I've run into a bit of trouble.
It seems that the close button no longer wants to work on the infoboxes, which is strange because I did have it working before, as I am turning a kiosk app into a web app. I am using a custom close button for this, but even if I switch it to google's default close button I get the same result. The infobox only closes when you click another marker on the map to open another infobox. Once one is open, it seems to be impossible to remove it. The code has not changed from the kiosk to the web version of this app...
Here is some code I'm using to instantiate the markers:
var displayingInfoBox;
// Options for the infobox
var popoverOptions = {
disableAutoPan : false,
maxWidth : 0,
closeBoxMargin : '8px 32px',
closeBoxURL : 'url/to/close_button/image.png',
infoBoxClearance : new google.maps.Size(50,50),
isHidden : false,
enableEventPropagation : true,
boxStyle: {
border : 'none',
opacity : 1.0,
background : "transparent url( 'url/to/background/image.png' ) no-repeat 0 0",
width: "266px",
height: "109px"
}
};
// Add listener to the marker to open the overlay -- where popupInfo is the content to display inside the popover and marker is the marker on the map
google.maps.event.addListener(marker, 'click', function( event ) {
createOverlay( marker, popupInfo, new google.maps.Size(-35, -235))
});
// Method to show in the overlay
function createOverlay(marker_, content_, offset_) {
// close the previous overlay if there was one.
VW.Map.closeInfoBox();
// set the provided content to the popover options
popoverOptions.content = content_;
popoverOptions.pixelOffset = offset_;
// use the infobox lib to create an overlay
displayingInfoBox = new InfoBox(popoverOptions);
// show the overlay over the marker passed in
displayingInfoBox.open(myMap, marker_);
// return in case the caller wants to do something with this.
return displayingInfoBox;
}
Any help with this is much appreciated.
Thanks in advance!
EDIT -- I am using the INFOBOX API, and not the InfoWindow object from the maps API. This is what I'm talking about: http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html
Graham
I had this problem. I used my main CSS stylesheet to style my infobox rather than boxStyle in the Javascript. When I had the opacity setting on anything other than 1.0 (or removed altogether) the close button would be visible but would not work. My advice would be to check to make sure your infobox does not inherit opacity from anywhere else.
Related
I have a problem with the Popup of OpenLayers 4, when I open the popup info and I'm inside the div with the pointer, it still triggering the hover popup with the data behind the popup, how can I prevent that?
I'm using this CSS code for the popup:
#popup {
z-index: 20;
background-color: #fff;
}
The popup is created with the overlay layer:
overlay = new ol.Overlay({
element: container,
autoPan: true,
autoPanAnimation: {
duration: 250
}
});
But the pointer still passes through the div. the popup contains a lot of div and inside span
In the screenshot the hover popup was triggered when the pointer was on the Vehs text
You can refer to this for the code I use for the popup, the only difference is that I have a hover popup, I think the problem is on the creation of the click popup (the one with button) and the real z-index of it.
http://openlayers.org/en/latest/examples/popup.html
You can use pointer-events:none before its open and pointer-events:all once it's in open state
In the end, I found a very simple way to solve the problem, inside the function I call for the hover popup I add a simple if statement
map.on('pointermove', function(evt) {
info.html("");
if (overlay.getPosition() !== undefined) {
return;
}
.....
}
I'm having an issue right now with my map where I need to export it as an image with the overlay layers. I found a solution to do so using html2canvas, however there is a bug with it where if you pan the map at all, when taking the screenshot the layers will not display properly in the screenshot from html2canvas like so...
Yet if I just change the center of my map with map.setView() it works fine. So my thought is, if I could just trigger the map to reload completely (including the layers) it would maybe overlay correctly. How can I trigger a Leaflet map to reload everything including the overlay layers?
I've looked through the documentation but haven't as of this second found a clear solution.
We had the same problem today. It also happened with an export by dom-to-image-more/lealfet-easy-print plugin.
Try to disable zoomSnap or try to deactivate the fractional zoom functionality.
Setting the view to some random place in the ocean and then changing it back worked.
function redraw() {
var lat_tmp = map.getCenter().lat;
var lng_tmp = map.getCenter().lng;
map.setView([-66.22149259832975, -1.142578125]);
console.log("Reloading...");
setTimeout(function () {
waitForTilesToLoad()
}, 50000);
map.setView([lat_tmp, lng_tmp]);
console.log("Done");
}
I am trying to modify the default cursor icon when a certain control button is pressed.
Although I was partially successful by using css on the container div, doing this overrides the move cursor state, which is something I do not want. What I mean with this is that the move icon no longer appears while moving through the map (but not when on markers!).
I'd like to know if there is a non-hacky way through the api to achieve special cursor behaviour without redifining everything.
This is what I tried to do, #map is the container div for the leaflet map.
#map[control=pressed] {
cursor: url('..custom.png');
}
Edit 5.18.2017: Raw CSS and Javascript via Leaflet Framework (recommended)
I was looking through the source code for the BoxZoom plugin and noticed their approach using Leaflet's built-in DOM mutators and wanted to promote it here...this is certainly the best practice.
Example jsfiddle
Somewhere in your CSS include a class like this..
.leaflet-container.crosshair-cursor-enabled {
cursor:crosshair;
}
When you want to enable crosshairs, do this in your JS..
// Assumes your Leaflet map variable is 'map'..
L.DomUtil.addClass(map._container,'crosshair-cursor-enabled');
Then, when you want to disable crosshairs, do this in your JS..
L.DomUtil.removeClass(map._container,'crosshair-cursor-enabled');
Original Answer: Map-level Crosshairs
#scud42 got me on the right path. You can use JQuery to change the Leaflet map cursor like this:
$('.leaflet-container').css('cursor','crosshair');
Then later, when you want to reset the map cursor, you can do this:
$('.leaflet-container').css('cursor','');
Edit 1.21.2016: Per-feature Crosshairs
You can also enable crosshairs for individual features supporting the className option, such as a polygon, or feature vertices, etc.
Here's an example of a draggable vertice that will toggle pointer crosshairs (jsfiddle):
var svg_html_default = '<div style="margin:0px;padding:0px;height:8px;width:8px;border-style:solid;border-color:#FFFFFF;border-width:1px;background-color:#424242"</div>';
var default_icon = L.divIcon({
html: svg_html_default,
className: 'leaflet-mouse-marker',
iconAnchor: [5,5],
iconSize: [8,8]
});
var m = new L.marker([33.9731003, -80.9968865], {
icon: default_icon,
draggable: true,
opacity: 0.7
}).addTo( map );
m.on("mouseover",function(){$('.leaflet-mouse-marker').css('cursor','crosshair');});
m.on("mouseout",function(){$('.leaflet-mouse-marker').css('cursor','');});
Leaflet's styles allow you to change some cursor behavior. Put these in your local CSS to make the change.
/* Change cursor when mousing over clickable layer */
.leaflet-clickable {
cursor: crosshair !important;
}
/* Change cursor when over entire map */
.leaflet-container {
cursor: help !important;
}
Set to crosshair:
document.getElementById('map').style.cursor = 'crosshair'
Reset it back:
document.getElementById('map').style.cursor = ''
Use the active pseudo class.
#map:active {
cursor: url('..custom.png');
}
JSFiddle
For overriding a cursor you will probably want to use the css3 attribute user-select: none so that it doesn't toggle between the text and default cursor when dragging on the element. That implementation is also shown in the JSFiddle.
This is what worked for me:
// CSS first. Add this to leaflet stylesheet.
.leaflet-interactive.wait-cursor-enabled {
cursor: wait !important;
}
// JS select from map container and add class to each element
let map = L.map('map');
let els = map.getContainer().querySelectorAll('.leaflet-interactive');
for(let el of els){
el.classList += ' wait-cursor-enabled';
}
//JS remove class once no longer needed
let els = map.getContainer().querySelectorAll('.leaflet-interactive.wait-cursor-enabled');
for(let el of els){
el.classList.remove("wait-cursor-enabled");
}
$('.leaflet-container').css('cursor','crosshair');
I use react-leaflet and needed to change the cursor over the map and the polygons on it, based on a bit of state higher up in the app. Changing the cursor for the map itself was simple:
map.getContainer().style.cursor = 'crosshair';
For the polygons on the map it was not as straightforward. Leaflet polygons take a className option, which could be used to override the default leaflet-interactive class that sets the cursor to pointer. However, I found that className was not a dynamic option: re-rendering the polygon did not change the className (see this github issue).
I use styled-components, so I tried to wrap the Polygon component to override the cursor style rule, but this, also, only worked when the Polygon was first created. Eventually, I settled on capturing a reference to the Polygon object:
<Polygon ref={(el:any) => this.wrapperRef = el} /* ... */ />
and used this to set the cursor style rule on update:
componentDidUpdate = () => {
this.wrapperRef._path.style.cursor = this.props.cursor;
}
As discussed in the aforementioned github issue, the property _path of the object created by Leaflet can be used to access and override the style.
I'm using Google Mpas Api v3 to display a map in a 200px high div:
<div id='propertyKaart'></div>
With the normal javascript i'm using this div to display the map:
$(document).ready(function(){
var map = new google.maps.Map(document.getElementById("propertyKaart"),
mapOptions);
map.setCenter(punt);
map.setZoom(14);
})
With a click on a button with class .mapPuller I want to change the height of the chart to lets say 600px:
var mapState
$('.mapPuller').click(function(e){
if(mapState == 'klein'){
$('#propertyKaart').animate({height: '600px'}, 200);
mapState = 'groot'
}else{
$('#propertyKaart').animate({height: '200px'}, 200);
mapState = 'klein';
}
//---- here
})
Works like a charm, with only one problem. The map (the tiles, so to say) still think the div is 200px high.
In the documentation I found I had to trigger the resize event when changing the container div. So I added the following code in the .mapPuller function on the //------ here spot.
google.maps.event.trigger(map, 'resize');
But this doesn't work......
Am I missing something?
When I resize my browser window, the event gets triggered and the tiles seem to do their work.....
I tried resizing the map with jquery's animate function and had the same problem with you. The map tiles didn't adapt. But triggering the map resize event fixed the problem.
So, maybe there's a problem with scoping. Make sure that the map variable is accessible inside mapPuller function and make sure that there isn't other errors in the console.
I'm having a problem with embedding a Google Map via the v3 API in a modal box.
Grey boxes appear in the map canvas when the modal is shown. Resizing the browser window, bringing up Web Inspector, etc. makes all map tiles visible, i.e. it "force re-render" the map.
The parent element of the map element (section#map-modal, see code below) has display: none set in its CSS on page load. The JS modal code automatically sets display: block when the show button is clicked. If I temporarily remove display: none from the modal element, the map renders correctly on page refresh. Isn't the Google Map liking having a hidden parent element?
I'm using Twitter's Bootstrap modal jQuery plugin, and am controlling the modal itself with CSS. It's fixed positioned, have a pixel width, etc. Nothing unusual.
I've of course googled around for solutions, and many points to the Google API method of triggering the resize event:
google.maps.event.trigger(map, 'resize');
I've indeed done so, but to no avail.
Relevant code: https://gist.github.com/1591488
As you can see, I'me triggering the events at line 39.
(press the View larger map button at the bottom of the sidebar).
Files:
fagerhult.js
fagerhult.map.js
bootstrap-modal.js
master.css
I would deeply appreciate any help or extra pair of eyes in this, as I'm soon going mad over it.
Try using the modal event handlers. I think this is the most concise (and correct) way to ensure that you are resizing after the modal is shown without rewriting any plugins:
$('#map-modal').on('shown', function () {
google.maps.event.trigger(map, 'resize');
})
UPDATE: I just realized that this solution still does not center the map properly, so I needed to add one more command:
$('#map-modal').on('shown', function () {
google.maps.event.trigger(map, 'resize');
map.setCenter(new google.maps.LatLng(42.3605336, -72.6362989));
})
I discovered that having display: none on the map's parent element (the modal) really messed things up. I changed it to visibility: hidden just in sheer desperation to see what would happen, and it worked!
I also modified the modal JS code to set the modal to visibility: visible/hidden when the modal is shown/hid. Otherwise it would get display: none/block set again, which would create the grey boxes again.
My solution for bootstrap-modal.js v 2.0
replace class "hide" for "invisible" in Modal div
<div id="map_modal" class="modal fade invisible">
...
</div>
function javascript
function open_map()
{
$('#map_modal').removeClass("invisible");
$('#map_modal').modal('toggle');
}
link html
Open map
For those using bootstrap, I had to remove "fade" from my "modal" class
From
<div class="modal fade"
to
<div class="modal" ...
I had tried the previous solutions with calling google.maps.event.trigger(map, 'resize'); but figured that
.on("shown.bs.modal" ...
was never getting called. This issue seemed to point me to removing the fade.
https://github.com/twbs/bootstrap/issues/11793
This is not an optimal solution since the fade is actually very nice to have...
The problem is that if you do something like this:
$("#mapModalLink").click(function(){
google.maps.event.trigger(map,"resize");
});
is that your modal probably wasn't open (and displayed at the right size) when the resize event is triggered. To solve this:
$("#mapModalLink").click(function(){
$("#mapModal").show();
google.maps.event.trigger(map, 'resize');
});
Worked for me at least :)
I had this problem and I solved it doing a callback to the draw method. I think this happens because you draw your map erlier than showing the dialog.
I used this code to solve it (it wasn´t a modal window):
$('#map').show(function()
{
var punto = new google.maps.LatLng(this.latitud, this.longitud);
var myOptions = {zoom: 15, center: punto, mapTypeId: google.maps.MapTypeId.ROADMAP,mapTypeControl:false, draggable:false};
var map = new google.maps.Map(document.getElementById('mapa'), myOptions);
var marker = new google.maps.Marker({
position:punto,
map: map,
title: this.nombre
});
});
google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
google.maps.event.trigger(map, 'resize');
});
});
As far as I poked at it a bit on Chrome using JS live edit, delaying the execution of resize to wait for the modal animation might work :)
https://gist.github.com/1592330#L107
map rendered successfully without resize.
Why resize gives you proper map ?
Because browser paints the view again.
How to fix it?
To get a proper layout of the map in any panel which is triggered lately, map has to be painted after the panel is loaded.This can be achieved by (setTimeout) code as mentioned below.
code objective is to trigger map resize event after 60 milli seconds.
setTimeout(function () {
uiGmapIsReady.promise().then(function (maps) {
google.maps.event.trigger(maps[0].map, 'resize');
lat = -37;
lon = 144;
maps[0].map.panTo(new google.maps.LatLng(lat,lon));
var marker = {
id: Date.now(),
coords: {
latitude: lat,
longitude: lon
}
};
$scope.map.markers = [];
$scope.map.markers.push(marker);
console.log($scope.map.markers);
});
}, 60);