Google maps v3 synchronized drag - javascript

I am currently trying to synchronize the movement of two Google Maps on screen when the user drags them.
Currently I am listening to the center_changed event. However that is only called once a drag has been completed, thus the second map only moves after the drag and not during.
My current code looks like this
var mapOptions = {
center: new google.maps.LatLng(52.287373, -1.548609),
zoom: 12,
// streetViewControl: false
disableDefaultUI: true,
// draggable: false,
// disableDoubleClickZoom: false
};
mapOptions["styles"] = dayStyle;
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
backgroundMap = new google.maps.Map(document.getElementById("background-map"),
mapOptions);
google.maps.event.addListener(map, 'center_changed', function() {
// Set backgroundMap to match actual map
backgroundMap.panTo(map.getCenter());
});
google.maps.event.addListener(map, 'zoom_changed', function() {
// Set backgroundMap zoom to be further out than actual map
backgroundMap.setZoom((map.getZoom()-2 >= 1) ? map.getZoom()-2 : 1);
});
But I really want to create the same effect that http://snazzymaps.com/ has. I've already tried using the bindTo method to link the background map to the foreground map. But that also only updates the background map after the drag is complete.

the drag event is the one you want, but use it in conjunction with center_changed, because panning using the keyboard arrows will not fire the drag event.

