import { deepMerge, wgs84ToGcj02Format, createRectangleCoordinates, getLevelMiddleHeight, } from "../util"; import Mars3dEntity from "../base/mars3d_entity"; import GaodeEntity from "../base/gaode_entity"; import SijiEntity from "../base/siji_entity"; import CesiumEntity from "../base/cesium_entity"; export default (hnMap: any) => { const defaultOption = { id: "", position: [], color: "#ff0000", opacity: 1, outline: false, outlineWidth: 2, outlineColor: "#ffffff", outlineOpacity: 1, scaleByDistance: true, distanceDisplayCondition: false, distanceDisplayCondition_far: 1, distanceDisplayCondition_near: 18, data: null, }; class mars3d_class extends Mars3dEntity { type: any = "retangle"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; graphic: any = null; constructor(option: any) { super(hnMap); this.id = option.id; deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.graphic = new mars3d.graphic.RectangleEntity(this.config); } formatConfig(option: any) { const distanceDisplayCondition_far = getLevelMiddleHeight( option.distanceDisplayCondition_far ); const distanceDisplayCondition_near = getLevelMiddleHeight( option.distanceDisplayCondition_near ); return { id: option.id, positions: option.position, style: { color: option.color, opacity: option.opacity, outline: option.outline, outlineColor: option.outlineColor, outlineWidth: option.outlineWidth, outlineOpacity: option.outlineOpacity, scaleByDistance: option.scaleByDistance, distanceDisplayCondition: option.distanceDisplayCondition, distanceDisplayCondition_far: distanceDisplayCondition_far, distanceDisplayCondition_near: distanceDisplayCondition_near, clampToGround: !(option.position[0] && option.position[0][2]), }, attr: option.data, }; } set(option: any) { deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.graphic.setOptions(this.config); } } class gaode_class extends GaodeEntity { id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; graphic: any = null; constructor(option: any) { super(hnMap); this.id = option.id; deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.graphic = new AMap.Rectangle(this.config); //创建矩形 } formatConfig(option: any) { const amapPosition = wgs84ToGcj02Format(option.position); //坐标转换 const southWest = new AMap.LngLat(amapPosition[0][0], amapPosition[0][1]); // const northEast = new AMap.LngLat(amapPosition[1][0], amapPosition[1][1]); // const bounds = new AMap.Bounds(southWest, northEast); // 创建矩形 return { bounds: bounds, fillColor: option.color, fillOpacity: option.opacity, strokeColor: option.outlineColor, strokeOpacity: option.outline ? option.outlineOpacity : 0, strokeWeight: option.outline ? option.outlineWidth : 0, extData: { id: option.id, data: option.data, }, }; } set(option: any) { deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.graphic.setOptions(this.config); this.graphic.setBounds(this.config.bounds); } } class siji_class extends SijiEntity { type: any = "rectangle"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; graphic: any = null; constructor(option: any) { super(hnMap); this.id = option.id; deepMerge(this.option, option); this.config = this.formatConfig(this.option); } formatConfig(option: any) { let RectanglePosition = createRectangleCoordinates( option.position[0], option.position[1] ); let config = { id: option.id, type: "fill", source: { type: "geojson", data: { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Polygon", coordinates: [RectanglePosition], }, }, ], }, }, paint: { "fill-color": option.color, // 填充颜色覆盖drawColor设置的颜色,呈现绿色 "fill-opacity": Number(option.opacity), "fill-antialias": true, "fill-outline-color": option.outlineColor, }, }; return config; } set(option: any) { deepMerge(this.option, option); this.config = this.formatConfig(this.option); let RectanglePosition = createRectangleCoordinates( option.position[0], option.position[1] ); let mySource = hnMap.map.map.getSource(this.config.id); mySource.setData({ type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Polygon", coordinates: [RectanglePosition], //三层数组[[0,0],[0,0]] }, }, ], }); for (let key in this.config) { if (this.config.hasOwnProperty(key)) { if (key == "paint") { for (let key2 in this.config[key]) { if (this.config[key].hasOwnProperty(key2)) { // 遍历 paint 属性 hnMap.map.map.setPaintProperty( this.config.id, key2, this.config[key][key2] ); } } } } } } } class cesium_class extends CesiumEntity { type: any = "rectangle"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; graphic: any = null; constructor(option: any) { super(hnMap); this.id = option.id; deepMerge(this.option, option); this.config = this.formatConfig(this.option); // 创建 Cesium Entity 使用 Polygon 模拟矩形 this.graphic = new Cesium.Entity(this.config); } formatConfig(option: any) { // 生成矩形四个角点(顺时针或逆时针,必须闭合) const corners = createRectangleCoordinates( option.position[0], option.position[1] ); // [[lng,lat], ...] // Cesium 要求坐标为 Cartesian3 const cartesianPositions = corners.map(([lng, lat]) => Cesium.Cartesian3.fromDegrees(lng, lat) ); // 填充区域(polygon) const fillColor = Cesium.Color.fromCssColorString(option.color).withAlpha( Number(option.opacity) ); // 外边框(polyline) const outlineColor = Cesium.Color.fromCssColorString( option.outlineColor ).withAlpha(Number(option.outlineOpacity)); return { id: option.id, polygon: { hierarchy: new Cesium.PolygonHierarchy(cartesianPositions), // 矩形四个角点 material: fillColor, height: 0, // 固定高度(贴地需 terrain + GroundPrimitive,此处简化) perPositionHeight: false, closeBottom: true, distanceDisplayCondition: option.distanceDisplayCondition ? new Cesium.DistanceDisplayCondition( getLevelMiddleHeight(option.distanceDisplayCondition_near), getLevelMiddleHeight(option.distanceDisplayCondition_far) ) : undefined, scaleByDistance: option.scaleByDistance ? new Cesium.NearFarScalar(1.0e2, 1.0, 1.0e7, 0.1) : undefined, }, polyline: option.outline ? { positions: [...cartesianPositions, cartesianPositions[0]], // 闭合线 width: Number(option.outlineWidth), material: outlineColor, clampToGround: false, // Cesium Polyline clampToGround 需开启 terrain 且有性能开销 distanceDisplayCondition: option.distanceDisplayCondition ? new Cesium.DistanceDisplayCondition( getLevelMiddleHeight(option.distanceDisplayCondition_near), getLevelMiddleHeight(option.distanceDisplayCondition_far) ) : undefined, scaleByDistance: option.scaleByDistance ? new Cesium.NearFarScalar(1.0e2, 1.0, 1.0e7, 0.1) : undefined, } : undefined, properties: option.data, }; } set(option: any) { deepMerge(this.option, option); const newConfig = this.formatConfig(this.option); // 生成矩形四个角点(顺时针或逆时针,必须闭合) const corners = createRectangleCoordinates( option.position[0], option.position[1] ); // [[lng,lat], ...] // Cesium 要求坐标为 Cartesian3 const cartesianPositions = corners.map(([lng, lat]) => Cesium.Cartesian3.fromDegrees(lng, lat) ); // 外边框(polyline) const outlineColor = Cesium.Color.fromCssColorString( option.outlineColor ).withAlpha(Number(option.outlineOpacity)); // 更新 polygon const polygon = this.graphic.polygon; if (polygon) { polygon.hierarchy = newConfig.polygon.hierarchy; polygon.material = newConfig.polygon.material; } // 更新或创建/移除 polyline(outline) if (option.outline) { if (!this.graphic.polyline) { this.graphic.polyline = new Cesium.PolylineGraphics(); } this.graphic.polyline.positions = [ ...cartesianPositions, cartesianPositions[0], ]; // 闭合线; this.graphic.polyline.width = Number(option.outlineWidth); this.graphic.polyline.material = outlineColor; } else { this.graphic.polyline = undefined; // 移除外边框 } if (option.distanceDisplayCondition) { this.graphic.polygon.distanceDisplayCondition = new Cesium.DistanceDisplayCondition( getLevelMiddleHeight(option.distanceDisplayCondition_near), getLevelMiddleHeight(option.distanceDisplayCondition_far) ); this.graphic.polyline.distanceDisplayCondition = new Cesium.DistanceDisplayCondition( getLevelMiddleHeight(option.distanceDisplayCondition_near), getLevelMiddleHeight(option.distanceDisplayCondition_far) ); } else { this.graphic.polygon.distanceDisplayCondition = undefined; this.graphic.polyline.distanceDisplayCondition = undefined; } if (option.scaleByDistance) { this.graphic.polygon.scaleByDistance = new Cesium.NearFarScalar( 1.0e2, 1.0, 1.0e7, 0.1 ); this.graphic.polyline.scaleByDistance = new Cesium.NearFarScalar( 1.0e2, 1.0, 1.0e7, 0.1 ); } else { this.graphic.polygon.scaleByDistance = undefined; this.graphic.polyline.scaleByDistance = undefined; } // 更新属性数据 this.graphic.properties = newConfig.properties; } destroy() { if (this.graphic && hnMap.map.map.entities) { hnMap.map.map.entities.remove(this.graphic); } } } const fn: any = { mars3d: mars3d_class, gaode: gaode_class, siji: siji_class, cesium: cesium_class, }; return fn[hnMap.mapType]; };