GLatLngBounds - wrong center and zoom level - javascript

I'm trying to use GLatLngBounds to make all the markers on the map visible. Below is a small example of what I'm doing.
INV.createMap = function(containerId) {
var map = null;
var geocoder = null;
var bounds = new GLatLngBounds();
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById(containerId), {
size: new GSize(600, 300)
});
map.setCenter(new GLatLng(54.729378425601766, 25.279541015625), 15);
map.addControl(new GSmallZoomControl());
geocoder = new GClientGeocoder();
}
return {
markAdress: function(address, infoContentHtml) {
if (map !== null && geocoder !== null) {
geocoder.getLatLng(address, function(point) {
if (point) {
var marker = new GMarker(point);
GEvent.addListener(marker, 'mouseover', function() {
if (!map.getInfoWindow().getPoint().equals(this.getLatLng())) {
this.openInfoWindowHtml(infoContentHtml);
}
});
map.addOverlay(marker);
bounds.extend(point);
}
});
}
},
finalize: function() {
map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
}
};
};
Usage:
var m = INV.createMap('whatever');
var addresses = ...
for (var i = 0, l = addresses.length; i < l; i++) {
m.markAdress('address...', 'htmlInfo...');
}
m.finalize();
The problem is that the zoom level is completely wrong (waaay too zoomed out) and the markers appear on the left top corner of the map for some reason (but all of them are visible).
What am I doing wrong?
EDIT: Ignore this question. I've made a stupid mistake - I overlooked the fact that GClientGeocoder makes asynchronous requests so the finalize() method is called too early.

The last argument of the function call below specifies the zoom level:
map.setCenter(new GLatLng(54.729378425601766, 25.279541015625), 15);
This article talks a bit about zooming. So the zooming level is a bit too high.
Further this tutorial tells you how to fit the map zooming to properly display a set of markers.
Hope this helps

Related

How to fix a not a LatLng or LatLngLiteral: not an Object issue - Google Maps

The idea of this functionality is when a user enters a location we add a marker in that location and pans too said marker and zooms into the location of the marker. All this is working relatively fine, however. It's giving me this error " Uncaught Kc {message: "not a LatLng or LatLngLiteral: not an Object", name: "InvalidValueError". "
if(map.getZoom() == 2) {
map.setCenter({lat:data.address_lat2, lng:data.address_lng2});
map.panTo(marker.position);
smoothZoom(map, 11, map.getZoom());
var location = new google.maps.LatLng({lat:data.address_lat2, lng:data.address_lng2});
var bounds = new google.maps.LatLngBounds();
bounds.extend(location.position);
map.fitBounds(bounds);
}
This is my smoothZoom function
function smoothZoom (map, max, cnt) {
if (cnt >= max) {
return;
} else {
z = google.maps.event.addListener(map, 'zoom_changed', function(event){
google.maps.event.removeListener(z);
smoothZoom(map, max, cnt + 1);
});
setTimeout(function(){map.setZoom(cnt)}, 150);
}
}
A google.maps.LatLng doesn't have a constructor that takes a google.maps.LatLngLiteral as the argument. This is not valid syntax:
var location = new google.maps.LatLng({lat:data.address_lat2, lng:data.address_lng2});
Should be:
var location_place = new google.maps.LatLng(data.address_lat2, data.address_lng2);
or:
var location_place = {lat:parseFloat(data.address_lat2), lng:parseFloat(data.address_lng2)};
(you only need the parseFloat if they are strings)
Also: location is not a good variable name. (see ref1 or ref2)
Turns out that this line of code bounds.extend(location.position); should've been bounds.extend({lat:data.address_lat2,lng:data.address_lng2});

IE Issue of Google Maps Marker Animation

