英文:
Adding Multiple HTML Markers to Google Maps API
问题
以下是您提供的代码部分的翻译:
function init() {
// 左侧
var locations = [
['500k', -33.890542, 151.274856, 1],
['1.3M', -33.923036, 151.259052, 2],
['2.3M', -34.028249, 151.157507, 3],
['750k', -33.800101, 151.287478, 4],
['200K', -33.950198, 151.259302, 5],
];
var map = new google.maps.Map(document.getElementById('mapdiv'), {
zoom: 10,
center: new google.maps.LatLng(-33.92, 151.25),
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
var infowindow = new google.maps.InfoWindow();
for (i = 0; i < locations.length; i++) {
var price = locations[i][0];
var latMarker = locations[i][1];
var lngMarker = locations[i][2];
function HTMLMarker(lat, lng) {
this.lat = lat;
this.lng = lng;
this.pos = new google.maps.LatLng(lat, lng);
}
HTMLMarker.prototype = new google.maps.OverlayView();
HTMLMarker.prototype.onRemove = function() {}
// 初始化您的 HTML 元素
HTMLMarker.prototype.onAdd = function() {
div = document.createElement('div');
div.className = "arrow_box d-flex";
div.innerHTML = "<div class='m-auto'>SR " + price + "</div>";
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
}
HTMLMarker.prototype.draw = function() {
var overlayProjection = this.getProjection();
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
var panes = this.getPanes();
panes.overlayImage.style.left = position.x + 'px';
panes.overlayImage.style.top = position.y - 30 + 'px';
}
// 使用它
var htmlmarker = new HTMLMarker(latMarker, lngMarker);
htmlmarker.setMap(map);
}
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#mapdiv {
height: 100%;
width: 100%;
}
#mapdiv2 {
height: 100%;
width: 100%;
}
div.arrow_box {
font-size: 10px;
width: 60px;
height: 20px;
background: blue;
border-radius: 10px;
margin: 10px -30px;
color: white;
cursor: pointer;
overflow: hidden;
}
div.arrow_box img {
min-width: 150px;
width: auto;
max-height: 100px;
height: auto;
border-radius: 5px;
}
.arrow_box:after {
top: 30px;
left: 0px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-color: rgba(136, 183, 213, 0);
border-top-color: blue;
border-width: 5px;
margin-left: -5px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<title>地图测试</title>
</head>
<style>
</style>
<body class="bg-dark d-flex p-1" onload="init()">
<div class="border border-primary bg-dark rounded" id="mapdiv">
</div>
</body>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous">
</script>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
</html>
请注意,上述代码的翻译只包括HTML、CSS和JavaScript的部分,不包括代码中的注释。
英文:
I've been trying to add multiple HTML markers on Google Maps so I can add CSS styles and also include text inside it and also animate the markers as you zoom in and out so I can make them smaller or bigger or turn them into a dot depending on the zoom level or add icons.
The style that I am trying to achieve is shown in this following example.
I've tried my best but the best I could muster up without critical errors is this following, for some reason they are stacking in one marker:
Here is the code I got.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function init() {
// LEFT
var locations = [
['500k', -33.890542, 151.274856, 1],
['1.3M', -33.923036, 151.259052, 2],
['2.3M', -34.028249, 151.157507, 3],
['750k', -33.800101, 151.287478, 4],
['200K', -33.950198, 151.259302, 5],
];
var map = new google.maps.Map(document.getElementById('mapdiv'), {
zoom: 10,
center: new google.maps.LatLng(-33.92, 151.25),
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
var infowindow = new google.maps.InfoWindow();
for (i = 0; i < locations.length; i++) {
var price = locations[i][0];
var latMarker = locations[i][1];
var lngMarker = locations[i][2];
function HTMLMarker(lat, lng) {
this.lat = lat;
this.lng = lng;
this.pos = new google.maps.LatLng(lat, lng);
}
HTMLMarker.prototype = new google.maps.OverlayView();
HTMLMarker.prototype.onRemove = function() {}
//init your html element here
HTMLMarker.prototype.onAdd = function() {
div = document.createElement('div');
div.className = "arrow_box d-flex";
div.innerHTML = "<div class='m-auto'>SR " + price + "</div>";
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
}
HTMLMarker.prototype.draw = function() {
var overlayProjection = this.getProjection();
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
var panes = this.getPanes();
panes.overlayImage.style.left = position.x + 'px';
panes.overlayImage.style.top = position.y - 30 + 'px';
}
// to use it
var htmlmarker = new HTMLMarker(latMarker, lngMarker);
htmlmarker.setMap(map);
}
}
<!-- language: lang-css -->
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#mapdiv {
height: 100%;
width: 100%;
}
#mapdiv2 {
height: 100%;
width: 100%;
}
div.arrow_box {
font-size: 10px;
width: 60px;
height: 20px;
background: blue;
border-radius: 10px;
margin: 10px -30px;
color: white;
cursor: pointer;
overflow: hidden;
}
div.arrow_box img {
min-width: 150px;
width: auto;
max-height: 100px;
height: auto;
border-radius: 5px;
}
.arrow_box:after {
top: 30px;
left: 0px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-color: rgba(136, 183, 213, 0);
border-top-color: blue;
border-width: 5px;
margin-left: -5px;
}
<!-- language: lang-html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<title>Map Test</title>
</head>
<style>
</style>
<body class="bg-dark d-flex p-1" onload="init()">
<div class="border border-primary bg-dark rounded" id="mapdiv">
</div>
</body>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous">
</script>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
</html>
<!-- end snippet -->
答案1
得分: 2
以下是您的代码中提到的问题的翻译:
- 无需在for循环内声明HTMLMarker函数。将其声明在循环外部,然后在循环内调用
new HTMLMarker(...)
和setMap()
函数。 - 我已经在create函数中添加了价格,因此您可以将其作为
this.price
引用,并在onAdd
函数中使用它。 - 同样适用于您正在创建的
div
。使用this.div = document.createElement('div');
,以便您可以在其他函数中引用它。 - 我使用了
overlayMouseTarget
,这似乎比overlayImage
更适合保存HTML标记。 - 在
draw()
函数中,设置this.div
的位置,而不是设置整个地图窗格的位置。 - 最后但并非最不重要的,您的
.arrow_box
元素需要position: absolute;
。
还有一些事情:
- 将
<script>
标签包含在<body>
元素内 - 在API调用
&callback=init
中将您的地图初始化函数init()
声明为回调,并使用defer
属性确保回调在浏览器完全解析DOM后执行 - 将
init()
函数声明为window
对象的属性 - 我修复了您的CSS,如果在框上有
overflow: hidden;
,箭头无法显示,您需要正确的top
和left
值 - 鉴于您的框设计,如果要箭头的尖端位于确切的坐标上,您需要将
draw()
函数中的this.div.style.top
值偏移35px,即this.div.style.top = (position.y - 35)
。 - 查看高级标记,但它仍处于预览(pre-GA)状态。
希望这些翻译对您有所帮助。如果您有其他问题或需要进一步的翻译,请随时提问。
英文:
There are several issues with your code.
- There is no need to declare the HTMLMarker functions within the for loop. Declare it outside and call the
new HTMLMarker(...)
andsetMap()
function within the loop. - I have added the price in the create function so you can refer to it as
this.price
and use it that way in theonAdd
function. - The same goes for the
div
you are creating. Usethis.div = document.createElement('div');
so you can refer to it in other functions. - I have used
overlayMouseTarget
which seems more appropriate thanoverlayImage
for holding HTML markers. - In the
draw()
function, set the position ofthis.div
instead of setting the position of the entire map pane. - Last but not least, your
.arrow_box
elements need to beposition: absolute;
A few more things:
- Include
<script>
tags within the<body>
element - Declare your map initialization function
init()
as a callback in the api call&callback=init
and usedefer
attribute to make sure the callback executes after the full DOM was parsed by the browser - Declare the
init()
function as a property of thewindow
object - I fixed your CSS, the arrows can't display if you have
overflow: hidden;
on the box and you need correcttop
andleft
values - Given your box design, you need to offset the top value by 35px
this.div.style.top = (position.y - 35)
in thedraw()
function if you want the tip of the arrow to be on the exact coordinates - Have a look at Advanced Markers but it is still in Preview (pre-GA)
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
function init() {
var locations = [
['500k', -33.890542, 151.274856, 1],
['1.3M', -33.923036, 151.259052, 2],
['2.3M', -34.028249, 151.157507, 3],
['750k', -33.800101, 151.287478, 4],
['200K', -33.950198, 151.259302, 5],
];
var map = new google.maps.Map(document.getElementById('mapdiv'), {
zoom: 10,
center: new google.maps.LatLng(-33.92, 151.25),
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
function HTMLMarker(lat, lng, price) {
this.price = price;
this.pos = new google.maps.LatLng(lat, lng);
}
HTMLMarker.prototype = new google.maps.OverlayView();
HTMLMarker.prototype.onRemove = function() {}
HTMLMarker.prototype.onAdd = function() {
this.div = document.createElement('div');
this.div.className = "arrow_box d-flex";
this.div.innerHTML = "<div class='m-auto'>SR " + this.price + "</div>";
var panes = this.getPanes();
panes.overlayMouseTarget.appendChild(this.div);
}
HTMLMarker.prototype.draw = function() {
var overlayProjection = this.getProjection();
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
this.div.style.left = position.x + 'px';
this.div.style.top = (position.y - 35) + 'px';
}
for (let i = 0; i < locations.length; i++) {
let htmlMarker = new HTMLMarker(locations[i][1], locations[i][2], locations[i][0]);
htmlMarker.setMap(map);
}
}
window.init = init;
<!-- language: lang-css -->
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#mapdiv {
height: 200px;
width: 100%;
}
.arrow_box {
position: absolute;
font-size: 10px;
width: 60px;
height: 20px;
background: blue;
border-radius: 10px;
margin: 10px -30px;
color: white;
cursor: pointer;
}
.arrow_box img {
min-width: 150px;
width: auto;
max-height: 100px;
height: auto;
border-radius: 5px;
}
.arrow_box:after {
top: 20px;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-color: rgba(136, 183, 213, 0);
border-top-color: blue;
border-width: 5px;
margin-left: -5px;
}
<!-- language: lang-html -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<div id="mapdiv"></div>
<!--
The `defer` attribute causes the callback to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises
with https://www.npmjs.com/package/@googlemaps/js-api-loader.
-->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=init" defer></script>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论