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: "line", color: "#ffffff", width: 2, opacity: 1, outline: false, outlineColor: "#ffffff", outlineWidth: 2, dashColor: "#00ff00", dashLength: 16, image: "", repeat: [1, 1], // 闪烁线重复次数 speed: 5, // 闪烁线速度 scaleByDistance: true, distanceDisplayCondition: false, distanceDisplayCondition_far: 1, distanceDisplayCondition_near: 18, data: null, combine: false, instances: [], }; class mars3d_class extends Mars3dEntity { type: any = "line"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; graphic: any = null; constructor(option: any) { // debugger super(hnMap); this.id = option.id; deepMerge(this.option, option); this.config = this.formatConfig(this.option); if (option.combine) { this.graphic = new mars3d.graphic.PolylineCombine(this.config); } else { this.graphic = new mars3d.graphic.PolylineEntity(this.config); } } formatConfig(option: any) { let config: any = {}; const distanceDisplayCondition_far = getLevelMiddleHeight( option.distanceDisplayCondition_far ); const distanceDisplayCondition_near = getLevelMiddleHeight( option.distanceDisplayCondition_near ); if (option.combine) { config = { id: option.id, combine: true, instances: option.instances.map((item: any) => { let itemOption = JSON.parse(JSON.stringify(defaultOption)); deepMerge(itemOption, item); return this.formatConfig(itemOption); }), }; } else { config = { id: option.id, positions: option.position, style: { materialType: "Color", color: option.color, width: option.width, opacity: option.opacity, outline: option.outline, outlineColor: option.outlineColor, outlineWidth: option.outlineWidth, clampToGround: !(option.position[0] && option.position[0][2]), scaleByDistance: option.scaleByDistance, // 缩放 distanceDisplayCondition: option.distanceDisplayCondition, distanceDisplayCondition_far: distanceDisplayCondition_far, distanceDisplayCondition_near: distanceDisplayCondition_near, }, attr: option.data, }; switch (option.type) { case "line": config.style.materialType = "Color"; break; case "dash": config.style.materialType = "PolylineDash"; config.style.materialOptions = { color: option.color, gapColor: option.dashColor, dashPattern: option.dashPattern, }; break; case "flicker": config.style.materialType = "LineFlicker"; config.style.materialOptions = { color: option.color, speed: option.speed, }; break; case "flow": config.style.materialType = "LineFlow"; config.style.materialOptions = { color: option.color, image: option.image, repeat: new Cesium.Cartesian2(option.repeat[0], option.repeat[1]), speed: option.speed, }; break; case "arrow": config.style.materialType = "PolylineArrow"; config.style.materialOptions = { color: option.color, }; break; } } 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); // } openPopup() { this.graphic.openPopup(); } /** * 判断给定的经纬度坐标是否在某个多边形内 * * @param {number} lng - 经度 * @param {number} lat - 纬度 * @returns {boolean} 返回一个布尔值,如果给定的坐标在多边形内则为true,否则为false */ isInPoly(lng: any, lat: any) { return this.graphic.isInPoly(new mars3d.LngLatPoint(lng, lat)); } } 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.Polyline(this.config); } formatConfig(option: any) { let amapPosition = wgs84ToGcj02Format(option.position); return { path: amapPosition, strokeColor: option.color, strokeOpacity: option.opacity, strokeWeight: option.width, outlineColor: option.outlineColor, borderWeight: option.outlineWidth, 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.setPath(this.config.path); } } class siji_class extends SijiEntity { type: any = "line"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; graphic: any = null; intervalId: any = null; constructor(option: any) { // debugger; super(hnMap); this.id = option.id; deepMerge(this.option, option); this.config = this.formatConfig(this.option); // this.graphic = hnMap.map.map.addLayer(this.config); } flickers(speed: number, isShow: boolean) { if (this.intervalId !== null) { clearInterval(this.intervalId); } let opacity = isShow ? 1 : 0; const that = this; this.intervalId = setInterval(() => { isShow = !isShow; opacity = isShow ? 1 : 0; that.config["line-opacity"] = opacity; }, speed); } formatConfig(option: any) { let config: any = {}; config = { id: option.id, type: "line", source: { type: "geojson", data: { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "LineString", coordinates: convertPosition(option.position), }, properties: { id: option.id, ...option.data, }, }, ], }, }, layout: { "line-cap": "round", // 线端点样式 "line-join": "round", // 线连接样式 }, paint: { "line-color": option.type == "dash" ? option.dashColor : option.color, "line-width": Number(option.width), "line-opacity": Number(option.opacity), // "line-gap-width": 4, }, }; let isShow: boolean = true; switch (option.type) { case "line": break; case "dash": config.paint["line-dasharray"] = [ option.dashLength * 1, option.dashLength * 1, ]; break; case "flicker": this.flickers(option.speed * 1, isShow); // 调用 flickers 方法 break; case "flow": break; case "arrow": break; } return config; } set(option: any) { deepMerge(this.option, option); this.config = this.formatConfig(this.option); let mySource = hnMap.map.map.getSource(this.config.id); mySource.setData({ type: "FeatureCollection", features: [ { type: "Feature", properties: { id: option.id, ...option.data, }, geometry: { type: "LineString", coordinates: convertPosition(this.option.position), }, }, ], }); 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, key2 == "line-opacity" || key2 == "line-width" ? Number(this.config[key][key2]) : this.config[key][key2] ); if (option.type == "dash") { hnMap.map.map.setPaintProperty( this.config.id, "line-dasharray", [option.dashLength, option.dashLength] ); } // else { // hnMap.map.map.setPaintProperty( // this.config.id, // "line-dasharray", // [0, 0] // ); // } } } } } } } openPopup() { this.graphic.openPopup(); } /** * 判断给定的经纬度坐标是否在某个多边形内 * * @param {number} lng - 经度 * @param {number} lat - 纬度 * @returns {boolean} 返回一个布尔值,如果给定的坐标在多边形内则为true,否则为false */ isInPoly(lng: any, lat: any) { return this.graphic.isInPoly(new mars3d.LngLatPoint(lng, lat)); } dispose() { if (this.intervalId) { clearInterval(this.intervalId); // 清除定时器 this.intervalId = null; // 重置定时器ID } } } class cesium_class extends CesiumEntity { type: any = "line"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; graphic: any = null; entity: any = null; flickerInterval: 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) { // 转换位置坐标为 Cesium 格式 const positions = option.position.map((pos: any) => { if (Array.isArray(pos) && pos.length >= 2) { const height = pos.length >= 3 ? pos[2] : 0; return Cesium.Cartesian3.fromDegrees(pos[0], pos[1], height); } return pos; }); const config: any = { id: option.id, name: option.id, polyline: { positions: positions, width: option.width || 2, material: this.createMaterial(option), clampToGround: !(option.position[0] && option.position[0][2]), scaleByDistance: option.scaleByDistance ? new Cesium.NearFarScalar(1.0e2, 1.0, 1.0e7, 0.1) : undefined, show: true, }, properties: option.data || {}, // 添加自定义数据 }; // 添加距离显示条件 - 使用实际的距离值(米) if (option.distanceDisplayCondition) { // 将级别转换为实际距离(米) // 注意:这里需要根据您的具体需求调整数值 const near = getLevelMiddleHeight(option.distanceDisplayCondition_near); // 近处显示的最小距离 const far = getLevelMiddleHeight(option.distanceDisplayCondition_far); // 远处显示的最大距离 // 确保参数顺序正确 (near, far) config.polyline.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(near, far); } return config; } // 创建材质 createMaterial(option: any) { const color = Cesium.Color.fromCssColorString(option.color).withAlpha( option.opacity || 1 ); switch (option.type) { case "dash": return new Cesium.PolylineDashMaterialProperty({ color: color, dashLength: option.dashLength || 16, gapColor: Cesium.Color.fromCssColorString( option.dashColor ).withAlpha(option.opacity || 1), }); case "flow": return new Cesium.PolylineGlowMaterialProperty({ color: color, glowPower: 0.2, // 闪烁宽度 }); case "arrow": return new Cesium.PolylineArrowMaterialProperty(color); case "flicker": const flickerMaterial = new Cesium.ColorMaterialProperty(color); this.setupFlickerEffect(); return flickerMaterial; default: // 'line' // 只有当明确要求描边时才使用 PolylineOutlineMaterialProperty if (option.outline) { return new Cesium.PolylineOutlineMaterialProperty({ color: color, outlineColor: Cesium.Color.fromCssColorString( option.outlineColor ), outlineWidth: option.outlineWidth || 1, }); } else { // 否则使用普通的颜色材质 return new Cesium.ColorMaterialProperty(color); } } } // 设置闪烁效果 setupFlickerEffect() { if ( this.option.type === "flicker" && this.entity && this.entity.polyline ) { // 清理已存在的定时器 this.cleanupFlickerEffect(); let visible = true; const toggleVisibility = () => { if (this.entity && this.entity.polyline) { visible = !visible; this.entity.polyline.show = visible; } }; // 设置定时器 this.flickerInterval = setInterval( toggleVisibility, 500 / this.option.speed ); } } // 清理闪烁效果 cleanupFlickerEffect() { if (this.flickerInterval) { clearInterval(this.flickerInterval); this.flickerInterval = null; } } // 设置方法 set(option: any) { deepMerge(this.option, option); // 清理之前的特效 this.cleanupFlickerEffect(); // 更新实体 if (this.graphic) { const polyline = this.graphic.polyline; if (polyline) { // 更新位置 if (option.position) { const positions = option.position.map((pos: any) => { if (Array.isArray(pos) && pos.length >= 2) { const height = pos.length >= 3 ? pos[2] : 0; return Cesium.Cartesian3.fromDegrees(pos[0], pos[1], height); } return pos; }); polyline.positions = positions; } // 更新材质 polyline.material = this.createMaterial(this.option); // 更新线宽 if (option.width !== undefined) { polyline.width = option.width; } if (option.scaleByDistance) { polyline.scaleByDistance = new Cesium.NearFarScalar( 1.0e2, 1.0, 1.0e7, 0.1 ); } else { polyline.scaleByDistance = undefined; } // 更新距离显示条件 if (option.distanceDisplayCondition) { // 启用距离显示条件 const near = getLevelMiddleHeight( option.distanceDisplayCondition_near ); const far = getLevelMiddleHeight( option.distanceDisplayCondition_far ); polyline.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(near, far); } else { // 禁用距离显示条件 polyline.distanceDisplayCondition = undefined; } } } } // 销毁方法 destroy() { this.cleanupFlickerEffect(); if (this.graphic && hnMap.map.map && hnMap.map.map.entities) { hnMap.map.map.entities.remove(this.graphic); } } // 打开弹窗(如果需要) openPopup(htmlContent: string) { if (this.entity && hnMap.map.map) { // 设置实体的描述属性 this.entity.description = htmlContent; // 选中实体以显示弹窗 hnMap.map.map.selectedEntity = this.entity; } } } const fn: any = { mars3d: mars3d_class, gaode: gaode_class, siji: siji_class, cesium: cesium_class, }; return fn[hnMap.mapType]; };