[英]Google maps api v3 - multiple markers, multiple infowindows, 3 icons
[英]Google Maps API markers with multiple icons
我想使用 Google Maps JavaScript API 實現一個復雜的標記,該 API 結合了靜態圖像(PNG 文件)和可“動態”編輯的圖像,例如 SVG。 這就是我的目標:
我已經將“士兵”構建為 PNG 文件標記,並且一切正常。 但是,我似乎找不到將多個元素添加到標記的“圖標”屬性的方法。 我已閱讀所有 Google Maps API 文檔、參考和示例,並查看了此鏈接:
該鏈接似乎並沒有完全幫助,因為我希望士兵下方的紅條能夠動態更改,因為它代表士兵的健康狀況。
有沒有人有一個可行的解決方案? 我不介意它不使用SVG並使用CSS甚至Canvas,只要它呈現一個長度可以動態調整的簡單矩形即可。
謝謝。
一種選擇是使用兩個單獨的標記,綁定在一起(如果您需要移動它們):
var soldier = new google.maps.Marker({
position: map.getCenter(),
map: map,
draggable: true,
icon: { url: "http://www.geocodezip.com/mapIcons/greenSoldier.png",
scaledSize: new google.maps.Size(32,48)
}
});
var health = new google.maps.Marker({
position: soldier.getPosition(),
map: map,
icon: { path: "M 100 100 L 150 100 L 150 110 L 100 110 z",
scale: 0.5,
fillColor: "red",
fillOpacity: 1.0,
strokeColor: "black",
strokeWeight: 2,
anchor: new google.maps.Point(125,110)
}
});
health.bindTo("position", soldier);
代碼片段:
function initialize() { var map = new google.maps.Map( document.getElementById("map_canvas"), { center: new google.maps.LatLng(37.4419, -122.1419), zoom: 13, mapTypeId: google.maps.MapTypeId.ROADMAP }); var soldier = new google.maps.Marker({ position: map.getCenter(), map: map, draggable: true, icon: { url: "https://www.geocodezip.net/mapIcons/greenSoldier.png", scaledSize: new google.maps.Size(32, 48) } }); var health = new google.maps.Marker({ position: soldier.getPosition(), map: map, icon: { path: "M 100 100 L 150 100 L 150 110 L 100 110 z", scale: 0.5, fillColor: "green", fillOpacity: 1.0, strokeColor: "black", strokeWeight: 2, anchor: new google.maps.Point(125, 110) } }); health.bindTo("position", soldier); setInterval(changeLength, 5000); var idx = 0; function changeLength() { var icon = health.getIcon(); icon.fillColor = colors[(idx) % colors.length]; icon.path = lengths[(idx++) % lengths.length]; health.setIcon(icon); } } google.maps.event.addDomListener(window, "load", initialize); var colors = ["green", "green", "yellow", "red"]; var lengths = ["M 100 100 L 150 100 L 150 110 L 100 110 z", "M 100 100 L 140 100 L 140 110 L 100 110 z", "M 100 100 L 130 100 L 130 110 L 100 110 z", "M 100 100 L 120 100 L 120 110 L 100 110 z" ]
html, body, #map_canvas { height: 100%; width: 100%; margin: 0px; padding: 0px }
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script> <div id="map_canvas"></div>
正如所承諾的那樣,我已經包含了我完整的工作代碼。 此函數將標記繪制為畫布圖像。 士兵和他的生命條是分開繪制的,因為士兵通常是靜態的(除非我們想為他設置動畫,我們可以通過畫布來做)但是當他被擊中時,生命條會發生變化。 我已經在我的游戲中測試了代碼,它運行良好。
geocodezip,我最終沒有采納您的建議,主要原因是出於性能原因不想將游戲中的標記數量增加一倍。 一個玩家可以在游戲中擁有數百個單位,並且任何時候都可能有數百個玩家,因此將標記加倍以實現我想要的效果可能會影響性能。 不過,您的代碼很棒,我可能會在加倍標記不會對性能產生影響的情況下使用它。
代碼如下:
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);
});
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.