import { deepMerge, getLevelMiddleHeight, wgs84ToGcj02Format, convertPosition, } 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: [], type: "color", radius: 20, color: "#ff0000", opacity: 1, waveCount: 2, waveSpeed: 5, outlineWidth: 0, outlineColor: "#ffffff", outlineOpacity: 1, outlineHighLight: false, outlineHighLightGlowPower: 0.1, outlineHighLightTaperPower: 1, scaleByDistance: true, distanceDisplayCondition: false, distanceDisplayCondition_far: 1, distanceDisplayCondition_near: 18, data: null, }; class mars3d_class extends Mars3dEntity { type: any = "circle"; 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.CircleEntity(this.config); } formatConfig(option: any) { const distanceDisplayCondition_far = getLevelMiddleHeight( option.distanceDisplayCondition_far ); const distanceDisplayCondition_near = getLevelMiddleHeight( option.distanceDisplayCondition_near ); let config: any = { id: option.id, position: new mars3d.LngLatPoint( option.position[0], option.position[1], option.position[2] || 0 ), style: { radius: option.radius || 1, color: option.color, opacity: option.opacity, outline: !!option.outlineWidth, 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[2], }, attr: option.data, }; switch (option.type) { case "color": config.style.materialType = mars3d.MaterialType.Color; break; case "wave": config.style.materialType = mars3d.MaterialType.CircleWave; config.style.materialOptions = { color: option.color, count: option.waveCount, speed: option.waveSpeed, }; break; } if (option.outlineHighLight) { config.style.outlineStyle = { materialType: "PolylineGlow", materialOptions: { color: option.outlineColor, glowPower: option.outlineHighLightGlowPower, taperPower: option.outlineHighLightTaperPower, }, }; } return config; } set(option: any) { deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.graphic.setOptions(this.config); } // flyTo(option = {}) { // let config = {} // if(option.height){ // config.scale = this.calculateScaleFromHeight(this.graphic, option.height) // } // // this.graphic.flyTo(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.Circle(this.config); } formatConfig(option: any) { let amapPosition = wgs84ToGcj02Format(option.position); return { center: new AMap.LngLat(amapPosition[0], amapPosition[1]), radius: option.radius, fillColor: option.color, fillOpacity: option.opacity, strokeColor: option.outline.color, strokeOpacity: option.outline.show ? option.outline.opacity : 0, strokeWeight: option.outline.show ? option.outline.width : 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.setCenter(this.config.center); } } class siji_class extends SijiEntity { type: any = "circle"; 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 SGMap.DrawCircleHandler(this.config); } formatConfig(option: any) { let config: any = { id: option.id, map: hnMap.map.map, // 允许编辑 enableEdit: false, // 允许调整圆心 canMove: false, // 设置非编辑状态下的图层颜色 // drawColor: option.outlineColor, // 设置编辑状态下的图层颜色 // editColor: "red", style: { // 设置非编辑状态下多边形面的样式 polygon: { "fill-color": option.color, // 填充颜色覆盖drawColor设置的颜色,呈现绿色 "fill-opacity": Number(option.opacity), "fill-outline-color": option.outlineColor, }, polyline: { "line-color": option.outlineColor, "line-opacity": Number(option.outlineOpacity), "line-width": Number(option.outlineWidth), }, }, // 编辑数据 featuresList: [], }; return config; } set(option: any) { deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.graphic.remove(); this.graphic.clearData(); this.graphic = new SGMap.DrawCircleHandler(this.config); let featureArr = { type: "Feature", properties: { centerPoint: convertPosition(this.option.position), radius: this.option.radius, }, geometry: { type: "Polygon", coordinates: [], }, }; this.graphic.addFeature(featureArr); } } class cesium_class extends CesiumEntity { type: any = "circle"; 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实体 this.graphic = new Cesium.Entity(this.config); } formatConfig(option: any) { const [lng, lat, height] = convertPosition(option.position); const config: any = { id: option.id, position: Cesium.Cartesian3.fromDegrees(lng, lat, height || 0), ellipse: { semiMinorAxis: option.radius || 1, semiMajorAxis: option.radius || 1, material: this.getMaterial(option), outline: !!option.outlineWidth, outlineColor: Cesium.Color.fromCssColorString( option.outlineColor ).withAlpha(Number(option.outlineOpacity) || 1), outlineWidth: option.outlineWidth, 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, height: Number(option.position[2]) || 0, extrudedHeight: 0, clampToGround: !option.position[2], }, properties: this.option.data || {}, // 添加自定义数据 }; return config; } getMaterial(option: any) { switch (option.type) { case "wave": return new Cesium.CircleWaveMaterial({ color: Cesium.Color.fromCssColorString(option.color), count: Number(option.waveCount), speed: Number(option.waveSpeed), gradient: 0.1, }); case "color": default: return new Cesium.ColorMaterialProperty( Cesium.Color.fromCssColorString(option.color).withAlpha( Number(option.opacity) ) ); } } set(option: any) { deepMerge(this.option, option); if (this.graphic && this.graphic.ellipse) { const config = this.formatConfig(this.option); // 更新位置 if (option.position) { const [lng, lat, height] = convertPosition(option.position); this.graphic.position = Cesium.Cartesian3.fromDegrees( lng, lat, height || 0 ); } // 更新半径 if (option.radius !== undefined) { this.graphic.ellipse.semiMinorAxis = option.radius; this.graphic.ellipse.semiMajorAxis = option.radius; } // 更新材质 if (option.type || option.color || option.opacity) { this.graphic.ellipse.material = this.getMaterial(this.option); } // 更新边框 if (option.outlineWidth !== undefined) { this.graphic.ellipse.outline = !!option.outlineWidth; this.graphic.ellipse.outlineWidth = Number(option.outlineWidth); this.graphic.ellipse.outlineColor = Cesium.Color.fromCssColorString( option.outlineColor ).withAlpha(Number(option.outlineOpacity) || 1); } if (option.distanceDisplayCondition) { this.graphic.ellipse.distanceDisplayCondition = new Cesium.DistanceDisplayCondition( getLevelMiddleHeight(option.distanceDisplayCondition_near), getLevelMiddleHeight(option.distanceDisplayCondition_far) ); } else { this.graphic.ellipse.distanceDisplayCondition = undefined; } if (option.scaleByDistance) { this.graphic.ellipse.scaleByDistance = new Cesium.NearFarScalar( 1.0e2, 1.0, 1.0e7, 0.1 ); } else { this.graphic.ellipse.scaleByDistance = undefined; } } } // 销毁实体 // 销毁方法 destroy() { if (this.graphic && hnMap.map.map && hnMap.map.map.entities) { hnMap.map.map.entities.remove(this.graphic); } } /** * 重写 flyTo 方法,针对圆形图形特殊处理 * @param option 飞行定位选项 */ flyTo(option: any = {}): void { console.log("开始飞行定位圆形图形...", this.graphic); if (this.graphic && this.hnMap && this.hnMap.map.map) { try { if (this.graphic.position) { const target = this.graphic.position.getValue( Cesium.JulianDate.now() ); if (target) { // 对于圆形图形,根据半径设置合适的高度以确保视野 const cartographic = Cesium.Cartographic.fromCartesian(target); // 根据圆形半径调整视距,确保圆形完整可见 const radius = this.option.radius || 100; const defaultHeight = option.height || Math.max(radius * 2, 500); const finalHeight = Math.max( cartographic.height + defaultHeight, defaultHeight ); const finalPosition = Cesium.Cartesian3.fromRadians( cartographic.longitude, cartographic.latitude, finalHeight ); this.hnMap.map.map.camera.flyTo({ destination: finalPosition, duration: option.duration || 2.0, orientation: { heading: Cesium.Math.toRadians(option.heading || 0), // 使用-90度俯仰角确保圆形位于视图中央 pitch: Cesium.Math.toRadians(option.pitch || -90), roll: Cesium.Math.toRadians(option.roll || 0), }, complete: option.complete, cancel: option.cancel, }); } } } catch (error) { console.error("圆形图形飞行定位失败:", error); } } } } const fn: any = { mars3d: mars3d_class, gaode: gaode_class, siji: siji_class, cesium: cesium_class, }; return fn[hnMap.mapType]; };