I am using google maps api v3.
The Below code i am trying to run , It is working on all Browsers except IE.
Can u please suggest any changes needed to work in IE.
Fiddle Link
My Code is :
var map;
var mapOptions = { center: new google.maps.LatLng(0.0, 0.0), zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP };
var markers = [];
function initialize() {
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
from1 = new google.maps.LatLng(0,0);
to1 = new google.maps.LatLng(30,12);
from2 = new google.maps.LatLng(-30,15);
to2 = new google.maps.LatLng(10,-100);
from3 = new google.maps.LatLng(0,-50);
to3 = new google.maps.LatLng(0,50);
addMarker(from1,to1);
addMarker(from2,to2);
addMarker(from3,to3);
}
function addMarker(pos, dest) {
var marker = new google.maps.Marker({
map: map,
position: pos,
destination: dest
});
google.maps.event.addListener(marker, 'click', function(event) {
fromLat = this.position.lat();
fromLng = this.position.lng();
toLat = this.destination.lat();
toLng = this.destination.lng();
// store a LatLng for each step of the animation
frames = [];
for (var percent = 0; percent < 1; percent += 0.01) {
curLat = fromLat + percent * (toLat - fromLat);
curLng = fromLng + percent * (toLng - fromLng);
frames.push(new google.maps.LatLng(curLat, curLng));
}
move = function(marker, latlngs, index, wait, newDestination) {
marker.setPosition(latlngs[index]);
if(index != latlngs.length-1) {
// call the next "frame" of the animation
setTimeout(function() {
move(marker, latlngs, index+1, wait, newDestination);
}, wait);
}
else {
// assign new route
marker.position = marker.destination;
marker.destination = newDestination;
}
}
// begin animation, send back to origin after completion
move(marker, frames, 0, 20, marker.position);
});
markers.push(marker);
}
google.maps.event.addDomListener(window, 'load', initialize);
After some fiddling it looks like a typing issue. Because you haven't implicitly declared the variable frames as a var ie is unsure that it is an array, thus the error "Object does not support method push".
You simply need to change:
frames = [];
to:
var frames = [];
Tested in ie 8- 10.

Remove markers out of viewport

I have to manage a map of about 80.000 markers concentrated in France.
To do that, I decided to get the bounds of the viewport and call a dynamic-JSON (with PHP) which contains the markers inside the viewport. And this on the "idle" event.
I faced a problem with this solution. Indeed, the markers which already exist was re-plotted (at the same position), which consequently weigh the map for nothing...
To solve it, the markers list before and after the JSON query are compared (thanks to jQuery), in order to plot only the new markers. And it works!
Now, I would want to remove the markers which are not currently shown on the map. Or a list of markers (I get it thanks to jQuery) designated by an ID which is also the title of the marker. So, how can a delete markers like that ? I specify that I am using MarkerManager.
Otherwise, you guess that if I do not remove these markers, they will be re-plotted in some cases... For example, you are viewing the city A, you move the map to view the city B, and you get back to the city A...
Here is the code:
var map;
var mgr;
var markers = [];
function initialize(){
var mapOptions = {
zoom: 6,
center: new google.maps.LatLng(46.679594, 2.109375)
};
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var mgrOptions = { borderPadding: 50, maxZoom: 15, trackMarkers: false };
mgr = new MarkerManager(map, mgrOptions);
google.maps.event.addListener(map, 'idle', function() {
mapEvent();
});
}
function mapEvent(){
if( map.getZoom() >= 8 ){
var bounds = map.getBounds();
getSupports(bounds.getNorthEast(), bounds.getSouthWest());
} else {
// Todo
}
}
var markerslistID = new Array();
var markerslistData = {};
function getSupports(ne, sw){
newMarkerslistID = new Array();
newMarkerslistData = {};
// Getting the markers of the current view
$.getJSON('./markerslist.php?nelat='+ne.lat()+'&nelng='+ne.lng()+'&swlat='+sw.lat()+'&swlng='+sw.lng(), function(data) {
for (var i = 0; i < data.points.length; i++) {
var val = data.points[i];
newMarkerslistID.push(val.id);
newMarkerslistData[val.id] = new Array(val.lat, val.lng, val.icon);
}
// List of New Markers TO PLOT
var diffNewMarkers = $(newMarkerslistID).not(markerslistID).get();
// List of Old markers TO REMOVE
var diffOldMarkers = $(markerslistID).not(newMarkerslistID).get();
// Plotting the NEW MARKERS
for( var i = 0; i < diffNewMarkers.length; i++ ){
var marker = new google.maps.Marker({
position: new google.maps.LatLng(newMarkerslistData[diffNewMarkers[i]][0], newMarkerslistData[diffNewMarkers[i]][1]),
title : diffNewMarkers[i],
icon : './images/'+newMarkerslistData[diffNewMarkers[i]][2]+'.png'
});
mgr.addMarker(marker, 0);
}
/*****************************************
HERE WE HAVE TO REMOVE
THE MARKERS CONTAINED IN diffOldMarkers
*****************************************/
mgr.refresh();
// Switching the new list to the old, for the next event
markerslistID = newMarkerslistID;
markerslistData = newMarkerslistData;
});
}
Thank you for your help.
A one-liner to hide all markers that ar not in the current viewport.
!map.getBounds().contains(marker.getPosition()) && marker.setVisible(false);
Or,
if (map.getBounds().contains(marker.getPosition()) && !marker.getVisible()) {
marker.setVisible(true);
}
else if (!map.getBounds().contains(marker.getPosition()) && marker.getVisible()) {
marker.setVisible(false);
}

