Google Map API - Multiple Icons in Wrong Spot

Google Map API - multiple icons in wrong spot

There is an issue with the MarkerWithLabel library. Issue.

Google Maps API markers with multiple icons

As promised, I've included my complete, working code. This function draws a marker as a canvas image. The soldier and his health bar are drawn separately, as the soldier is usually static (unless we want to animate him which we can do through canvas) but the health bar changes when he gets hit. I've tested the code in my game and it's working perfectly.

geocodezip, I didn't end up going with your suggestion for the main reason of not wanting to double the number of markers in the game for performance reasons. A player can have hundreds of units in the game, and there can be hundreds of players at any one time, so doubling the markers to achieve what I wanted could have impacted performance. Your code is great though, and I may use it in situations where doubling markers wouldn't have an impact on performance.

Code below:

function createUnitMarker(latLng, unitData) {
var img = new Image();
img.crossOrigin = "Anonymous";
img.src = 'http://yourservername.com/' + unitData.icon;

img.onload = function() {
// google maps markers can only be created inside the onload function, otherwise nothing is drawn

// source: GitHub, viktorkelemen/Custom canvas google maps marker
// create the marker and all associated elements
var canvas, context;
var color = "blue";
var healthBar = { // this object controls aspects of the unit health bar
width: 62,
height: 10,
x: 5,
y: 82
}

canvas = document.createElement("canvas");
context = canvas.getContext("2d");

canvas.width = unitData.width;
canvas.height = unitData.height;

function drawBar(percent, color) {
// this function draws the unit health bar

// colours the health bar background grey
context.fillStyle = "gray";
context.fillRect(healthBar.x, healthBar.y, healthBar.width, healthBar.height);

// fills the health bar with the passed colour, or empty it if the unit dies
if (typeof percent == undefined || percent == null || percent == NaN) {
percent = 100;
}

if (typeof color == undefined || color == null || color == NaN) {
color = "green";
}

// we want to ensure that the health bar fill is always contained within the health bar width
var width = Math.min(percent * healthBar.width, healthBar.width);
width = Math.max(width, 0);

// colour-code the health bar depending on health
if (percent < 0.4) {
color = "red";
}

else if (percent < 0.7) {
color = "orange";
}

else {
color = "green";
}

context.fillStyle = color;
context.fillRect(healthBar.x, healthBar.y, width, healthBar.height);

// places a black stroke around the health bar for greater visibility
context.lineWidth = 2;
context.strokeStyle = "black";
context.strokeRect(healthBar.x, healthBar.y, healthBar.width, healthBar.height);
}

function drawIcon(img, width, height) {
// this function draws the unit

if (typeof img === "undefined" || img === null || img === "" || img === NaN) {
img = img;
}

if (typeof width === "undefined" || width === null || width === "" || width === NaN) {
width = unitData.width;
}

if (typeof height === "undefined" || height === null || height === "" || height === NaN) {
height = unitData.height;
}

context.clearRect(0, 0, width, height);

// save the canvas context
context.save();

// draw the image
context.drawImage(img, 0, 0);

context.restore();
}

drawIcon(img, unitData.width, unitData.height);

// create an icon based on the png we want to use
var icon = {
url: canvas.toDataURL(),
size: new google.maps.Size(unitData.width, unitData.height), // the dimensions in pixels of the marker image
origin: new google.maps.Point(0, 0), // the origin for this image, where top left is (0, 0)
labelOrigin: new google.maps.Point(25, 40), // the position of the label relative to the icon
anchor: new google.maps.Point(unitData.width / 2, unitData.height / 2) // the anchor for this image, or where the "base point" is located
}

// this is the key unit object. it should store all information directly related to this unit
var marker = new google.maps.Marker({
position: latLng, // the lat/lon where the marker is drawn
label: {
color: "yellow",
fontFamily: "Oswald",
fontSize: "20px",
fontWeight: "bold", // use CSS font-weight properties
text: unitData.unit_ID.toString(),
visibility: "hidden"
},
title: "Infantry", // title on hover
icon: icon, // the icon to be drawn, using an image file or canvas
animation: google.maps.Animation.DROP, // a bit of flair :)
// every element below this point is game-specific and not part of the google maps api
unitID: unitData.unit_ID, // the unique unit id for this unit as returned by the server
etc: 0
});

// to add the marker to the map, call setMap()
marker.setMap(gv.map);

// draw the health bar last so that it's always on top, and after we know the unit's current/max health
var healthPercent = marker.current_health / marker.max_health;
drawBar(healthPercent);

// these are the key commands required every time we need to re-draw something on the unit
icon.url = canvas.toDataURL(); // re-draws the canvas, usually because we have changed something above this line
icon = JSON.parse(JSON.stringify(icon)); // stringifies the icon properties
marker.setIcon(icon); // applies the changed icon properties to the icon

marker.addListener('label_changed', function() {
// this listener is intended to update the unit's health bar on attack. it's a bit of a hack as it relies on changes to the marker's label to fire an event. other options are changing a marker's title, or writing a custom event (which is more involved)
// draw the health bar last so that it's always on top, and after we know the unit's current/max health
healthPercent = this.current_health / this.max_health;
drawBar(healthPercent);

icon = {
url: canvas.toDataURL(),
size: new google.maps.Size(unitData.width, unitData.height), // the dimensions in pixels of the marker image
origin: new google.maps.Point(0, 0), // the origin for this image, where top left is (0, 0)
labelOrigin: new google.maps.Point(25, 40), // the position of the label relative to the icon
anchor: new google.maps.Point(unitData.width / 2, unitData.height / 2) // the anchor for this image, or where the "base point" is located
}

// all we want to do is change the icon url, but we can't just pass it to setIcon as it will lose the other icon properties. instead, we clone the icon object and change the url in the clone, passing it to setIcon when selected
icon = JSON.parse(JSON.stringify(icon));

this.setIcon(icon);
});
}
}

Google maps marker Showing wrong Position?

The longitude is not getting set correctly. You have an error on this line

let latLong = {lat:data.geometry.location.lat,lng:data.geometry.location.lat}

You are setting data.geometry.location.lat to both lat as well as lng.

Change data.geometry.location.lat to data.geometry.location.lng while setting the longitude

let latLong = {lat:data.geometry.location.lat,lng:data.geometry.location.lng}

Google maps API V3 - multiple markers on exact same spot

Take a look at OverlappingMarkerSpiderfier.

There's a demo page, but they don't show markers which are exactly on the same spot, only some which are very close together.

But a real life example with markers on the exact same spot can be seen on http://www.ejw.de/ejw-vor-ort/ (scroll down for the map and click on a few markers to see the spider-effect).

That seems to be the perfect solution for your problem.

Google Maps V3: Marker Images displayed in incorrect position after map drag and zoom

I'm fired.

Just after the block of code in the example, I had

if (init) {
//a bunch of stuff, PLUS
this.map.fitBounds(bounds);

} else {
//a bunch of other stuff, BUT NO fitBounds

}

so, adding

this.map.fitBounds(bounds);

in both logic paths fixed the problem



Related Topics



Leave a reply



Submit