It appears that my code does work in desktop environments.
However the maps JS API limits it callback rates in mobile environments (I can only assume it's for performance reasons), and thus only calls center_changed once per drag. Unlike the on desktop where it is call far more frequently.

Related

pan with one finger

I want to prevent the user from panning while pinch rotating or zooming,
so the solution I have come with is to limit the user to pan only with one finger.
so I was able to do that with the following code:
var interactions = map.getInteractions().forEach(function(interaction) {
if (interaction instanceof ol.interaction.DragPan) {
pan = interaction;
}
}, this);
//disable pan with 2 fingers by redefine the handleDownEvent function and call
//to the original handleDownEvent_ function only when the user use 1 finger.
var panDownEvent = pan.handleDownEvent_;
pan.handleDownEvent_ = function (e) {
if(pan.targetPointers.length >1) return false;
panDownEvent.call(pan,e);
return true;
}
The problem is that when I am using this code from some reason the tiles lazy load stop working only on mobile.
I will be graceful if you can add an api option to limit the pan to only one finger or give me other solution,
or event better, how to trigger the ol lazy load function.
Thanks.
The OpenLayers map is created with some default interactions. The PinchZoom interaction is one of them. Any default interaction can be disabled when creating the map, for example to disable the pinch zoom interaction, you can do this:
var map = new ol.Map({
layers: layers,
interactions: ol.interaction.defaults({
pinchZoom: false
}),
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
Learn more about this in the list of interactions page, which includes details about ol.interaction.defaults, i.e. the list of default interactions in an OpenLayers map.
Try this and see if that makes your other issue disappear.

google maps refresh without displaying gray

I am using the Google Maps API v3 in javascript, and I am constantly reloading the map with an app.get, and adding layers and bookmarks using mongodb. To erase everything I reload the map, and while it's loading a gray background displays in the div that contains the map.
What technique do you recommend so that the gray transition is not displayed, and the map is displayed all at once?
I'm reloading the map with the following code, within the function that does the reload; if I put this code outside of the function, the new elements that arrive will appear on top. This is why I do it this way.
var geocoder,map
geocoder = new google.maps.Geocoder();
var options = {
zoom: 5,
minZoom: 5,
center: new google.maps.LatLng(5.1573603, -74.982409),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map'), options);
You can first set the visibility of the div which contains map to hidden; then listen to the first tilesloaded event, and set the visibility back to visible. Doing this the Maps should only pop up after all it tiles is loaded (so no gray screen)
Here is a quick demo which do just that:
http://jsfiddle.net/nq5t85sz/1/

fitBounds() shows whole earth (if map is first hidden and then shown)

I have a bunch or markers, and I want to show only the area containing them. I found a long list of similar questions (see at the bottom of the post for some), but none of the solutions works for me. The LatLngBounds is built correctly, but when I call fitBounds the result will be the following:
Instead of:
Can anybody spot an evident error in my code?
var opt = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"),opt);
var box = new google.maps.LatLngBounds();
for(var i=0;i<list.length;i++){
var p = new google.maps.LatLng(list[i].lat,list[i].lon);
var marker = new google.maps.Marker({
position: p,
map: map
});
box.extend(p);
}
map.fitBounds(box);
map.panToBounds(box);
Some of the posts I read and tried (list not comprehensive):
Google Maps v3 - Automating Zoom Level?
Google maps V3 custom marker images and fitBounds()
Google Maps with fitBounds don't zoom
fitbounds() in Google maps api V3 does not fit bounds
Edit: this actually happens if (as I do in my application) the map is at first hidden, and showed only later.
I hide it in this way:
$('#map').hide();
and show it:
$('#map').show(function(){
//this is necessary because otherwise
//the map will show up in the upper left corner
//until a window resize takes place
google.maps.event.trigger(map, 'resize');
});
Any clue as to why this happens and how to prevent it (apart from initialising the map when first shown)?
On a side note, if I set zoom and center when declaring the map object (i.e. I don't use fitBounds()) then the map will show correctly, even after a hide/show.
I can't set zoom and center, though, because the list of points is retrieved elsewhere and I don't know where they are beforehand.
Solved (not in a nice way, though).
What I ended up doing was initialising the LatLngBounds with the points when loading the page, but panning and zooming only when showing the map. In this way it works correctly.
E.g.
var box;
function init(){
var opt = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"),opt);
box = new google.maps.LatLngBounds();
for(var i=0;i<list.length;i++){
var p = new google.maps.LatLng(list[i].lat,list[i].lon);
var marker = new google.maps.Marker({
position: p,
map: map
});
box.extend(p);
}
}
and then, later (click on a button for example)
function showMap(){
$('#map').show(function(){
google.maps.event.trigger(map, 'resize');
map.fitBounds(box);
map.panToBounds(box);
});
}
It works, but I don't like to have that global var hanging around. I implement the exact same behavior using OpenLayers, and it works correctly without the need for this hack. If anybody has a better solution, please post it and I will accept it if it works.
Thanks to #Engineer and #Matt Handy for helping me eliminate one possible source of errors.
I tried your code in a fiddle, and it works as expected.
So the reason why your code fails must be in the definition of your datapoints (as already suggested by Engineer). Compare your list definition with mine and check if they are different.
Modify to your needs
map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() {
if (map.getZoom() > 16) map.setZoom(16);
google.maps.event.removeListener(listener);
});
same problem, found the reason is that I hide the map (make the container of the map display: none;) before calling fitbounds()
To expand a bit on #JayThakkar 's answer, this worked for me
google.maps.event.addListenerOnce(map, 'idle', function(){
map.fitBounds(bounds);
});
The addListenerOnce function removes the need to call google.maps.event.removeListener(listener);.
And calling map.fitBounds(bounds) inside the listener let us use the calculated bounds's zoom level.

Zooming to center on a map in Google Maps API V3

I'm new to using google maps and am trying to find out how to restrict the zoom function so that it does not zoom anywhere except of the center of the map and not zoom to the mouse point. Basically it zooms to the center of the returned map no matter where your mouse pointer is on the map as opposed to zooming where the mouse pointer is located on the map. I don't even know if this is possible currently, some help would be appreciated.
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(51.285583, 1.091045);
var myOptions = {
zoom: 15,
center: latlng,
scrollwheel: true,
navigationControl: false,
mapTypeControl: false,
scaleControl: false,
draggable: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(51.285826, 1.089973),
map: map,
title: 'Run of The Mill',
clickable: true
});
}
</script>
There are several zoom types:
using zoom control - that zooms to the center of the map
using scroll wheel - that zooms to the mouse pointer as you complain
using double click - that first centers the place under the mouse pointer and then zooms
So if you want only the first zoom type, you can disable the other two by setting disableDoubleClickZoom and scrollwheel map options to false.
Moreover, you might handle dblclick map event (scroll wheel event is not so straightforward, but maybe you'll find a way how to handle the scroll wheel in javascript too) and in this handler just change the map scale using map.setZoom(). The map center will stay the same. Fairly easy.
Or handle this by re-centering the map on zoom change. This preserves the expected functionality on double click and scroll wheel.
google.maps.event.addListener(map,'zoom_changed',function () {
map.setCenter(new google.maps.LatLng(47.61388802057299,-122.31870898147581));
})
From what I can see in your code you are zooming on the latlng variable that you declared above. That is correct. You myOptions variable is then passed into your new maps declaration. So you should be centered on 51.285583, 1.091045, which is Caterbury Kent in the UK.
If that is where your mouse is pointing it is working, if this doesn't help I would suggest copying an example from the google examples and cutting out what you don't need for your first demo.
http://code.google.com/apis/maps/documentation/javascript/examples/index.html

Hand cursor on mouseover KMLLayer in Google Maps

is it possible to show hand cursor on mouseover KMLLayer in Google Maps 3?
I see the two solutions (but it seems that they cannot be used):
handle mouseover event for KMLLayer and change cursor in CSS
handle mouseover event for Map and check if cursor's location is contained by KMLLayer
Do you have any other ideas?
Thanks
The kml polygon cannot have a mouseover event so 1. is not possible.
As for second i really don't see an easy way out.
If you could change the format of the data to something else than kml things would be way better.
You can't have mouseover event, but you can set a click listener onto the layer, which will show the hand cursor.
var layer = new google.maps.KmlLayer('http://...');
google.maps.event.addListenerOnce(layer, 'click', function () {
// do nothing here
});
Now whenever you mouse over an area defined in the KML it will show the cursor. You can also obtain the location of the mouse (if the user clicks on the KML Layer) because that will generate a KmlMouseEvent which will contain the LatLng of the point they clicked. It will also tell you information about which KML Placemark they clicked. You can then do your calculations here to see if it's contained by the KML Layer you want...
From what I know you can enable/disable cursor pointer in google maps v3 over kml by the option clickable:
var kml = new google.maps.KmlLayer(
kmlUrl,
{
suppressInfoWindows: true,
preserveViewport: true,
map: null,
clickable: false
}
);

Categories