UI
地图引擎里的数据要素不仅仅有图形,有时我们还要在地图上加些UI元素,像弹窗,气泡等
在maptalks里关于domui方面主要提供了ui
和control
两个命名空间,关于他们的区别:
- control下的类,他们的位置是不随着地图视角的改变而改变的,他们的位置是死的,例如比例尺,指北针啊等
- ui和control正好相反,他们的位置是随着地图视角的改变而改变的,他们的位置会跟随地图,例如弹窗,UIMarker等
WARNING
地图上的UI他们的位置都是随着地图的视角改变而改变的
如果你的UI元素不需要随着地图视角改变而改变其位置,那么你不应该使用地图的UI模块,应该直接使用原生的DOM
例如下面的视频演示的DOM,他的位置是死的
InfoWindow和UIMarker怎样选择
InfoWindow和UIMarker都是在地图上展示UIDOM,但是他们还是有些区别的
- InfoWindow 一般是随着图形(Geometry)来展示,其一般作为图形的附属信息展示的
- UIMarker 是独立展示的,不需要成为 Geometry的附属者
- InfoWindow的展示位置是固定的,一般都是放在Geometry的上面
- UIMarker的位置就比较灵活了,可以随意放到四周,可以Geometry一起组成一些特殊的效果
你可以把该UIMarker随意的放到Geomtry的四周,UIMarker提供了对齐功能 UIMarker Align Demo
如果UI/UX设计师喜欢设计这种奇奇怪怪的效果就特别适合 UIMarker
Marker和UIMarker怎样选择?
Marker是纯图片渲染,采用canvas或者webgl等渲染技术,而UIMarker是纯的DOM,所以:
- 纯图片的用Marker
- 需要在地图展示表格,图表,表单,各种CSS效果,交互等的元素就采用UIMarker
地图展示的UI东西有点多乱糟糟的怎么办?
maptalks的UI已经内置碰撞了功能,开启碰撞即可 ui-collision demo
UI要素支持海拔高度吗?
支持的,不管是UIMarker
还是InfoWindow
都是支持的
const layer = new maptalks.VectorLayer("layer", {
enableAltitude: true,
}).addTo(map);
const center = map.getCenter();
//海拔
center.z = 100;
const point = new maptalks.Marker(center).addTo(layer);
point.setInfoWindow({
content: "hello",
});
//显示时会自动那point的坐标作为显示的点,也可以手动传入坐标的值
//openInfoWindow(coordinate)
point.openInfoWindow();
let c2 = center.copy();
c2.x += 0.01;
const marker = new maptalks.ui.UIMarker(c2, {
content: '<div class="text-marker">maptalks</div>',
verticalAlignment: "top",
}).addTo(map);
3D模型绑定InfoWindow自动读取模型的高度值
const layer = new maptalks.GLTFLayer("layer");
const groupLayer = new maptalks.GroupGLLayer("group", [layer]).addTo(map);
const center = map.getCenter().toArray();
const point = new maptalks.GLTFMarker(center, {
symbol: {
url: "./../assets/data/alien.gltf",
modelHeight: 50, //model height,Unit is meters
scaleX: 1,
scaleY: 1,
scaleZ: 1,
rotationZ: 180,
},
});
point.addTo(layer);
point.setInfoWindow({
content: "hello I am a gltfmarker",
});
UI的内容只支持字符串吗?
UI的内容content
不仅仅支持字符串的,也是支持dom
节点的
原生的dom
const center = map.getCenter().toArray();
const point = new maptalks.Marker(center, {
symbol: {
markerType: "ellipse",
markerWidth: 40,
markerHeight: 40,
markerFill: "#fff",
},
});
point.addTo(layer);
point.setInfoWindow({
content: document.getElementById("infowindow"),
});
支持Vue/React等组件
只需要把Vue/React等组件挂载的dom节点传递给content
即可
randomCoordinates().map((c, index) => {
var Profile = Vue.extend({
template: `<div class="profile"> <el-button size="mini">默认按钮</el-button>
<el-button size="mini" type="danger">危险按钮</el-button>
<el-checkbox v-model="checked">备选项</el-checkbox>
<p>{{firstName}} {{lastName}} aka {{alias}}</p></div>`,
data: function () {
return {
firstName: "Walter" + index,
lastName: "White",
alias: "Heisenberg",
checked: index % 2 === 0,
};
},
});
const profile = new Profile().$mount();
console.log(profile);
var uiMarker = new maptalks.ui.UIMarker(c, {
content: profile.$el,
verticalAlignment: "top",
// eventsPropagation: false
});
uiMarker.addTo(map);
});
设置UI的层级
ui创建时有个参数zIndex
,就是css里的zIndex,自己设置合适的值即可
var uiMarker = new maptalks.ui.UIMarker(c, {
content: profile.$el,
verticalAlignment: "top",
zIndex: 2,
// eventsPropagation: false
});
注意事项
ui是纯dom,因为dom的性能问题,所以地图上不适合有大量的UI节点,否则性能很差
UIMarker默认是中心点对齐的,默认在地图上会比较大的视觉误差,导致其所在的位置和我们期望的不一样,尤其是将地图缩小时视觉误差更大,你可以把UIMarker的verticalAlignment设为top,让UIMarker垂直对齐方式为
top
来解决视觉误差的问题 关于UIMarker对齐方式的例子maptalks里UI里的dom容器是maptalks自动生成的,所以要想关闭UI,请调用UI的
hide
或者remove
方法,用户传入的dom只是UI的内容而已, 内容作为dom容器的子节点了,所以仅仅对你传入的dom节点进行隐藏等是不能关闭UI元素的
point.closeInfoWindow();
//or
point.removeInfoWindow();
//or
point.getInfoWindow().hide();
//or
infowindow.hide();