I started implementing my software using maps api v3. Unfortunatelly i found out that v3 API has some serious issues which draws me back from bying a bussiness licence.
We had issue that we had CSS3 transition added to all elements..
So remove transition and its worked fine..
See example:
#map * {
-moz-transition: none;
-webkit-transition: none;
-o-transition: all 0s ease;
transition: none;
}
I was facing this issue in only mobile browsers. The drag/pan was smooth in desktop browsers but when it came to mobile there was lag when user dragged the map. I spent like 3 hours on this and finally realized that a missing meta tag was the reason.
Basically if you do not include this meta tag
<meta name="viewport" content="width=device-width, initial-scale=1">
the problem comes. I feel incredibly stupid for realizing this after 3 hours or not adding the meta tag in the first place. But anyways if someone else is also making this mistake I hope I saved some of your time.
Same here. What I noticed is that v3 fires a lot of events while panning the map and the browser tends to choke (FF especially). I say this because I also used Bing Maps API and the number of events per second for viewchange
(equivalent for center_changed
in Google) is much smaller. Also they provide the method addThrottledHandler()
with which you can reduce the number of events generated.
From what I can tell, Google Maps seem to fire one center_changed
event for each mousemove
event and before the map's view is updated. So you get a lot of events generated but none of them are replicated on the screen; browser chokes on map view updates or it might be that the map waits until there are no more changes and only then it updates the view.
Edit: if we prevent some of the mousemove
events to reach Google Maps then the browser will not choke on mousemove
events plus all the other events that Google Maps generates from this event, like center_changed
, and the map will pan smoothly.
To do this we add an event listener to the #map
div (we can add it to body
tag also). We add the event for the capture phase. When mouse moves on the screen, first the body
tag receives the event then our #map
div and then Google Maps elements (divs, tiles). This is the capture phase. After that follows the bubble phase in which the event goes back from Google Maps elements to our #map
div and then to the body
tag. Usually event handlers are registered for the bubbling phase so if we register a handler for the capture phase we can cancel the event and so there will be no bubbling phase for this event. This also means that Google Maps will not receive the event.
You can increase the period
and space
parameters to kill more events. Killing too many events means that the map will start to jump from one position to the next. Killing too few means that all events will reach Google Maps and the browser will choke on newly generated events from Google Maps and so the map will jump from one position to the next. Some middle ground works best.
Now after all these, Google Maps will not be as smooth as Bing Maps. This is because Bing Maps use inertia: when you move the map violently, the map will start slowly to follow the mouse and then faster and faster. This creates a very smooth pan indeed.
An interesting fact that I've found is that Google Chrome and Opera/Chrommium will generate about one mousemove
event per second even if the mouse doesn't move! This code will kill those events too (because distance
is zero for those events).
http://jsfiddle.net/uNm57/ (check js console in Firefox; you should see some events that are stopped and then one allowed event)
<html>
<head>
<style type='text/css'>
#map {
position: absolute;
width: 100%;
height: 100%;
margin: 20px;
}
</style>
<script type='text/javascript'>
var last = {time : new Date(), // last time we let an event pass.
x : -100, // last x position af the event that passed.
y : -100}; // last y position af the event that passed.
var period = 100; // ms - don't let pass more than one event every 100ms.
var space = 2; // px - let event pass if distance between the last and
// current position is greater than 2 px.
function init_map() {
map_div = document.getElementById("map")
// map
var map_options = {
center: new google.maps.LatLng(45.836454, 23.372497),
zoom: 8
};
map = new google.maps.Map(document.getElementById("map"), map_options);
// register event handler that will throttle the events.
// "true" means we capture the event and so we get the event
// before Google Maps gets it. So if we cancel the event,
// Google Maps will never receive it.
map_div.addEventListener("mousemove", throttle_events, true);
};
function throttle_events(event) {
var now = new Date();
var distance = Math.sqrt(Math.pow(event.clientX - last.x, 2) + Math.pow(event.clientY - last.y, 2));
var time = now.getTime() - last.time.getTime();
if (distance * time < space * period) { //event arrived too soon or mouse moved too little or both
console.log("event stopped");
if (event.stopPropagation) { // W3C/addEventListener()
event.stopPropagation();
} else { // Older IE.
event.cancelBubble = true;
};
} else {
console.log("event allowed: " + now.getTime());
last.time = now;
last.x = event.clientX;
last.y = event.clientY;
};
};
</script>
</head>
<body onload = "init_map()">
<div id="map"></div>
</body>
</html>