第九节:绘制和测距工具接入
上一节中我们实现了自定义地图工具来做任意点预报,这一节我们将直接使用QE内置的地图工具,所以会更简单一些!
添加区域绘制功能
在本示例中,我们计划添加的是区域绘制功能,这是一个纯粹为了演示而演示的功能,但是业务系统的复杂功能往往是由这些小的功能组成。
功能分析
我们希望这个区域绘制具有如下功能:
- 能够独立设置每次绘制的颜色
- 能够将绘制好的图形持久化的保存在一个固定图层中,单独控制显示和隐藏
创建绘制工具
为了实现上面的功能,我们将创建绘制工具的方法抽为一个独立的方法_createDrawTool
,然后在切换地图工具的方法中调用:
public switchTool(value: string) {
...
let mapTool: IMapTool;
if (value === "forecast") {
mapTool = new PointForecastMapTool();
} else if (value === "draw_poly") {
mapTool = this._createDrawTool();
} else if (value === "distance") {
} else {
message.warn("未能获取到对应的地图工具!");
return;
}
map.toolService.setCurrent(mapTool ?? null);
}
private _createDrawTool() {
return undefined;
}
接下来我们使用QE内置的LVectorMapTool
作为绘制工具,这是一个功能丰富的绘制工具,可以绘制数十种图形,而且支持扩展,目前我们用来绘制曲线多边形,只要简单的创建并且返回即可:
private _createDrawTool() {
const mapTool = new LVectorMapTool({ drawType: PlotTypes.CLOSED_CURVE, autoClear: true, continious: true });
return mapTool;
}
如果我们不需要实现用户自定义绘制的颜色,那么只要autoClear为false,就可以实现绘制图层不消失,除非手动调用clear方法。
此时点击区域绘制按钮,我们就可以在地图上绘制多边形了:
单独存储绘制内容,重设图形颜色
虽然绘制的时候我们都使用了同一种颜色,但是我们希望在绘制结束后保存的图形能够显示不同的颜色,在这里我们在外部定义一个独立的图层interactionLayer
,并且把这个图层的数据源也单独保存为interactionDataSource
,为了实现不同的颜色,使用一个interactionLayerColors
来保存每次绘制图形后所定义的颜色。
定义代码如下:
const interactionLayerColors: { [key: string]: string | Spectra } = {};
const interactionLayerStyle: IFeatureStyleOptions = {
polygon: {
fill: true,
color: (feature) => {
return interactionLayerColors[feature.id] ?? "rgba(255,0,0,0.6)"
}
}
}
let interactionDataSource: GeoJSONFeatureProvider;
const interactionLayer = new LGeoJSONLayer({ pane: consts.customPanes.topmap.name }).setDrawOptions(interactionLayerStyle);
之所以在外部保存这个图层,是为了方便后面在菜单里面能够直接显示和隐藏这个图层,实际应用中可以使用图层id来直接从map中获取这个图层,这里只是为了方便才定义在外部。为了方便的实现每个对象独立定义颜色,绘制的color值使用函数从缓存的颜色map中获取用户定义的颜色,如果获取不到则使用默认颜色。
要实现绘制完成的图层存储的步骤如下:
- 监听图元绘制完成的消息
- 每次绘制完成后,调用绘制工具的
getGeoJSON
方法来获取当前有效的绘制结果 - 获取绘制图元的id,如果不存在则创建
- 要求用户输入一个颜色,如果不输入,则使用默认颜色
- 将id作为key,颜色作为value存储到
interactionLayerColors
中 - 将绘制结果更新到图层数据源中
- 重绘图层
- 清空绘制的缓存
实现代码如下:
mapTool.on(LVectorMapTool.EventTypes.drawFinish, args => {
const dataSource: GeoJSON.FeatureCollection<GeoJSON.Polygon> = mapTool.getGeoJSON() as any;
const feature = dataSource.features[0];
const color = prompt("请填入颜色,支持css颜色,若使用默认颜色直接点击确定");
if (color) {
feature.id = feature.id ?? uid();
const sColor = new Spectra(color);
if (sColor.alpha() === 1) {
sColor.alpha(0.6);
}
interactionLayerColors[feature.id] = sColor;
}
if (!interactionDataSource) {
interactionDataSource = new GeoJSONFeatureProvider(dataSource);
interactionLayer.setDataSource(interactionDataSource);
} else {
interactionDataSource.addFeature(feature);
interactionLayer.redraw();
}
mapTool.clear();
});
这时候我们绘制完发现图层被清空了,并没有加到地图上,这是因为我们的交互图层还没有添加到地图,我们可以直接在创建的地方加到地图上,但是这样就会一直在地图上,我们选择另一种方式,将交互图层设置为图层菜单,可以由用户控制是否显示,我们在图层管理器的菜单配置中加入如下配置:
{
name: "交互图层",
id: "interaction",
userData: {
overlay: true
}
},
然后还要在创建图层的地方返回这个交互图层,这样才能将交互图层接入我们的业务逻辑:
public async createLayer(item: IMenuItem): Promise<boolean> {
...
if (item.id === "realtime_metar") {
layer = await this._createMetarLayer();
} else if (item.id === "realtime_sate") {
layer = this._createCloudLayer();
} else if (item.id.startsWith("gfs")) {
layer = await this._createGFSLayer(item.userData.dataInfo);
} else if (item.id === "flight") {
layer = await this._createFlightLayer();
} else if (item.id === "interaction") {
layer = interactionLayer;
}
...
}
接着设置这个图层是默认加载到地图的:
public defaultSelectedItemIds = ["interaction", "realtime_metar", "flight"];
现在,点击绘制按钮,可以不断的绘制新的图形,而且可以支持很多不一样的颜色:
我们的绘制工具接入完成!
实现测距
QE内置了一个测距的地图工具LDistanceMapTool
,只要直接使用即可,将切换地图工具的函数更新如下:
public switchTool(value: string) {
if (!defined(value) || value === "pan") {
map.toolService.getCurrent()?.clear();
map.toolService.setCurrent(null);
return;
}
let mapTool: IMapTool;
if (value === "forecast") {
mapTool = new PointForecastMapTool();
} else if (value === "draw_poly") {
if (!interactionLayer["_visible"]) {
message.warn("当前交互图层被隐藏,绘制后将无法看!");
}
mapTool = this._createDrawTool();
} else if (value === "distance") {
mapTool = new LDistanceMapTool();
} else {
message.warn("未能获取到对应的地图工具!");
return;
}
map.toolService.setCurrent(mapTool ?? null);
}
如果您觉得不够好用,也可以按照我们上一节自定义工具中的介绍,自己定义一个测距工具!
总结
越看到最后会发现QE的使用很简单,更多的是对业务逻辑的把握,业务梳理清楚后,再有QE的加持,一个应用系统很快就能搭建出来!
No Comments