// @ts-check
/**
* 地图工具类,包含常用操作,不能把工具类的实例赋值给 vue 的响应性值
*/
class MapUtil {
/**
* MapUtil类实例化函数
* @param {object} maptalks - maptalks库的引用
* @param {object} domRef - 地图要挂载的dom引用
* @param {object} option - 地图配置
*/
constructor(maptalks, domRef, option = {}) {
if (!maptalks || !domRef) return;
this.maptalks = maptalks;
this.option = option;
this.mapIns = null;
this.drawTool = null;
this.init(domRef, option);
this.initDrawTool();
}
/**
* 初始化地图
* @param {object} domRef - 地图要挂载的dom引用
* @param {object} option - 地图配置
* @returns 地图实例
*/
init(domRef, option) {
return (this.mapIns = new this.maptalks.Map(domRef, option));
}
/**
* 添加图层
* @param {string} type - layer类型
* @param {string} id - layer id 唯一
* @param {...any} args - layer 需要的其它参数
* @returns layer实例
*/
addLayer(type, id, ...args) {
return (
this.mapIns.getLayer(id) ||
new this.maptalks[type](id, ...args).addTo(this.mapIns)
);
}
/**
* 设置图层显隐
* @param {string} id - 目标图层 id
* @param {boolean} isShow - 是否显示
*/
toggleLayer(id, isShow) {
if (id) {
this.mapIns.getLayer(id)[isShow ? "show" : "hide"]();
}
}
/**
* 添加 geometry
* @param {object[]} data - 要渲染的数据
* @param {function} optionCb - 数据 -> geometry配置 的函数(函数要返回一个数组,数组值的顺序是: geometry类型、生成geometry所需的参数(数组形式)、要监听的方法(可选))
* @param {string} targetLayer - 目标layer id
* @param {object} infoWindowRef - infoWindow的渲染函数或者单文件组件的引用(使用组件中的 infowindowOption,来设置 infowindow,传入 closeInfoWindow 函数来控制显隐)
* @returns {object[]} geometrys
*/
addGeometry(data, optionCb, targetLayer, infoWindowRef) {
if (!(data && optionCb)) {
throw "addGeometry 失败:缺少 data 或 optionCb";
}
const geometrys = data
.map((el) => optionCb(el))
.map(([type, args, callbacks = {}]) => {
const geometry = new this.maptalks[type](...args);
Object.entries(callbacks).forEach(([key, fn]) => geometry.on(key, fn));
if (infoWindowRef) {
const infoWindowIns = new this.maptalks.ui.InfoWindow({
custom: true,
}).addTo(geometry);
const infoWindowTempIns = MapUtil.prototype.createApp(infoWindowRef, {
...geometry.getProperties(),
closeInfoWindow: () => infoWindowIns.hide(),
});
infoWindowIns.setContent(infoWindowTempIns.$el);
infoWindowIns.config({
custom: true,
...(infoWindowTempIns.infowindowOption || {}),
});
}
return geometry;
});
if (targetLayer) {
this.mapIns.getLayer(targetLayer).addGeometry(geometrys);
}
return geometrys;
}
/**
* 添加 geometry 实例
* @param {object | object[]} geometryIns - geometry实例或实例数组
* @param {string} targetLayer - 目标layer id
*/
addGeometryIns(geometryIns, targetLayer) {
if (targetLayer) {
this.mapIns.getLayer(targetLayer).addGeometry(geometryIns);
}
}
/**
* 绘制
* @param {string} mode - 图形类型
* @param {object} symbolOption - drawTool.symbol 的配置参数
* @returns {promise} promise resolve 后返回绘制的 geometry 的相关信息
*/
draw(mode, symbolOption) {
return new Promise((resolve) => {
const _endCb = (params) => {
resolve(this.getGeometryInfo(params.geometry));
this.drawTool.disable();
// 绘制结束后,取消对 drawend 的监听,防止重复监听报错
this.drawTool.off("drawend", _endCb);
};
if (mode) {
this.drawTool.setMode(mode);
}
if (symbolOption) {
this.drawTool.setSymbol(symbolOption);
}
this.drawTool.on("drawend", _endCb);
this.drawTool.enable();
});
}
/**
* 销毁
*/
destroy() {
this.mapIns.getLayers().map((layer) => layer.clear());
this.mapIns.remove();
this.mapIns = null;
}
/**
* 获取 geometry 实例的相关信息
* @param {object} geometry - geometry 实例
* @returns {object} geometry 的相关信息,area 面积(平方千米),length 长度(千米)
*/
getGeometryInfo(geometry) {
if (!geometry) return null;
return {
type: geometry.getType(),
area: geometry.getArea() / 1000000,
length: geometry.getLength() / 1000,
center: this.maptalks.Coordinate.toNumberArrays(geometry.getCenter()),
property: geometry.getProperties(),
symbol: geometry.getSymbol(),
geoJsonGeometry: geometry.toGeoJSONGeometry(),
geoJson: geometry.toGeoJSON(),
json: geometry.toJSON(),
geometry: geometry,
};
}
/**
* 初始化 drawTool
* @param {object} symbol - symbol 配置
* @param {object} option - drawTool 配置
*/
initDrawTool(symbol = null, option = {}) {
const options = {
mode: "Polygon",
once: true,
...option,
};
if (symbol) {
options.symbol = symbol;
}
this.drawTool = new this.maptalks.DrawTool(options)
.addTo(this.mapIns)
.disable();
}
}
export default MapUtil;