Google maps marker icons - loss in image quality when resizing - google-maps

I'm having icon image quality issues when resizing my own map marker icons (png files) in google maps.
Here is an example of the problem:
Taking Google's 'Simple markers' example code:(developers.google.com/maps/documentation/javascript/examples/marker-simple)
and adding only a new 'icon' object (which I believe has replaced MarkerImage object from v3.11 maps api) gives me the following code (http://codepen.io/anon/pen/AIgkf?editors=100):
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Simple markers</title>
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script>
function initialize() {
var myLatlng = new google.maps.LatLng(-25.363882, 131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var myicon = {
url: 'https://bnuviq.dm2301.livefilestore.com/y2pOGYfm607bdir1fks45DMUo0i9S-R5cZ1yc2Fy6kE6UAqf9qlmcHnwSeMvLrnAFz4YEFrYEu3JxMZBWHOxloZdlHmRhsuZmQR4rdP1G7K76o/blue_20.png?psid=1',
origin: new google.maps.Point(0, 0),
scaledSize: new google.maps.Size(24, 24),
anchor: new google.maps.Point(12, 12)
};
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
icon: myicon,
//draggable: true, // uncomment this draggable property or set draggable=false and icon displays correctly in Chrome???
title: 'Test custom map icon'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
My original png is 100x100 pixels but the image quality of the resized 24x24 icon is not very good. The edges of the white numbers become jagged.
I am using an original png file of 100x100 pixels because I want to use the same image file for both web and iOS/Android apps and the apps want to use larger map icons to prevent pixelisation.
Browser behaviour:
Chrome (Windows/Ubuntu)
icon image quality not good - numbers have jagged edges
Strangely however, if the marker's 'draggable' property is set to 'true', Chrome displays the icon correctly i.e. with no jagged edges???
Firefox (Windows/Ubuntu)
icon image quality not good - numbers have jagged edges
IE (Windows)
icon image quality not good - numbers have jagged edges
Can anyone suggest how to get my resized map icons displaying better?
Is the problem the large size of the original png file or something else? And any ideas why the icon displays correctly in Chrome when 'draggable=true'?
Thanks in advance
p.s. first post, apologies if I've left anything out

Try setting the optimized property in the marker options to false:
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
icon: myicon,
optimized: false, // <------
title: 'Test custom map icon'
});
This ensures that the marker is rendered as a separate DOM element by the browser and the scaling will be better quality.
No need to set draggable to true.

In Maps V3, when you add a custom marker that is not draggable, maps will draw it on the map tiles at the google server, and then send it down to you. When you mark it as draggable, it becomes it's own DOM object. When it is its own DOM object, the browser handles the resizing of the icon, when it is resized at google, their servers handle it. Seems to me that the algorithm Google uses to resize the icon is not as good as the one the browsers use. (and additionally, the algorithm that Chrome uses is better than the one in FF, at least for handling the resizing of text).
Have you considered using custom icons without text in them? they will most definitely appear better when resized. You could always add the text in the infowindow instead...

Related

Google Maps API problem with Marker icon SVG path size on laptop with touchscreen

I am trying to display Google Maps markers with a circular icon as a SVG path.
I have this HTML:
<div id="map-canvas"></div>
And this javascript:
function initialize() {
let mapOptions = {
zoom: 4,
center: new google.maps.LatLng(48, 20)
}
let map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions)
let circle = {
path: 'M 1, 2 a 1,1 0 1,1 2,0 a 1,1 0 1,1 -2,0',
anchor: new google.maps.Point(2, 2),
scale: 10
}
let marker = new google.maps.Marker({
position: map.getCenter(),
icon: circle,
map: map
})
}
google.maps.event.addDomListener(window, 'load', initialize);
http://jsfiddle.net/ea32j950/
Google Maps renders the SVG path as an img tag inside a div tag.
Without touchscreen, both tags have calculated dimensions width: 30px; height: 30px;, which is as expected (in all browsers I tested).
But on a laptop with touchscreen there are some unexpected margins rendered. Both img and div tag have calculated dimensions width: 46px; height: 46px;. Both in Chrome and Firefox:
How can I prevent this difference? Is there a way to override the setting window.navigator['maxTouchPoints'] of the client?
Edit: "Device Manager -> Human Interface Devices -> HID-compliant touch screen -> Disable" seems to cause window.navigator['maxTouchPoints'] = 0 and the issue is gone. Is there any other workaround, which keeps the touchscreen functionality outside of the webpage?
When I draw two markers close to each other, hovering over the marker with lower z-index causes the tooltip of the other marker to show up due to the margin.
I have tried setting a circular MarkerShape but the problem remains: http://jsfiddle.net/shrt8axj/
Edit: I ended up opening a new issue with Google.

Google Maps custom markers on ionic

