常见问题
InfoWindow点击图形后自动弹出
InfoWindow默认是和图形的点击事件绑定的,如果你不想自动弹窗可以把关联的事件写成null
, 然后根据自己的需求自动打开
js
const marker = new maptalks.Marker([-0.113049, 51.49856]).addTo(layer);
marker.setInfoWindow({
title: "Marker's InfoWindow",
content: "Click on marker to open.",
autoOpenOn: null,
// 'autoPan': true,
// 'width': 300,
// 'minHeight': 120,
// 'custom': false,
//'autoOpenOn' : 'click', //set to null if not to open when clicking on marker
//'autoCloseOn' : 'click'
});
marker.on("click", (e) => {
setTimeout(
() => {
//do some things
e.target.openInfoWindow();
},
1000 * Math.random() + 500,
);
});
怎样异步更新InfoWindow的内容
还是正常的绑定InfoWindow,在图形的点击事件里我们来动态请求图形的信息,然后把信息更新到InfoWindow即可
js
const marker = new maptalks.Marker([-0.113049, 51.49856]).addTo(layer);
marker.setInfoWindow({
title: "Marker's InfoWindow",
content: "Click on marker to open.",
// 'autoPan': true,
// 'width': 300,
// 'minHeight': 120,
// 'custom': false,
//'autoOpenOn' : 'click', //set to null if not to open when clicking on marker
//'autoCloseOn' : 'click'
});
marker.on("click", (e) => {
const infoWindow = e.target.getInfoWindow();
infoWindow.setTitle("数据加载中....");
infoWindow.setContent(defaultContent);
//mock data fetch
setTimeout(
() => {
infoWindow.setTitle("《滕王阁序》");
infoWindow.setContent(
document.getElementById("infowindow").outerHTML,
);
},
500 + Math.random() * 1000,
);
});
InfoWindow多例
InfoWindow 选项里有个single
参数,默认是true,即单例,配置成false即可
js
point.setInfoWindow({
// collision: true,
single: false,
content: `point${index + 1}`,
});
怎样批量管理UIMarker集合
maptalks里关于UI元素没有提供批量管理UIMarker的能力,why?
- maptalks 里图层都是canvas/webgl渲染图层
- UIMarker比较特殊,其是html渲染的,一般用来渲染一些特殊的东西,图表,表格,css动画等
- 因为是html渲染所以无法和其他的图层位置三维深度关系
UI元素的操作一般是:
js
uiMarker.addTo(map);
uiMarker.remove();
如果你的业务里有这种批量和分类管理的需求,你可以自己抽象个UIMarker的图层管理工具, 下面是我写的一个简单的UIMarker管理图层类
WARNING
代码仅供参考,自己可以根据自己的需求做对应的修改,这里主要是模拟图层功能,以此来达到图形管理图层同样的API和使用习惯
js
class UIMarkerLayer {
constructor() {
this.markers = [];
this.map = null;
this.zIndex = null;
this.maxZoom = null;
this.minZoom = null;
this.opacity = 1;
}
_checkMarkers() {
if (!this.map) {
return this;
}
this.markers.forEach((marker) => {
if (!marker.getMap) {
return;
}
if (!marker.getMap()) {
marker.addTo(this.map);
}
});
return this;
}
_removeMarkers(markers) {
markers.forEach((marker) => {
if (this.markers.indexOf(marker) > -1) {
marker.remove();
}
});
return this;
}
getMap() {
return this.map;
}
addTo(map) {
if (this.map) {
console.warn("has add to map");
return this;
}
this.map = map;
this._checkMarkers();
return this;
}
remove() {
this._removeMarkers(this.markers);
this.map = null;
return this;
}
clear() {
this._removeMarkers(this.markers);
this.markers = [];
return this;
}
show() {
this.markers.forEach((marker) => {
marker.options.visible = true;
});
return this;
}
hide() {
this.markers.forEach((marker) => {
marker.options.visible = false;
});
return this;
}
_markersArrayJudge(markers) {
markers = Array.isArray(markers) ? markers : [markers];
return markers.filter((marker) => {
return !!(marker && marker.getMap);
});
}
addMarker(markers) {
markers = this._markersArrayJudge(markers);
markers.forEach((marker) => {
if (this.markers.indexOf(marker) === -1) {
this.markers.push(marker);
}
});
this._checkMarkers();
return this;
}
removeMarker(markers) {
markers = this._markersArrayJudge(markers);
this._removeMarkers(markers);
this.markers = this.markers.filter((marker) => {
return markers.indexOf(marker) === -1;
});
return this;
}
getMarkers() {
return this.markers.map((marker) => {
return marker;
});
}
setZIndex(zIndex) {
if (!maptalks.Util.isNumber(zIndex)) {
return this;
}
this.markers.forEach((marker) => {
marker.setZIndex(zIndex);
});
this.zIndex = zIndex;
return this;
}
getZIndex() {
return this.zIndex;
}
setMinZoom(minZoom) {
if (!maptalks.Util.isNumber(minZoom)) {
return this;
}
this.markers.forEach((marker) => {
marker.options.minZoom = minZoom;
});
this.minZoom = minZoom;
return this;
}
getMinZoom() {
return this.minZoom;
}
setMaxZoom(maxZoom) {
if (!maptalks.Util.isNumber(maxZoom)) {
return this;
}
this.markers.forEach((marker) => {
marker.options.maxZoom = maxZoom;
});
this.maxZoom = maxZoom;
return this;
}
getMaxZoom() {
return this.maxZoom;
}
setOpacity(opacity) {
if (!maptalks.Util.isNumber(opacity)) {
return this;
}
opacity = Math.min(1, opacity);
opacity = Math.max(0, opacity);
this.markers.forEach((marker) => {
const dom = marker.getDOM();
if (dom) {
dom.style.opacity = opacity;
}
});
this.opacity = opacity;
return this;
}
getOpacity() {
return this.opacity;
}
}
js
const layer = new UIMarkerLayer().addTo(map);
const coordinates = [
[119.26945017383241, 30.376871910976178],
[119.41899273004572, 30.377746042120833],
[119.51608471650138, 30.37726503747328],
[119.46354801648795, 30.31694687527127],
[119.60562937352347, 30.37820924055947],
[119.59045825643739, 30.430436461050107],
[119.584406756833, 30.487931288984754],
[119.51453485707066, 30.49039516064832],
[119.45440953161744, 30.48646614394201],
[119.69247157405653, 30.486815730590678],
[119.80953084691987, 30.472457196921],
[119.89535951684763, 30.47496435491533],
[119.84708685095575, 30.36586547405281],
[119.67054883716764, 30.303609976340255],
[119.65234867735501, 30.363784873871822],
[119.54423459602981, 30.480024325865287],
[119.47395594040563, 30.56338903320065],
[119.39707374359091, 30.53546677150925],
[119.57396685725621, 30.574315977713553],
[119.6401686202828, 30.569305689523247],
];
const markers = coordinates.map((c, index) => {
return new maptalks.ui.UIMarker(c, {
content: `<div class="marker">${index}</div>`,
});
});
const markers1 = markers.slice(0, 5);
const markers2 = markers.slice(5, Infinity);
layer.addMarker(markers1);
UI Content 传参Dom报错
这种一般都是content的内容不和合法的HTMLElement
导致的,比如可能是null,Array等
WARNING
注意在Vue
里的v-for
里ref
拿到的dom节点是个数组,直接给content
参数就会报这种错误
html
<div v-for="item in list">
<div :ref="'infowindow_content'+item.name">
<h2>{{name}}</h2>
<input type="text" v-model="name" />
<h4>count:{{count}}</h4>
<button @click="add">count++</button><br /><br />
<button v-for="item in btns">{{item}}</button>
</div>
</div>
js
marker.setInfoWindow({
// custom: true,
content: this.$refs["infowindow_content1"],
});
marker.openInfoWindow();
所以业务里请做好对应的判断
UI内容元素不能滚动
UI元素比较特殊,其是随着地图的位置改变要改变其自己自身的位置的,所以要对其的事件 系统进行事件的冒泡的控制的,即缩放操作用于这个这个UI本身时也要冒泡到地图容器上,所以导致了 UI元素内容的滚动失效
maptalks里的UI元素有:
- UIMarker
- InfoWindow
- Menu
InfoWindow和Menu都是默认禁用冒泡的,所以当其出现滚动时,其是可以滚动的, 但是UIMarker我们是当成Marker来看待和处理,默认是冒泡的,如果你想要其内容可以滚动, 你可以关闭冒泡
js
var uiMarker = new maptalks.ui.UIMarker(c, {
content: profile.$el,
verticalAlignment: "top",
zIndex: 2,
eventsPropagation: false,
});
WARNING
注意关闭冒泡后,UIMarker上的所有操作将不能作用到地图上了,所以业务里根据的需要配置合适的值