import { Scene, MarkerLayer, Marker, PointLayer, ILayer, Layers, LineLayer, PolygonLayer } from "@antv/l7"; import HPaaSL7 from "../../HPaaSL7"; import Overlay, { OverlayEventKeys } from "../Overlay"; import { AreaOverlayDataWithName, IAreaOverlayDataOption, IOverlayOptions } from "../overlay.types"; import { center, Feature, featureCollection, FeatureCollection, Polygon, simplify } from "@turf/turf"; import api from "../../../../http/api_road_network"; import Tooltips from "../Tooltips"; import ColorStops from "colorstops"; // 为所有此类管理的overlay计数,用来做zIndex的基础值,保证图层互相覆盖的规则。 let indexBase = 1; class AreaOverlay extends Overlay { private areaBorderLayer!: ILayer; private areaBgLayer!: ILayer; private markerLayer = new MarkerLayer({}); private areaList!: AreaOverlayDataWithName[]; private areaNameMarkers: Marker[] = []; private featureCollection!: FeatureCollection; tooltips!: Tooltips; constructor(hpaas: HPaaSL7, options: IOverlayOptions) { super(hpaas, options); this.tooltips = new Tooltips(hpaas, this.dataOption.key); if (!this.hpaas.sceneLoaded) { this.hpaas.l7Scene.on("loaded", () => { this.init(); }); return; } else { this.init(); } } init() { this.createOneLayer(); // this.dataOption.filters.forEach((f) => { // f.imgUrl && this.hpaas.scene.addImage(this.dataOption.key + f.name, f.imgUrl); // this.createOneLayer(f); // }); } createOneLayer() { // 拆分开 indexBase++; // 区域边界线 this.areaBorderLayer = new LineLayer({ zIndex: 81 + indexBase, }) .source(featureCollection([])) .style({ lineType: "dash", dashArray: [2, 2], }) .size(1) .shape("line") .color("#FF8A00") .style({ opacity: 2, cursor: "pointer", }); this.hpaas.l7Scene.addLayer(this.areaBorderLayer); // 区域边界线 this.areaBgLayer = new PolygonLayer({ zIndex: 80 + indexBase, enablePicking: true, enableHighlight: true, }) .source(featureCollection([]), {}) .color("color", (color) => { if (color) return color; return "#F65252"; }) .active({ color: "#fff9b0", }) .shape("fill") .style({ opacity: this.dataOption.colorOpacity || 1, cursor: "pointer", }); this.hpaas.l7Scene.addLayer(this.areaBgLayer); // 区域名称 // const center = center(turf); // const el = document.createElement("div"); // el.className = "map-area-name"; // el.textContent = this.areaModel.name?.toString() || null; // this.areaNameLayer = new Marker({ // element: el, // }).setLnglat({ // lng: center.geometry?.coordinates[0] || 0, // lat: center.geometry?.coordinates[1] || 0, // }); // const style = document.createElement("style"); // style.textContent = ` // .map-area-name { // font-size: 14px; // font-weight: 600; // background: ${theme.areaNameBgColor}; // box-sizing: border-box; // color: rgba(255, 255, 255, 0.8); // padding: 3px 10px; // border-radius: 20px; // } // `; // document.body.appendChild(style); // this.markerLayer.addMarker(this.areaNameLayer); this.hpaas.l7Scene.addMarkerLayer(this.markerLayer); // let lastFeatureId = -1; const templateResultCache: { [key: string]: any } = {}; this.areaBgLayer.on("mousemove", (e) => { if (e.feature && e.feature.properties.areaCode) { const tmp = this.dataOption.popupTemplate; if (tmp) { // requestAnimationFrame(() => { let html = ""; if (templateResultCache[e.feature.properties.areaCode]) { html = templateResultCache[e.feature.properties.areaCode]; } else { html = tmp(e.feature.properties); templateResultCache[e.feature.properties.areaCode] = html; } this.tooltips.moveTo(e.lngLat.lng, e.lngLat.lat).setHTML(html).show(); // }); } } else { this.tooltips.hide(); } }); this.areaBgLayer.on("click", (e) => { if (e.feature && e.feature.properties.areaCode) { this.emit(OverlayEventKeys.CLICK, e.feature.properties); } }); this.areaBgLayer.on("mouseout", (e) => { console.log("area mouseout"); // setTimeout(() => { // if (!mouseIsInTooltipOrPoint) { // console.log("hide tooltips"); // lastFeatureId = -1; this.emit(OverlayEventKeys.HIDE_TOOLTIP); this.tooltips.hide(); // } // }, 500); }); this.tooltips.ele.style.pointerEvents = "none"; } /** * 渲染散点图(聚合图) */ async renderData(areaList: AreaOverlayDataWithName[]) { if (!this.hpaas.sceneLoaded) { this.hpaas.l7Scene.on("loaded", () => { this.renderData(areaList); }); return; } this.areaList = areaList; const features: Feature[] = []; for (let i = 0; i < this.areaList.length; i++) { const p = this.areaList[i]; try { if (p.areaCode) { const areaInfo = (await api.area.queryAreaFromJsonByUid(p.areaCode)) as Feature; if (areaInfo) { let polygon = areaInfo; // p.color && polygon.properties && (polygon.properties.color = p.color); // p.name && polygon.properties && (polygon.properties.name = p.name); polygon.properties && Object.assign(polygon.properties, p); p.extends && polygon.properties && Object.assign(polygon.properties, p.extends); polygon = simplify(polygon, { tolerance: 0.002, highQuality: true, }); features.push(polygon); } } } catch (e) { console.log(e); } } // 设置属性到 properties 中 this.featureCollection = featureCollection(features); this.markerLayer.clear(); this.hpaas.l7Scene.removeMarkerLayer(this.markerLayer); this.markerLayer = new MarkerLayer(); this.areaNameMarkers = []; features.forEach((feature) => { const _center = center(feature); const el = document.createElement("div"); el.className = "map-area-name"; el.textContent = (feature.properties && feature.properties.name) || ""; Object.assign(el.style, { fontSize: "14px", fontWeight: 600, boxSizing: "border-box", color: "rgba(255, 255, 255, 0.8)", padding: "3px 10px", borderRadius: "20px", }); el.style.background = (feature.properties && feature.properties.color) || "#999"; const areaNameLayer = new Marker({ element: el, }).setLnglat({ lng: _center.geometry?.coordinates[0] || 0, lat: _center.geometry?.coordinates[1] || 0, }); this.markerLayer.addMarker(areaNameLayer); this.areaNameMarkers.push(areaNameLayer); }); this.hpaas.l7Scene.addMarkerLayer(this.markerLayer); if (this.dataOption.show) { this.show(); this.updateData(); } else { this.hide(); } } /** * 根据 value 过滤数据,并重新渲染 * @param value */ async filterDataByDataOption() { if (this.dataOption.show) { this.show(); this.updateData(); } else { this.hide(); } } updateData() { const checkedValues = this.dataOption.filters ?.filter((filter) => { return filter.checked; }) .map((filter) => { return filter.value; }); if (checkedValues && checkedValues.length) { const checkedFilterKey = checkedValues[0]; const values = this.featureCollection.features.map((f) => { return f.properties ? f.properties[checkedFilterKey as string] : 0; }); values.sort((r1, r2) => { return r1 - r2; }); const min = values[0]; const max = values[values.length - 1]; const colors: any = []; if (this.dataOption.colors) { const configColors = this.dataOption.colors; configColors.forEach((color, i) => { colors.push({ color: color, value: Math.floor(100 * ((i + 1) / configColors.length)), }); }); } const colorStops = new ColorStops(colors); this.areaBgLayer .color(checkedFilterKey as string, (...args: any) => { if (this.dataOption.colors) { const v = args[0]; const color = colorStops.hex(Math.floor((100 * (v - min)) / (max - min))); return color; } }) .setData(this.featureCollection); this.areaBorderLayer.setData(this.featureCollection); } } hide() { this.areaBgLayer.hide(); this.areaBorderLayer.hide(); this.tooltips.hide(); this.hpaas.l7Scene.removeMarkerLayer(this.markerLayer); } show() { this.areaBgLayer.show(); this.areaBorderLayer.show(); this.tooltips.show(); // this.markerLayer.addMarker(this.marker); this.areaNameMarkers.forEach((m) => { this.markerLayer.addMarker(m); }); this.hpaas.l7Scene.addMarkerLayer(this.markerLayer); } filterByFeature(features: Feature[]) {} } export default AreaOverlay;