I am using custom markers on Google Maps, and they work perfectly on browser mode, but the problem happens with device, I can't get picture of marker, not sure if I am placing image of marker right.
This is the code I am using.
var marker = new google.maps.Marker({
position: myLatLng,
map:this.map,
title: 'Pumpa',
icon: { url: "../assets/img/2.png",
scaledSize: new google.maps.Size(30, 30)
} });
any clues where should I put marker image and what path should I use then.
Not sure what the downvotes on the previous answer are about, using
url: "assets/img/2.png"
works for me
i think you need to remove the 2 dots in url of icon

Change maker icon size in Google Maps API v3.21

I'm trying to change the size of my marker icons with Google Maps API. Here is my code:
new google.maps.Marker({
position: {lat: this.model.get('latitude'), lng: this.model.get('longitude')},
title: this.model.get('name'),
icon: {
url: this.model.get('iconUrl'),
size: google.maps.Size(50, 50)
}
});
The icon image is naturally 512x512. It is appearing in the correct location on the map, but it is 512x512 instead of 50x50. I've read similar questions and answers for this problem, but none of them seem to address setting the marker size with this version of the API. For example, others use the MarkerImage class, but that class no longer exists in this version.
I've also tried including the scaledSize property in the icon object, but that doesn't have any effect either.
Does anyone know what I am doing wrong? Here is the 512x512 image I would like to display as 50x50:
Looks like I was missing a new and also had to use scaledSize instead of size. This works for me:
new google.maps.Marker({
position: {lat: this.model.get('latitude'), lng: this.model.get('longitude')},
title: this.model.get('name'),
icon: {
url: this.model.get('iconUrl'),
scaledSize: new google.maps.Size(50, 50)
}
});

google maps api v3 white overlay

I began to use Google Map API recently and I tried the hello world sample in my own webpage. The only difference of my code from the original one is I display the map element in javascript code like this:
function showMap () {
container = document.getElementById("id_container");
container.innerHTML = "<div id=\"map_canvas\"><\/div>";
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}
And in the external css file, I defined the width and height by fixed values for #map_canvas.
But I didn't get the expected result. The map showed for about 1 second and became all white (see the image below). When I zoom the map, I can see it flashing. I have searched on Google but I didn't get any solution and I don't even know what the problem is. Has anyone encountered the same problem before?
After several days' trying, I know what's happening --
I set the background attribute of all divs to be white. Though I reset the background of the map div to be "none", it doesn't work. The only solution is to avoid any definitions that would possibly give it a not "none" background, like "div {background-color: white;}".
However, feel free to set the background color of its parent tags.

Integrating Spiderfier JS into markerClusterer V3 to explode multi-markers with exact same long / lat

