Google Maps API v3 Resize SVG Path Icon With Zoom - google-maps-api-3

I put three icons on a map and they represent buildings on the map, but when I zoom into or out of the map the icon sizes are the same and they no longer correspond to the actual building size on the map. Now I know how to resize png icons by pixels but is there a way to keep the vectoral icons proportional to the map zoom while zooming in-out or do I have to manipulate scale property of the Icon object by catching the zoom event? Thanks.
for (var cnt = 0; cnt < pathArr.length; cnt++) {
var path = {
path: pathArr[cnt].Path,
fillColor: "#CCCCCC",
fillOpacity: 1,
strokeColor: "#666666",
strokeWeight: 4,
scale: 1
};
var pos = new google.maps.LatLng(pathArr[cnt].Lat, pathArr[cnt].Lng);
var marker = new google.maps.Marker({
position: pos,
icon: path,
map: this.Gmap
});
this.MapMarkers.push(marker);
}

The best way to achieve what I want is to use custom overlays and svg:
https://developers.google.com/maps/documentation/javascript/customoverlays

Related

Leaflet polyline not moving on drag/zoom

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

Google Map API v3 arrow zoom level

I'm trying draw polygon arrow using Google Map APT V3. See code below. The problem is when I zoom out the map arrow head remain same. Any way to adjust the zoom level of arrow head?
var myCoordinates = [
new google.maps.LatLng(54.065836, -7.415771),
new google.maps.LatLng(53.219191, -7.261963)
];
var polyOptions = {
path: myCoordinates,
strokeColor: "#FF0000",
strokeOpacity: 1,
strokeWeight: 3
, icons: [{ icon: { path: google.maps.SymbolPath.FORWARD_OPEN_ARROW, scale: 2 }, offset: "100%"}]
}
var it = new google.maps.Polyline(polyOptions);
it.setMap(map);
You could have an event listener for the zoom_changed event on the map, which adjusts the scale property on the icon Symbol object.

Google Map API v3 Infowindow doesn't show up on mouseover/click on a polygon

I am trying to display dynamic data in infowindows whenever user hovers over polygons on the map. Debugging shows the data and other infowindow/polygon settings are all right. I am able to get the color change on mouseover, just that infowindows doesn't show up. What might be the reason behind it? What am I missing here?
statePolygon = new google.maps.Polygon({
paths: stateBorderCoords,
strokeColor: '#f33f00',
strokeOpacity: 1,
strokeWeight: 1,
fillColor: '#ff0000',
fillOpacity: 0.2
});
statePolygon.pId = infoText; // Fetching from a JSON response
statePolygon.wPet = wPet; // Fetching from a JSON response
statePolygon.infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(statePolygon,"mouseover",function(event){
this.setOptions({fillColor: "#00FF00"});
this.infoWindow.setPosition(event.latLng);
this.infoWindow.setContent(this.wPet);
this.infoWindow.open(map, this);
});
google.maps.event.addListener(statePolygon,"mouseout",function(){
this.setOptions({fillColor: "#FF0000"});
this.infoWindow.close();
});
google.maps.event.addListener(statePolygon, 'click', function(){
//createInfoWindow(this.pId);
});
statePolygon.setMap(map);
What happens if you leave out the "this" in the line:
this.infoWindow.open(map, this);
?
I've been fighting with something similar over the last few days and just discovered my code works for google.maps.Markers (as in Google pins) but not for google.maps.Circles (and I guess google.maps.Polygons.)
My guess: "infoWindow.open(map, object)" which tries to anchor the InfoWindow to the object only seems to work for google.maps.Markers, not Circles, Polygons, etc. What does seem to work is "open(map)" which doesn't anchor it to anything. However the position of the infoWindow has to be explicitly set (which you are already doing).
Edit:
In my case this doesn't work (assuming global variable map)
var circle = { clickable: true,
strokeColor: "darkred",
strokeOpacity: 1,
strokeWeight: 1,
fillColor: "green",
fillOpacity: 1,
map: map,
center: new google.maps.LatLng(55.95,-3.19),
radius: 45
};
var marker1 = new google.maps.Circle(circle);
infoWindow = new google.maps.InfoWindow();
infoWindow.setContent("Hello");
inoWindow.setPosition(new google.maps.LatLng(55.95,-3.19));
infoWindow.open(map,marker1);
but this does:
var circle = { clickable: true,
strokeColor: "darkred",
strokeOpacity: 1,
strokeWeight: 1,
fillColor: "green",
fillOpacity: 1,
map: map,
center: new google.maps.LatLng(55.95,-3.19),
radius: 45
};
var marker1 = new google.maps.Circle(circle);
infoWindow = new google.maps.InfoWindow();
infoWindow.setContent("Hello");
infoWindow.setPosition(new google.maps.LatLng(55.95,-3.19));
infoWindow.open(map);
The only difference is in the last line.
Thinking about the above post, setting the position after opening presumably overwrites the anchor position and thus makes it appear.
First you open the InfoWindow, then set its position:
http://jsfiddle.net/fuDfa/
google.maps.event.addListener(statePolygon,"mouseover",function(event){
this.setOptions({fillColor: "#00FF00"});
this.infoWindow.setContent(this.wPet);
this.infoWindow.open(map);
this.infoWindow.setPosition(event.latLng);
});
However, I realized that if the mouse moves on top of the InfoWindow (even if it's on top of the polygon), it will count as if the mouse moved outside the polygon. So, the polygon will turn red and Infowindow will close. But since the mouse is still inside the polygon, the infowindow will open again, causing a flicker.
I don't know a way to get around this (tried a timeout but it's not reliable either). I only thought about putting the Infowindow in a preset position instead of event.latLng.

Google maps and Transparent click-through marker

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 // <------
)

Resize markers depending on zoom Google maps v3

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

Resources