问题
Use case; click on marker opens infowindow, click on map closes it.
stopEventPropagation
is used to prevent that marker click propagates to the map (click on map would close the infowindow), this works fine in chrome, but in mobile safari (iphone 5) or chrome itself emulating the same phone, the event isn't stopped (thus the infobox not shown, or inmediatelly closed).
function stopEventPropagation(e) {
var evt = e ? e : window.event;
evt.cancelBubble = true;
if (evt.stop) evt.stop();
if (evt.stopPropagation) evt.stopPropagation();
if (evt.stopImmediatePropagation) evt.stopImmediatePropagation();
if (evt.preventDefault) evt.preventDefault();
evt.returnValue = false;
}
function initialize() {
var map = new google.maps.Map(document.getElementById('map-canvas'));
var infowindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();
var point = new google.maps.LatLng(49.277, -123.125);
var RichMarkerDiv='<div style="width:100px; height:100px;border:solid black 1px;">RichMarker</div>';
var marker = new RichMarker({ position: point, map: map, title: 'RichMarker', content: RichMarkerDiv });
google.maps.event.addListener(marker, 'click', function(e) {
stopEventPropagation(e);
infowindow.setContent(this.title);
infowindow.open(map, this);
});
bounds.extend(point);
google.maps.event.addListener(map, 'click', function(event) {
infowindow.close();
});
map.fitBounds(bounds);
}
initialize();
This can be tested here: http://jsfiddle.net/hy7rrm28/4/
The rich marker lib used has a small improvement to pass around events as suggested here: https://code.google.com/p/google-maps-utility-library-v3/issues/detail?id=280
Note: This was working a week or so ago, so it may be related to an update inside google maps, or in these browsers (?).
回答1:
I recently solved a similar problem for a custom google maps marker I created, and I believe I know what's going on. I had code similar to yours.
If you don't know (and I didn't prior to encountering this issue), on mobile devices, when you click the screen, a TouchEvent (https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) is triggered... this TouchEvent isn't created on desktop.
On desktop, my code worked because I was correct in assuming that the marker and map were interacting with the same event: a MouseEvent.
On mobile, however, when I put a debugger into the callback of this code - google.maps.event.addListener(map, 'click', callback) - I found the 'window.event' object was actually a TouchEvent (whereas when I checked the click event on my marker, it was interacting with a MouseEvent). It became clear that I needed to stop the TouchEvent from happening.
When I listened to the 'touchend' event on my marker and stopped propagation, this stopped any click events from taking place (both on the marker and the map) on mobile. I inserted this code into your fiddle, as something similar worked for me. Unfortunately, it didn't work in your fiddle.
google.maps.event.addDomListener(marker, "touchend", function(e) {
e.stopPropagation();
infowindow.setContent(this.title);
infowindow.open(map, this);
});
Why it didn't work, I'm not immediately sure, but my guess is the solution is pretty close to that (maybe the problem has to do with the differences between my marker and your RichMarker? The 'div' I use addDomListener on is not a google maps object. Maybe that's it?). The only problem with the solution above (or something like it) is that I wanted other events to take place on the marker (ex. double click), I needed to do something a little different (since stopping propagation of the 'touchend' event would stop other click events from being triggered on the object). I ended up creating a variable named 'touchMobileEvent' and set it to false. When the 'touchend' event is triggered on the marker (only triggered on mobile), I set it to true, the click event would trigger on the marker, and then I created a conditional within my map's click event callback that set touchMobileEvent back to false rather than triggering a click event. I also turned it back to false when a doubleclick event was triggered:
Creating variable to check if a touchMobileEvent is taking place:
var touchMobileEvent = false;
Setting events on my marker:
google.maps.event.addDomListener(div, "touchend", function(e) {
touchMobileEvent = true;
});
google.maps.event.addDomListener(div, "click", function(e) {
e.stopPropagation();
self.triggerClickEvent();
});
google.maps.event.addDomListener(div, "dblclick", function(event) {
event.stopPropagation();
event.preventDefault();
self.triggerDblClickEvent();
touchMobileEvent = false;
});
Setting events on my map:
google.maps.event.addListener(map, 'click', function(e){
if (touchMobileEvent) {
touchMobileEvent = false;
} else {
mapClickEvent();
});
Hope that helps. I recommend examining the various events that are being triggered/caught from within each callback. My original mistake was in assuming that the event listeners were interacting with the same event (when in actuality I was stopping propagation of a MouseEvent, but not doing anything about the TouchEvent that was created on mobile).
来源:https://stackoverflow.com/questions/35997804/stopeventpropagation-not-working-on-mobile-safari-or-chrome-dev-tools-emulation