I have a Google map running on the v3 API, I added some custom markers, is it possible to make them scale depending on the zoom level of the map?
I tried searching the reference but can't seem to find any methods to resize a MarkerImage.
Maybe I have to remove markers everything the map changes zoom and create new markers in a different size?
This code will resize every time the map is zoomed so it always covers the same geographic area.
//create a marker image with the path to your graphic and the size of your graphic
var markerImage = new google.maps.MarkerImage(
'myIcon.png',
new google.maps.Size(8,8), //size
null, //origin
null, //anchor
new google.maps.Size(8,8) //scale
);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(38, -98),
map: map,
icon: markerImage //set the markers icon to the MarkerImage
});
//when the map zoom changes, resize the icon based on the zoom level so the marker covers the same geographic area
google.maps.event.addListener(map, 'zoom_changed', function() {
var pixelSizeAtZoom0 = 8; //the size of the icon at zoom level 0
var maxPixelSize = 350; //restricts the maximum size of the icon, otherwise the browser will choke at higher zoom levels trying to scale an image to millions of pixels
var zoom = map.getZoom();
var relativePixelSize = Math.round(pixelSizeAtZoom0*Math.pow(2,zoom)); // use 2 to the power of current zoom to calculate relative pixel size. Base of exponent is 2 because relative size should double every time you zoom in
if(relativePixelSize > maxPixelSize) //restrict the maximum size of the icon
relativePixelSize = maxPixelSize;
//change the size of the icon
marker.setIcon(
new google.maps.MarkerImage(
marker.getIcon().url, //marker's same icon graphic
null,//size
null,//origin
null, //anchor
new google.maps.Size(relativePixelSize, relativePixelSize) //changes the scale
)
);
});
Unfortunately, you would have to setIcon every single time. However, you can pre-define them, and then just apply them to the marker.
zoomIcons = [null, icon1, icon2]; // No such thing as zoom level 0. A global variable or define within object.
marker.setIcon(zoomIcons[map.getZoom()]);
To add to the map an image that follows the zoom level, use a GroundOverlay.
https://developers.google.com/maps/documentation/javascript/groundoverlays
Related
I want to learn pixels band values, for example when I clik on mNDWI image in screen of Earth Engine, I need learning values of red, green and blue
var geometry=ee.Geometry.Polygon([[38.877002459052335,40.75574968156597],
[41.206104021552335,41.17882292442983],
[40.645801287177335,41.59918091806734],
[40.052539568427335,41.84517989453356],
[39.569141130927335,41.886088143011904],
[38.800098162177335,41.48405920501165],
[38.877002459052335,40.75574968156597],
]);
var s2SR = ee.ImageCollection('COPERNICUS/S2_SR')
//filter start and end date
.filter(ee.Filter.calendarRange(2020,2020,'year'))
.filter(ee.Filter.calendarRange(8,8,'month'))
//filter according to drawn boundary
.filterBounds(geometry)
.filterMetadata('CLOUD_COVERAGE_ASSESSMENT', 'less_than',10);
//Map.addLayer(s2SR, {bands:['B4', 'B3', 'B2'], min:0, max:8000}, 's2SR');
// adding mNDWI function
var addMNDWI = function(image) {
var mndwi = ee.Image(image).normalizedDifference(['B3', 'B11']).rename('MNDWI');
return ee.Image(image).addBands(mndwi);
};
var mndwı=s2SR
.map(addMNDWI);
Map.addLayer(mndwı.first(), { min:245, max:5000}, 'mndwı');
It is simple to view the values for any displayed image. First, click on the “Inspector” tab in the top right pane of the Earth Engine Code Editor.
Then, click wherever you want on the map. The Inspector tab will display:
The coordinates of the location you clicked.
The values of every band of every image under that point. (When there are many, as a chart.)
The details of the image (or feature), including properties.
Please find the google mapsApi documentation https://developers.google.com/maps/documentation/javascript/shapes#editable
Please zoomout to world view and then expand the region selection towards right in single attempt. At some point you could observe that the selection became unstable and it selects entirely different section of the world.
By default the rectangle selection tool seems to look for shortest possible path to complete the shape. This creates a strange behavior when attempting to draw a very very large region.
I wanted to click and drag a very large region that covered a large geography. I was dragging West to East. Once the size of the object was very large, the selection reserved and was covering a completely different section of the world.
I attempt to expand a boundary to include the entire world. When the boundary goes far enough, again the region appears to be the minimal/smaller area.
Expected behavior was the selector to continue expanding in the direction the user intends. In this case I would expect the selector to continue its west to east expansion.
https://developers.google.com/maps/documentation/javascript/shapes#editable
var bounds = {north: 44.599, south: 44.490, east: -78.443, west: -78.649 }; // Define a rectangle and set its editable property to true. var rectangle = new google.maps.Rectangle({bounds: bounds, editable: true});
Please tries to expands rectangle to further right
Is there a solution to resolve the scenario mentioned?
Please let me know if further details required.
As I said in my comment, when you drag it "too far", the rectangle left and right coordinates (longitude) get inverted.
In other words, if you drag it too far to the right, right will become left and left will be where you dragged the right side to. And the opposite in the other direction. So by comparing where was the left with where is the right or vice-versa, you can detect if your rectangle left and right got inverted and invert it again... This way you can achieve what you want.
And of course if you drag the right side further to the right than where the left was (or the other way around), it will reset, as you can't have a rectangle overlapping itself around the globe.
The UI can be a bit confusing though, as you can see the rectangle lines get inverted but you can't do much about that.
var map;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(0, 0),
zoom: 2,
zoomControl: false
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Set origin bounds
var originBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(-20, -100),
new google.maps.LatLng(20, 20)
);
// Get left/right coords
var left = originBounds.getSouthWest().lng();
var right = originBounds.getNorthEast().lng();
// Create editable rectangle
var rectangle = new google.maps.Rectangle({
bounds: originBounds,
fillColor: 'white',
fillOpacity: .5,
editable: true,
map: map
});
// Check for rectangle bounds changed
google.maps.event.addListener(rectangle, 'bounds_changed', function() {
// Get currents bounds and left/right coords
var newBounds = rectangle.getBounds();
var newLeft = newBounds.getSouthWest().lng();
var newRight = newBounds.getNorthEast().lng();
if ((newRight === left) || (newLeft === right)) {
// User dragged "too far" left or right and rectangle got inverted
// Invert left and right coordinates
rectangle.setBounds(invertBounds(newBounds));
}
// Reset current left and right
left = rectangle.getBounds().getSouthWest().lng();
right = rectangle.getBounds().getNorthEast().lng();
});
}
function invertBounds(bounds) {
// Invert the rectangle bounds
var invertedBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng()),
new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng())
);
return invertedBounds;
}
initialize();
#map-canvas {
height: 150px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js"></script>
I'm using leaflet with custom CRS.Simple projection. If I draw a polyline at the page Load it is more or less drawn ok (Although much more accurate in firefox than in chrome) but if I drag the map the polyline remains in the same place of the browser window, so then appears shifted respect of the background map.
Example:
Initial load
After drag the map, the map moves but the polyline remains in the same place
To add the polyline I'm converting the coordinates to the CRS.Simple projection. I don't think there is a problem here as every other map marker or text appears correctly
.....
//initialize leaflet map
map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
zoomControl: false,
crs: L.CRS.Simple //simple coordinates system
}).setView([0, 0], mapMaxZoom);
//set the bounds of the map to the current dimension
var mapBounds = new L.LatLngBounds(
map.unproject([0, mapHeight], mapMaxZoom),
map.unproject([mapWidth, 0], mapMaxZoom)
);
//load the tiles
map.fitBounds(mapBounds);
L.tileLayer(mapData.info.tiles+'/{z}/{x}/{y}.png', {
minZoom: mapMinZoom,
maxZoom: mapMaxZoom,
bounds: mapBounds,
attribution: '',
noWrap: true,
continuousWorld: true
}).addTo(map);
.....
var pointList = [getMapCoordinates(1750,1750),
getMapCoordinates(1520,1764),
getMapCoordinates(1300,1560),
getMapCoordinates(1132,1258),
getMapCoordinates(1132,1060),
getMapCoordinates(926,960)];
polyline = new L.Polyline(pointList, {
color: 'red',
weight: 3,
opacity: 0.5,
smoothFactor: 1
});
polyline.addTo(map);
....
function getMapCoordinates(px,py)
{
//as we use simple system, transform the point (based on pixel) on map coordinates that leaflet understand
return map.unproject([px, py], map.getMaxZoom());
}
Any idea what I'm doing wrong, or is it a bug? Any workaround would be appreciated
Ok, it seems the problem was in stable version (0.7.3) Using dev version (1.0-dev) works ok and even solves the problem with the different browser drawing
I draw a polyline to a google maps, and put markers to every point of it. I want to hide these markers higher zoom levels, therefore I use the Marker Manager. It's works well.
After draw everything, the map zoom to the bound of the polyline with the google.map.fitBound command. But if it zoom to far, where the markers would be hided, they don't. They still visible. If I drag or zoom again, they are hiding.
I use the markermanager in the simple way:
var aMarkers [...array of markers...],
markerMgr = new MarkerManager(map);
google.maps.event.addListener(markerMgr, 'loaded', function() {
markerMgr.addMarkers(aMarkers[0], 15, 0);
markerMgr.addMarkers(aMarkers[1], 12, 0);
markerMgr.addMarkers(aMarkers[2], 10, 0);
markerMgr.refresh();
});
Is anybody met this problem before? Thank is advance!
I had this same problem. When creating your markers, don't set the "map" parameter in the marker options. The MarkerManager will add the markers to your map as you zoom in and out.
For example:
var newMarker = new google.maps.Marker({
//map: map
position: markerPosition,
icon: icon
});
mgr.addMarker( newMarker, 9 );
Why do you have the maximum zoom for the markers set to 0?
MarkerManager.addMarkers(aMarkers[0], minZoom, maxZoom(optional))
Try (that parameter is optional per the documentation):
var aMarkers [...array of markers...],
markerMgr = new MarkerManager(map);
google.maps.event.addListener(markerMgr, 'loaded', function() {
markerMgr.addMarker(aMarkers[0], 15);
markerMgr.addMarker(aMarkers[1], 12);
markerMgr.addMarker(aMarkers[2], 10);
markerMgr.refresh();
});
Working Example
I'm using Google maps api v3. In the middle of the map there is a (custom) flag marker with large transparent areas around the flag body. Under the flag icon there are another markers that are inaccessible because of dead transparent areas. Is there any way to set flag marker to be click-through? I cant find solution.
Yes, it is possible the Marker class has a shape property that takes a MarkerShape object. This describes the clickable region for the Marker.
Here is Google's Example. They have a custom flag image and adjusted the shape so that only the rectangular flag section is clickable. With the MarkerShape object you can draw a Circle, Retangle, or Polygon shape area.
Google example code segment:
function setMarkers(map, locations) {
// Add markers to the map
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.
// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.
var image = new google.maps.MarkerImage('images/beachflag.png',
// This marker is 20 pixels wide by 32 pixels tall.
new google.maps.Size(20, 32),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is the base of the flagpole at 0,32.
new google.maps.Point(0, 32));
var shadow = new google.maps.MarkerImage('images/beachflag_shadow.png',
// The shadow image is larger in the horizontal dimension
// while the position and offset are the same as for the main image.
new google.maps.Size(37, 32),
new google.maps.Point(0,0),
new google.maps.Point(0, 32));
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var shape = {
coord: [1, 1, 1, 20, 18, 20, 18 , 1],
type: 'poly'
};
for (var i = 0; i < locations.length; i++) {
var beach = locations[i];
var myLatLng = new google.maps.LatLng(beach[1], beach[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
shadow: shadow,
icon: image,
shape: shape,
title: beach[0],
zIndex: beach[3]
});
}
}
Yes, set the clickable property to false. for example:
const newMarker = new google.maps.Marker(
position: {
lat: 10,
lng: -66
},
clickable: false // <------
)