I am using markerCLusterer V3 on a db file from Filemaker to generate a (semi-live) map of current delivery locations, based off of addresses. Grabbing the lat/long from Google and populating those
fields is no problem. Generating the map via markerClusterer is no problem. I am even hosting the JS locally so that I can change the maxZoom variable to break the clusters apart above max zoom, so that I can see multiple markers. However, with the markers at exactly the same lat / long, I can only see the last one entered. I would like to integrate OverlappingMarkerSpiderfier into this JS so that after I zoom in past the maxZoom, the markers would "spider" apart to see the markers (as an example, multiple pieces of equipment being delivered to the same address). I can't find any info here on on the web of how to do this. It's either that simple and I'm missing it or it hasn't been done yet. Thanks in advance for any help!
I'm using:
MarkerClustererPlus-2.0.14 and
OverlappingMarkerSpiderfier-version-??
At first only the clustering works, clicking on a cluster, zooms in but 2 or more markers on the exact same point still stay a cluster even when zoomed in to the maximum. Unfortunately no spiderfier showed up :-(.
But than a noticed the setMaxZoom() method on markerClusterPlus. When setting this too your appropriate zoom level (15 for me) spiderfier takes over beyond the zoom level. It looks like markerClusters says it ain't my business anymore from here on it's up to spiderfier :-).
Setting the max zoom will fix the problem:
minClusterZoom = 14;
markerCluster.setMaxZoom(minClusterZoom);
but for viewing purposes you may want to create a clusterclick listener to prevent it from zooming in really close on a cluster of points at the same location (clicking a cluster set the bounds of the map to cover the points in the cluster; if all points are at the same location it will zoom in all the way, which tends to look bad):
google.maps.event.addListener(markerCluster, 'clusterclick', function(cluster) {
map.fitBounds(cluster.getBounds()); // Fit the bounds of the cluster clicked on
if( map.getZoom() > minClusterZoom+1 ) // If zoomed in past 15 (first level without clustering), zoom out to 15
map.setZoom(minClusterZoom+1);
});
Integrating Spiderfier JS into markerClusterer
Download the oms.min.js file from here
Download the markerClusterer.js and the image folder from here
In order to make both work together you only need to add a maxZoom to the clusterMarker object
new MarkerClusterer(map, clusterMarker, {imagePath: 'images/m', maxZoom: 15});
(Zoomlevel 0 is the complete earth, and 20 is pretty close to the ground). This means that if you zoom into the map further as zoom level 15 (for example if you click on a cluster) then the clusters are not shown anymore. If you now click on markers that are on the exact same location (or close to each other) Spiderfier JS will trigger.
It follows now a minimal working example. I made some comments in the code so I think its self-explanatory, but here are some things to mention:
Replace YOUR_API_KEY with your api key
Make sure to load oms.min.js after you loaded the google maps api
Example:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script src="https://maps.googleapis.com/maps/apijs?key=YOUR_API_KEY">
</script>
<script src="oms.min.js"></script>
<script src="markerclusterer.js"></script>
<script>
window.onload = function() {
// cluster marker
var clusterMarker = [];
var map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng( 50, 3),
zoom: 6,
mapTypeId: 'terrain'
});
// Create infowindow
var infoWindow = new google.maps.InfoWindow();
// Create OverlappingMarkerSpiderfier instsance
var oms = new OverlappingMarkerSpiderfier(map,
{markersWontMove: true, markersWontHide: true});
// This is necessary to make the Spiderfy work
oms.addListener('click', function(marker) {
infoWindow.setContent(marker.desc);
infoWindow.open(map, marker);
});
// Some sample data
var sampleData = [{lat:50, lng:3}, {lat:50, lng:3}, {lat:50, lng:7}];
for (var i = 0; i < sampleData.length; i ++) {
var point = sampleData[i];
var location = new google.maps.LatLng(point.lat, point.lng);
// create marker at location
var marker = new google.maps.Marker({
position: location,
map: map
});
// text to appear in window
marker.desc = "Number "+i;
// needed to make Spiderfy work
oms.addMarker(marker);
// needed to cluster marker
clusterMarker.push(marker);
}
new MarkerClusterer(map, clusterMarker, {imagePath: 'images/m', maxZoom: 15});
}
</script>
</head>
<body><div id="map" style='width:400px;height:400px;'></div></body></html>
Recommendation
If you are starting from scratch, I would recommend to use the JS Libary Leaflet. Because this library provides you with the LeafletMarkerCluster plugin which is basically markercluster with Spiderfier integrated, and a lot of other cool stuff.
Advantage:
Cluster look really nice
Leaflet really easy to use and looks pretty
You do not need to customize the code, because Spiderfier and markerCluster already integrated
Some fancy other stuff: Like showing the border on hover of a region where marker are spread.
You can freely choose your map-tiles-provider and are no longer restricted to google maps (possible providers here)
Downsites:
You may need to invest 30min to learn and use the Leaflet API instead of the Google API
If you want to use Google Map Tiles, then you need to use this plugin, because you are only allowed to use the Google Tiles when using the Google API. This plugin is a wrapper for the Google API.
Here is an example code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
<link rel="stylesheet" href="leaflet/dist/MarkerCluster.css" />
<link rel="stylesheet" href="leaflet/dist/MarkerCluster.Default.css" />
<script src="leaflet/dist/leaflet.markercluster-src.js"></script>
<script>
$(document).ready(function(){
var tiles = L.tileLayer(***);//Depending on your tile provider
var map = new L.Map('map', {center: latlng, zoom: 1, layers: [tiles]});
var markers = new L.MarkerClusterGroup({
removeOutsideVisibleBounds: true,
spiderfyDistanceMultiplier: 2,
maxClusterRadius: 20
});
var markersList = [];
var sampleData = [{lat:50, lng:3}, {lat:50, lng:3}, {lat:50, lng:7}];
for (var i = 0; i < sampleData.length; i ++) {
var point = sampleData[i];
var location = new L.LatLng(point.lat, point.lng);
// create marker at location
var m = new L.Marker(location);
m.bindPopup("Number" +i); //Text to appear in window
markersList.push(m);
markers.addLayer(m);
}
var bounds = markers.getBounds();
map.fitBounds(bounds)
map.addLayer(markers);
}
</head>
<body><div id="map" style='width:400px;height:400px;'></div></body></html>
I came across this post because I was looking for the exact same thing, but lucky for me I have made it work!
I honestly didn't do anything special, I followed the integration guide for MarkerClusterer, and then followed the integration guide for OverlappingMarkerSpiderfier and they work flawlessly together.
When I click/zoom in on a cluster of properties that are all at the same address, initially it just shows the "top" marker, but when I click it, they Spiderfy just like you'd want them too!
What specific result are you getting when you try to use the two scripts together?
var markerClusterer = new MarkerClusterer(map, myMarkers, {
maxZoom: 15,
zoomOnClick: false
});
//zoom 0 corresponds to a map of the Earth fully zoomed out, 20 is closeup
//markerCluster goes away after zoom
//turn off zoom on click or spiderfy won't work