Extend Google Maps marker to animate smoothly on update?

Using the Google Maps API v3 I've been able to update multiple positions of markers via an AJAX call. However, it lacks any transition. Code below:
if ( !latlong.equals( point.latlong ) ) {
point.latlong = latlong;
point.marker.setPosition(latlong);
}
The drawback is that setPosition has no native animation method. Does anyone know any methods for extending setPosition so the marker can fluently "move" from it's old to new position? Or any methods available? I have not been able to find any documentation. Thanks!
I did not find any native way to create this animation. You can create your own animation by stepping the position from the current point to the final point using the setPosition. Here is a code snippet to give you an idea:
var map = undefined;
var marker = undefined;
var position = [43, -89];
function initialize() {
var latlng = new google.maps.LatLng(position[0], position[1]);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
marker = new google.maps.Marker({
position: latlng,
map: map,
title: "Your current location!"
});
google.maps.event.addListener(map, 'click', function(me) {
var result = [me.latLng.lat(), me.latLng.lng()];
transition(result);
});
}
var numDeltas = 100;
var delay = 10; //milliseconds
var i = 0;
var deltaLat;
var deltaLng;
function transition(result){
i = 0;
deltaLat = (result[0] - position[0])/numDeltas;
deltaLng = (result[1] - position[1])/numDeltas;
moveMarker();
}
function moveMarker(){
position[0] += deltaLat;
position[1] += deltaLng;
var latlng = new google.maps.LatLng(position[0], position[1]);
marker.setPosition(latlng);
if(i!=numDeltas){
i++;
setTimeout(moveMarker, delay);
}
}
This can probably be cleaned up a bit, but will give you a good start. I am using JavaScript's setTimeout method to create the animation. The initial call to 'transition' gets the animation started. The parameter to 'transition' is a two element array [lat, lng]. The 'transition' function calculates the step sizes for lat and lng based upon a couple of animation parametes (numDeltas, delay). It then calls 'moveMarker'. The function 'moveMarker' keeps a simple counter to indicate when the marker has reached the final destination. If not there, it calls itself again.
Here is a jsFiddle of the code working: https://jsfiddle.net/rcravens/RFHKd/2363/
Hope this helps.
Bob
In case you want smooth animations (with easing), these libraries should help:
https://github.com/terikon/marker-animate-unobtrusive
http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/markermove-sliding.html
I know its late but it might help the future SO wanderers.
Problem Statement: write a function(and not a library due to specific use-case) to animate a google maps marker to a new location.
Solution is based on this awesome library marker-animate-unobtrusive
function animateMarkerTo(marker, newPosition) {
var options = {
duration: 1000,
easing: function (x, t, b, c, d) { // jquery animation: swing (easeOutQuad)
return -c *(t/=d)*(t-2) + b;
}
};
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
// save current position. prefixed to avoid name collisions. separate for lat/lng to avoid calling lat()/lng() in every frame
marker.AT_startPosition_lat = marker.getPosition().lat();
marker.AT_startPosition_lng = marker.getPosition().lng();
var newPosition_lat = newPosition.lat();
var newPosition_lng = newPosition.lng();
// crossing the 180° meridian and going the long way around the earth?
if (Math.abs(newPosition_lng - marker.AT_startPosition_lng) > 180) {
if (newPosition_lng > marker.AT_startPosition_lng) {
newPosition_lng -= 360;
} else {
newPosition_lng += 360;
}
}
var animateStep = function(marker, startTime) {
var ellapsedTime = (new Date()).getTime() - startTime;
var durationRatio = ellapsedTime / options.duration; // 0 - 1
var easingDurationRatio = options.easing(durationRatio, ellapsedTime, 0, 1, options.duration);
if (durationRatio < 1) {
marker.setPosition({
lat: (
marker.AT_startPosition_lat +
(newPosition_lat - marker.AT_startPosition_lat)*easingDurationRatio
),
lng: (
marker.AT_startPosition_lng +
(newPosition_lng - marker.AT_startPosition_lng)*easingDurationRatio
)
});
// use requestAnimationFrame if it exists on this browser. If not, use setTimeout with ~60 fps
if (window.requestAnimationFrame) {
marker.AT_animationHandler = window.requestAnimationFrame(function() {animateStep(marker, startTime)});
} else {
marker.AT_animationHandler = setTimeout(function() {animateStep(marker, startTime)}, 17);
}
} else {
marker.setPosition(newPosition);
}
}
// stop possibly running animation
if (window.cancelAnimationFrame) {
window.cancelAnimationFrame(marker.AT_animationHandler);
} else {
clearTimeout(marker.AT_animationHandler);
}
animateStep(marker, (new Date()).getTime());
}

