import * as KMap from "@/utils/ol-map/KMap"; import config from "@/api/config"; import { wktCastGeom, newAreaFeature } from "@/common/ol_common"; import { unByKey } from "ol/Observable"; import Feature from "ol/Feature"; import { Point } from "ol/geom"; import Style from "ol/style/Style"; import Icon from "ol/style/Icon"; import mapPointImg from "@/assets/page/map-point.png"; /** 与 workDetail/areaMap 默认中心一致 */ const DEFAULT_LOCATION = "POINT(113.61448114737868 23.585550924763083)"; /** * 存放点位选择地图 * - 展示蓝区范围(不可点选) * - 地图中心默认点位图标,点击地图移动点位 */ export default class LocationSelectMap { constructor() { const vectorStyle = new KMap.VectorStyle(); this.vectorStyle = vectorStyle; this.kmap = null; this.clickKey = null; this.pointFeature = null; this.blueRegionLayer = new KMap.VectorLayer("blueRegionLayer", 99999, { minZoom: 1, maxZoom: 22, style: () => vectorStyle.getPolygonStyle( "rgba(0, 0, 0, 0.45)", "rgba(255, 212, 137, 0.85)", 1.5 ), }); this.pointLayer = new KMap.VectorLayer("locationPointLayer", 100000, { minZoom: 1, maxZoom: 22, style: new Style({ image: new Icon({ src: mapPointImg, scale: 0.55, anchor: [0.5, 1], anchorXUnits: "fraction", anchorYUnits: "fraction", }), }), }); } /** * @param {HTMLElement} target * @param {string} location WKT,优先用于点位初始位置 */ init(target, location = DEFAULT_LOCATION) { this.destroy(); const level = 16; const coordinate = wktCastGeom(location).getFirstCoordinate(); this.kmap = new KMap.Map( target, level, coordinate[0], coordinate[1], null, 1, 22, "vec", true, true ); this.kmap.addLayer(this.blueRegionLayer.layer); this.kmap.addLayer(this.pointLayer.layer); const xyz = config.base_img_url + "map/lby/{z}/{x}/{y}.png"; this.kmap.addXYZLayer(xyz, { minZoom: 8, maxZoom: 22 }, 2); // 点位等区域加载并 fit 完成后再放置,避免闪一下 this.addMapSingleClick(); setTimeout(() => this.updateSize(), 80); } addMapSingleClick() { this.clickKey = this.kmap.on("singleclick", (evt) => { this.setPoint(evt.coordinate); }); } /** @param {[number, number]} coordinate [lng, lat] */ setPoint(coordinate) { if (!this.pointLayer?.source || !coordinate) return; if (this.pointFeature) { this.pointFeature.getGeometry().setCoordinates(coordinate); return; } this.pointFeature = new Feature({ geometry: new Point(coordinate), }); this.pointFeature.set("nodeType", "location"); this.pointLayer.addFeature(this.pointFeature); } /** * 仅展示蓝区,不可点击选择 * @param {Array} list */ setRegions(list = []) { if (!this.blueRegionLayer?.source) return; this.blueRegionLayer.source.clear(); for (const item of list) { const wkt = item.geom || item.wkt; if (!wkt) continue; const id = item.blueZoneCode ?? item.id; const feature = newAreaFeature({ ...item, geom: wkt, id, name: item.name || item.regionName || item.blueZoneName || String(id), }); this.blueRegionLayer.addFeature(feature); } this.fitToRegions(); } fitToRegions() { const extent = this.blueRegionLayer?.source?.getExtent?.(); if (!extent || !isFinite(extent[0]) || !this.kmap) return; // 无动画,避免 fit 过程中点位位置错乱 this.kmap.fit(extent, { padding: [40, 40, 40, 40], duration: 0, maxZoom: 18 }); } /** 将点位放到当前地图中心 */ setPointToCenter() { const center = this.kmap?.view?.getCenter?.(); if (center) this.setPoint(center); } getPoint() { if (!this.pointFeature) return null; const [lng, lat] = this.pointFeature.getGeometry().getCoordinates(); return { lng, lat, wkt: `POINT(${lng} ${lat})`, label: `POINT(${Number(lng).toFixed(6)} ${Number(lat).toFixed(6)})`, }; } updateSize() { this.kmap?.updateSize?.() || this.kmap?.map?.updateSize?.(); } destroy() { if (this.clickKey) { unByKey(this.clickKey); this.clickKey = null; } this.blueRegionLayer?.source?.clear?.(); this.pointLayer?.source?.clear?.(); this.pointFeature = null; this.kmap?.destroy?.(); this.kmap = null; } }