图形
地图引擎的图形和我们平时数学的几何还是有区别的:
- 数学几何里的图形只有形状
- 地图引擎里的图形不仅仅有形状还有样式
比如数学里关于线段的描述:只有长度没有大小的一段距离
但是在地图引擎里图形不仅仅要考虑线段的长度,还有考虑线段的粗细,透明度,是否是虚线等
所以这里的说的图形:图形=几何+样式
经常做GIS业务的同学应该都知道 turfjs,jsts,jts,postgis这些空间关系判断的库或者工具,他们都是纯的几何计算库
但是在地图引擎里这些关系的判断我们还需要考虑样式的,所以地图引擎里的图形的空间关系判断和事件交互等要考虑的东西可不仅仅几何的关系,还要把样式的东西考虑进来,引擎层面图形的交互上我们要把样式的一些特殊情况考虑进去的:
- 透明的地方不可交互
- 虚线的地方不可交互
- 点的交互要考虑不规则形状的图片,不仅仅是根据点的大小,和点图片里的路径有关,比如下面这图片,不仅要考虑图片的大小,还要考虑鼠标点是否在这个图片内部的图形路径上

为什么要解释这些? 当大家使用maptalks的过程遇到一些因为样式的特殊性的而不能交互的地方要理解我们为啥要这样设计,不要把你的纯的几何思维带进去来,比如你设置了一个面的填充色,然后发现图形不能点击了,就不要在那里想?鼠标点明明在面内为什么不能点击呢?,其实是我们故意而为之的
图形继承关系
![]()
图形,图层,地图三者关系
![]()
- 一个地图上可以多个图层
- 每个图层里有多个图形数据
一个图形只能被加到一个图层上
- 图形要素只能加到图层里,不能直接加到地图上
- 一个图形只能属于一个图层,不能被同时加入多个图层
- 即使将图形作为Mask使用也是的,只能被加到一个图层,如果想同一个图形加到不同的图层,需要
copy下
const polygons = maptalks.GeoJSON.toGeometry(geojson);
const mask1 = polygons[0];
const mask2 = mask1.copy();
layer1.setMask(mask1);
layer2.setMask(mask2);maptalks常用的图形
| 名字 | 描述 |
|---|---|
| Marker | 点 |
| LineString | 线 |
| Polygon | 面 |
| MultiPoint | 多点 |
| MultiLineString | 多线 |
| MultiPolygon | 多面 |
| Circle | 圆 |
| Rectangle | 矩形 |
![]()
![]()
![]()
![]()
图形的组成
maptalks里图形虽然有很多,但是他们的组成都是一样的,图形的组成有:
| 名字 | 描述 |
|---|---|
| Coordinates | 图形坐标 |
| options | 图形配置信息 |
| options.symbol | 图形样式 |
| options.properties | 图形属性,一般携带的是业务信息 |
const point = new Point(
[120, 31], //坐标信息
{
symbol: {
//样式
markerType: "ellipse",
},
properties: {
//属性
name: "hello",
},
draggable: true, //配置项
//其他配置信息
},
);
layer.addGeometry(point);图形常用的方法
| 方法 | 描述 |
|---|---|
| getLayer() | 获取图层 |
| getMap() | 获取地图 |
| config() | 修改图形的配置选项 |
| getProperties() | 获取属性信息 |
| setProperties(properties) | 设置属性信息 |
| getSymbol() | 获取样式 |
| setSymbol(symbol) | 设置样式 |
| updateSymbol(props) | 更新样式 |
| getCenter() | 获取中心点 |
| show() | 显示 |
| hide() | 隐藏 |
| isVisible() | 当前是否可见 |
| copy() | 克隆 |
| remove() | 从图层上移除 |
| startEdit(optionsopt) | 编辑 |
| setInfoWindow(options) | 设置信息框 |
| on() | 监听事件 |
| off() | 移除事件监听 |
| once() | 只监听一次事件 |
const point = new Point(
[120, 31], //坐标信息
{
symbol: {
//样式
markerType: "ellipse",
},
properties: {
//属性
name: "hello",
},
draggable: true, //配置项
},
);
layer.addGeometry(point);
point.getLayer();
point.getMap();
point.on("click", (e) => {});图形常用的事件
| 事件 | 描述 |
|---|---|
| mousedown | 鼠标点击下 |
| mouseup | 鼠标点击弹起 |
| mousemove | 鼠标移动 |
| click | 点击 |
| dblclick | 双击 |
| contextmenu | 鼠标右键 |
| mouseover | |
| mouseout | |
| show | 显示 |
| hide | 隐藏 |
| symbolchange | 样式改变 |
| editstart | 编辑开始 |
| editend | 编辑结束 |
| dragging | 拖拽ing |
| dragend | 拖拽结束 |
| dragstart | 拖拽开始 |
| handledragstart | 编辑顶点拖拽开始 |
| handledragging | 编辑顶点拖拽ing |
| handledragend | 编辑顶点拖拽结束 |
| handleremove | 编辑顶点移除 |
point.on("click mouseover mouseout", (e) => {});怎样修改图形的配置选项(options)
所有的图形都提供了config方法,直接调用这个方法即可
point.config({
draggable: true,
...
});TIP
在maptalks里,config方法在顶级父类Class上,这就意味着Map,所有的Layer,所有的Geometry都拥有这个方法
样式更新注意点
图形的样式支持对象或者数组,在更新时需要保证样式的数据结构不变,即:
- 如果样式一开始是
Object的,更新也只能是以Object的方式更新 - 如果样式一开始是
Array的方式,更新也只能是以Array的方式更新 - 若果想重置就
setSymbol来重置
const point = new Marker(
[120, 31], //坐标信息
{
symbol: {
//样式
markerType: "ellipse",
markerWidth: 10,
markerHeight: 10,
textName: "hello",
},
properties: {
//属性
name: "hello",
},
draggable: true, //配置项
},
);
point.updateSymbol({
markerWidth: 20,
markerHeight: 20,
});
const point1 = new Marker(
[120, 31], //坐标信息
{
symbol: [
//样式
{
markerType: "ellipse",
markerWidth: 10,
markerHeight: 10,
},
{
textName: "hello",
},
],
properties: {
//属性
name: "hello",
},
draggable: true, //配置项
},
);
//只更新顶一个样式项
point1.updateSymbol([
{
markerWidth: 20,
markerHeight: 20,
},
]);怎样缓存图形的样式
有时我们系统需要如下的地图效果,当鼠标进入某个图形时高亮这个图形,鼠标移出时还原成原来的样式,这时就需要一点小技巧来缓存图形高亮前的样式
方法也很简单:即当图形第一次高亮时记录下其样式,当鼠标移出改图形把其样式还原回来
function mouseEventFunc(e) {
const polygon = e.target;
if (e.type === "mouseover") {
if (!polygon._oldSymbol) {
polygon._oldSymbol = polygon.getSymbol();
}
polygon.setSymbol({
polygonFill: "red",
});
} else if (e.type === "mouseout") {
if (polygon._oldSymbol) {
polygon.setSymbol(polygon._oldSymbol);
}
}
}
fetch("./../assets/data/area.geojson")
.then((res) => res.json())
.then((geojson) => {
const polygons = maptalks.GeoJSON.toGeometry(geojson);
polygons.forEach((polygon) => {
polygon.setSymbol({
polygonFill: randomColor(),
polygonOpacity: 0.7,
});
polygon.on("mouseover mouseout", mouseEventFunc);
});
layer.addGeometry(polygons);
});怎样控制图形是否可以交互?
图形的配置项里有个参数interactive ,将其设置为false即可
const point = new Point(
[120, 31], //坐标信息
{
symbol: {
//样式
markerType: "ellipse",
markerWidth: 10,
markerHeight: 10,
textName: "hello",
},
properties: {
//属性
name: "hello",
},
interactive: false,
draggable: true, //配置项
},
);
//动态修改图形的配置项
point.config({ interactive: true });
point.config({ interactive: false });图形编辑
图形提供了startEdit,endEdit方法,
point.startEdit();
line.startEdit();
point.endEdit();
line.endEdit();- 线面编辑时为了性能考虑我们提供了编辑顶点碰撞功能
line.startEdit({
collision: true,
vertexZIndex: 2, //顶点层级
newVertexZIndex: 1, //线段间新建顶点层级控制
});![]()
- 另外当图形里具有海拔时我们也提供了支持
![]()
3D模型怎样拖拽
- 可以使用
maptalks-gl里自带的TransformControl控件
控制模型的平移、旋转、缩放例子
WARNING
注意TransformControl控件不支持three插件里的toModel的
- 使用第三方的模型控制插件 maptalks.modelcontrol
- 支持GLTFMarker
- 支持ThreeLayer的
toModel()
![]()