Google map with route-trace loading data instead of adding it on click

In this map
http://econym.org.uk/gmap/example_snappath.htm
source:
<script type="text/javascript">
//<![CDATA[
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(53.7877, -2.9832),13)
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
var dirn = new GDirections();
var firstpoint = true;
var gmarkers = [];
var gpolys = [];
var dist = 0;
GEvent.addListener(map, "click", function(overlay,point) {
// == When the user clicks on a the map, get directiobns from that point to itself ==
if (!overlay) {
if (firstpoint) {
dirn.loadFromWaypoints([point.toUrlValue(6),point.toUrlValue(6)],{getPolyline:true});
} else {
dirn.loadFromWaypoints([gmarkers[gmarkers.length-1].getPoint(),point.toUrlValue(6)],{getPolyline:true});
}
}
});
// == when the load event completes, plot the point on the street ==
GEvent.addListener(dirn,"load", function() {
// snap to last vertex in the polyline
var n = dirn.getPolyline().getVertexCount();
var p=dirn.getPolyline().getVertex(n-1);
var marker=new GMarker(p);
map.addOverlay(marker);
// store the details
gmarkers.push(marker);
if (!firstpoint) {
map.addOverlay(dirn.getPolyline());
gpolys.push(dirn.getPolyline());
dist += dirn.getPolyline().Distance();
document.getElementById("distance").innerHTML="Path length: "+(dist/1000).toFixed(2)+" km. "+(dist/1609.344).toFixed(2)+" miles.";
}
firstpoint = false;
});
GEvent.addListener(dirn,"error", function() {
GLog.write("Failed: "+dirn.getStatus().code);
});
}
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
// This Javascript is based on code provided by the
// Community Church Javascript Team
// http://www.bisphamchurch.org.uk/
// http://econym.org.uk/gmap/
//]]>
</script>
You can click and add paths that trace routes.
I would like to use the trace-road-functionality, but pre-define the data using coordinates instead. How would I do this?

Categories

Resources