Set google map zoom dynamically - javascript

It's possible to define a level of zoom depending of the height of polygon shapes (administrative boundaries)?
This polygon going to be completely displayed into the map's div.

There is a map.fitBounds(my_bounds) function, which sets the viewport to contain the given bounds. It would set the map to the highest zoom level possible, in which you can see the whole bounds.
For that you need to determine the bounds of your polygon. If you use google.maps.Polygon to display your polygons, check out this solution.
In this case you would have:
google.maps.Polygon.prototype.getBounds = function() {
var bounds = new google.maps.LatLngBounds();
var paths = this.getPaths();
var path;
for (var i = 0; i < paths.getLength(); i++) {
path = paths.getAt(i);
for (var ii = 0; ii < path.getLength(); ii++) {
bounds.extend(path.getAt(ii));
}
}
return bounds;
}
...
map.fitBounds(my_polygon.getBounds());
If you use Data layer to display polygons, check out this SO answer. It provides example on how to calculate bounds of Data.Feature if it's a polygon.
If you have some other means of determining the bounds of polygon, then just use this:
map.fitBounds(new google.maps.LatLngBounds(new google.maps.LatLng(SouthWestCornerLat, SouthWestCornerLng), new google.maps.LatLng(NorthEastCornerLat, NorthEastCornerLng));

Related

leaflet.js ImageOverlay zoom changes marker position

Am using ImageOverlay to use an image as a map, using Leaflet.js - but when changing the zoom the markers change position.
Have followed guideance in this tutorial and a code pen example is here.
// Markers
var markers = [{"title":"OneOcean Port Vell","description":"Super yacht marina","link":"http:\/\/www.oneoceanportvell.com\/","x":"68.28125","y":"68.443002780352178"}];
var map = L.map('image-map', {
minZoom: 2,
maxZoom: 4,
center: [0, 0],
zoom: 2,
attributionControl: false,
maxBoundsViscosity: 1.0,
crs: L.CRS.Simple
});
// dimensions of the image
var w = 3840,
h = 2159,
url = 'map.png';
// calculate the edges of the image, in coordinate space
var southWest = map.unproject([0, h], map.getMaxZoom()-1);
var northEast = map.unproject([w, 0], map.getMaxZoom()-1);
var bounds = new L.LatLngBounds(southWest, northEast);
// add the image overlay,
// so that it covers the entire map
L.imageOverlay(url, bounds).addTo(map);
// tell leaflet that the map is exactly as big as the image
map.setMaxBounds(bounds);
// Add Markers
for (var i = 0; i < markers.length; i++){
var marker = markers[i];
// Convert Percentage position to point
x = (marker['x']/100)*w;
y = (marker['y']/100)*h;
point = L.point((x / 2), (y / 2))
latlng = map.unproject(point);
L.marker(latlng).addTo(map);
}
In the codepen, change zoom to 4 to see the markers lose their position.
Ideally I'm trying to change the zoom to allow for different screen sizes and to get more of the map visible on mobile devices.
Also perhaps related, I can't see to get the zoomSnap feature to work to allow for fractional zooming.
Any pointers greatly appriciated.
map.unproject needs the zoom value at which you want the un-projection to be applied.
You correctly specify your static imageZoom value to unproject when computing your bounds and center, but not for your markers positions.
If the zoom parameter is not specified, then unproject uses the current map zoom level, i.e. what you have defined in your zoom variable. That is why when you change its value, unproject for your markers uses a different value, and they are positioned in different locations.
You even had to divide your x and y values (relative to your image) by 2, to account for the fact that in your initial situation, they are correct for an imageZoom of 4, but since you do not specify the zoom for unproject, the latter uses the current zoom (i.e. 3), so coordinates should be divided by 2 to be "correct".
Updated codepen: https://codepen.io/anon/pen/pLvbvv

Tiling contiguous polygons in Google Maps

I'm trying to draw a hexagonal grid in Google Maps. I've come up with a solution based off this answer which looks fine at higher zooms, but when zoomed further out I find that the classic "orange-peel" problem occurs: The hexagons no longer fit together like they should:
I'm using this rather cool geodesy library to calculate hexagon centers based on an ellipsoidal model (since a 2d model clearly doesn't work on a real-world map) but it's still looking pretty bad when zoomed out.
Preferably, I'd like to draw the hexagons in such a way that they are exactly the same shape and size on screen.
Here's the code I've been working with, also available as a Plunker here. I've tried calculating the vertices of each polygon using the same geodesy library that I'm using to calculate the polygon centers, but it still doesn't look right when zoomed out.
var hexgrid = [];
function initialize(){
// Create the map.
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 51.5, lng: 0},
scrollwheel: true,
zoom: 8
});
// This listener waits until the map is done zooming or panning,
// Then clears all existing polygons and re-draws them.
map.addListener('idle', function() {
// Figure out how big our grid needs to be
var spherical = google.maps.geometry.spherical,
bounds = map.getBounds(),
cor1 = bounds.getNorthEast(),
cor2 = bounds.getSouthWest(),
cor3 = new google.maps.LatLng(cor2.lat(), cor1.lng()),
cor4 = new google.maps.LatLng(cor1.lat(), cor2.lng()),
diagonal = spherical.computeDistanceBetween(cor1,cor2),
gridSize = diagonal / 20;
// Determine the actual distance between tiles
var d = 2 * gridSize * Math.cos(Math.PI / 6);
// Clear all the old tiles
hexgrid.forEach(function(hexagon){
hexagon.setMap(null);
});
hexgrid = [];
// Determine where the upper left-hand corner is.
bounds = map.getBounds();
ne = bounds.getNorthEast();
sw = bounds.getSouthWest();
var point = new LatLon(ne.lat(), sw.lng());
// ... Until we're at the bottom of the screen...
while(point.lat > sw.lat()){
// Keep this so that we know where to return to when we're done moving across to the right
leftPoint = new LatLon(point.lat, point.lon).destinationPoint(d, 150).destinationPoint(d, 210).destinationPoint(d, 270).destinationPoint(d, 90)
step = 1;
while(point.lon < ne.lng()){
// Use the modulus of step to determing if we want to angle up or down
if (step % 2 === 0){
point = new LatLon(point.lat, point.lon).destinationPoint(d, 30);
} else {
point = new LatLon(point.lat, point.lon).destinationPoint(d, 150);
}
step++; // Increment the step
// Draw the hexagon!
// First, come up with the corners.
vertices = [];
for(v = 1; v < 7; v++){
angle = v * 60;
vertex = point.destinationPoint(d / Math.sqrt(3), angle);
vertices.push({lat: vertex.lat, lng: vertex.lon});
}
// Create the shape
hexagon = new google.maps.Polygon({
map: map,
paths: vertices,
strokeColor: '#090',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#090',
fillOpacity: 0.1,
draggable: false,
});
// Push it to hexgrid so we can delete it later
hexgrid.push(hexagon)
}
// Return to the left.
point = leftPoint;
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
Please consider that Google Maps is in Mercator Projection.
You have to compensate for the sphere of the globe on the projection.
https://en.wikipedia.org/wiki/Mercator_projection

How to add text on circle and how to combine circle when zoom out different cicle

I have more than 1000 markers at 3 different location in my Map.
I read Lat and Long from a text file and render it in Google maps and create circle over them on the basis of country name. And count the number of markers in those circle.
Now what i am not able to do is?
(1) I have to print the text of count on those circle (How to do without using Cluster ?)
(2) When i zoom out circle overlaps . So whenever circle overlaps it should combine the 2 radius of these two circles and should make one big circle covering the markers of the two smaller (smaller 2 will now disappear resulting on total of marker on the bigger one only).
My full code to do this (http://prntscr.com/6kt30w) is :
$.ajax({
type: 'GET',
url: './App_Start/TextFile/latLongList3.txt',
dataType: 'text',
}).success(function (data)
{
var s2 = data.replace(/^.*$/, " ").replace(/\r\n/g, " ");
var array = s2.split(/[ ]+/g);
var test = [].concat.apply([], array.map(function (array) { return array.split(/\s+/); }))
var col1 = [];
var col2 = [];
var col3 = [];
var j = 0;
for (var i = 0; i <= test.length - 3; i = i + 3)
{
col1[j] = test[i];
col2[j] = test[i + 1];
col3[j] = test[i + 2];
var myLatlng = new google.maps.LatLng(col3[j], col2[j]);
marker = new google.maps.Marker(
{
position: myLatlng,
map: map,
title: 'Hello World! ' + col1[j]
});
markers.push(marker);
if (j > 0) {
LatLong[j] = myLatlng;
}
j++;
}
})
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
I don't want to use MarkerClusterer because it is very small. Yes it's true that it will do the 2 tasks i want to accomplish but the problem i feel with it is when i have markers all over the country then MarkerClusterer just hovers over a very little part of the country whereas i want the circle to hover over all country wherever i have marker and it should have text on it. So if there is any alternative to make the size of cluster such that it cover all the markers in the entire country(because my 1 country is full of markers) and has text on it than any way to do this is welcomed too.
Could some one please help me in solving the 2 problems ?
I have to print the text of count on those circle (How to do without
using Cluster ?)
You can use the following to get count of marker from marker.length
var markers = [];
for (var i = 0; i < 100; i++) {
var latLng = new google.maps.LatLng(data.photos[i].latitude,
data.photos[i].longitude);
var marker = new google.maps.Marker({'position': latLng});
markers.push(marker);
}
To add the count to circle, you can look at this JSFiddel.
I still have to look more your second problem
Finally i found the solution of it.I simply used MarkerClusterer and got it done by increasing its size.
And it works perfectly for me.

Is it possible to remove the border from RouteBoxer-boxes?

EDIT This question has been answered but I've clarified it for future readers.
RouteBoxer provides a solution of 'boxing in' a route in Google maps so that I can list various points of interest along that route. This technic though creates borders around each box presented on the map. I've attached an image to describe what it looks like.
The code produced to create RouteBoxer looks like this:
<script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/routeboxer/src/RouteBoxer.js"></script>
var directionService = new google.maps.DirectionsService();
var rboxer = new RouteBoxer();
var distance = 20; // km
directionService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
// Box the overview path of the first route
var path = result.routes[0].overview_path;
var boxes = routeBoxer.box(path, distance);
for (var i = 0; i < boxes.length; i++) {
var bounds = box[i];
// Perform search over this bounds
}
}
});
Is it possible to remove the borders surrounding each box on the map?
You have full control. Here is the example above in a fiddle, without black borders -> http://jsfiddle.net/ftgr8dyp/ Look at the function drawBoxes() :
function drawBoxes(boxes) {
boxpolys = new Array(boxes.length);
for (var i = 0; i < boxes.length; i++) {
boxpolys[i] = new google.maps.Rectangle({
bounds: boxes[i],
fillOpacity: 0,
strokeOpacity: 1.0,
strokeColor: '#000000', //<-- change color
strokeWeight: 0, //<-- change strokeWeight from 1 to 0
map: map
});
}
}
It is standard google.maps.Rectangle's you can style as you are used to. There is nothing in the RouterBoxer-code that forces certain design or styles.

Is there a way to use Google Maps API v3 on a server side (Node.js)?

I extend a polygon shape on the client. Please see my question (How to evenly adjust some area to polygon (extend a polygon)?) to understand what I exactly mean. I do all the calculations in browser and then send a result to server and store it in DB. I use this function (from here):
this.extendPolygon = function(polyline, offset) {
var distance = Number(offset) * 1000;
var numPts = polyline.getPath().getLength();
var bounds = new google.maps.LatLngBounds();
for (var i=0; i< numPts; i++) {
bounds.extend(polyline.getPath().getAt(i));
}
var center = bounds.getCenter();
var extendedPolyPts = [];
for (var i=0; i< numPts; i++) {
var heading = google.maps.geometry.spherical.computeHeading(center,polyline.getPath().getAt(i));
var initialDist = google.maps.geometry.spherical.computeDistanceBetween(center,polyline.getPath().getAt(i));
var extendedDist = initialDist + distance;
var extendedPt = google.maps.geometry.spherical.computeOffset(center, extendedDist, heading);
extendedPolyPts.push(extendedPt);
}
extendedPoly = new google.maps.Polygon({
// map: map,
paths:extendedPolyPts,
fillColor:"#00FF00",
strokeWidth:2,
fillOpacity:0.4,
strokeColor:"#0000FF",
strokeOpacity:0.5
});
return extendedPoly;
};
But I'd like to do calculations on a server side. Is it possible to run the function on a server? It uses these functions of GM API:
google.maps.geometry.spherical.computeHeading
google.maps.LatLngBounds
polyline.getPath().getLength()
google.maps.geometry.spherical.computeDistanceBetween
google.maps.geometry.spherical.computeOffset
google.maps.Polygon

Categories