Преглед на файлове

feat(map): 添加动态河流效果和流速控制功能
- 在config.json中配置地形参数和关闭地面大气显示
- 新增heshui.js文件实现动态河流图形层功能
- 优化图表销毁逻辑增加异常处理和资源清理
- 为图层样式添加贴地显示选项clampToGround
- 在工具栏添加流速测量功能和对话框组件
- 修改水面图层实现为动态河流效果并添加位置数据
- 实现全局事件通信机制用于流速值传递更新

王杰 преди 1 седмица
родител
ревизия
02230ed0aa

+ 368 - 0
heshui.js

@@ -0,0 +1,368 @@
+import * as mars3d from "mars3d"
+
+export let map // mars3d.Map三维地图对象
+export let graphicLayer // 图层
+
+// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
+export const mapOptions = {
+  scene: {
+    center: { lat: 30.422407, lng: 115.820222, alt: 3498, heading: 67, pitch: -32 },
+    globe: {
+      depthTestAgainstTerrain: true
+    }
+  }
+}
+
+// 初始化地图业务,生命周期钩子函数(必须),框架在地图初始化完成后自动调用该函数
+export function onMounted(mapInstance) {
+  map = mapInstance // 记录map
+
+  // 创建矢量数据图层
+  graphicLayer = new mars3d.layer.GraphicLayer()
+  map.addLayer(graphicLayer)
+
+  // 在layer上绑定监听事件
+  graphicLayer.on(mars3d.EventType.click, function (event) {
+    console.log("监听layer,单击了矢量对象", event)
+  })
+
+  bindLayerPopup() // 在图层上绑定popup,对所有加到这个图层的矢量数据都生效
+  bindLayerContextMenu() // 在图层绑定右键菜单,对所有加到这个图层的矢量数据都生效
+
+  // 加一些演示数据
+  addDemoGraphic1()
+}
+
+// 释放当前地图业务的生命周期函数,具体项目中时必须写onMounted的反向操作(如解绑事件、对象销毁、变量置空)
+export function onUnmounted() {
+  map = null
+  clear()
+}
+
+// 立体围墙扩散效果,面状
+function addDemoGraphic1() {
+  const dynamicRiver = new mars3d.graphic.DynamicRiver({
+    positions: [
+      [115.906607, 30.441582, 555.9],
+      [115.899964, 30.438543, 467.3],
+      [115.893105, 30.440714, 374.6],
+      [115.88362, 30.443924, 340.7],
+      [115.873948, 30.444827, 299],
+      [115.864003, 30.442111, 292.2],
+      [115.850741, 30.438108, 189.9]
+    ],
+    style: {
+      image: "https://data.mars3d.cn/img/textures/poly-rivers.png",
+      width: 280,
+      height: 30,
+      speed: 10
+    }
+  })
+  graphicLayer.addGraphic(dynamicRiver)
+}
+
+// 生成演示数据(测试数据量)
+export function addRandomGraphicByCount(count) {
+  graphicLayer.clear()
+  graphicLayer.enabledEvent = false // 关闭事件,大数据addGraphic时影响加载时间
+
+  const bbox = [116.984788, 31.625909, 117.484068, 32.021504]
+  const result = mars3d.PolyUtil.getGridPoints(bbox, count, 30)
+  console.log("生成的测试网格坐标", result)
+
+  for (let j = 0; j < result.points.length; ++j) {
+    const position = result.points[j]
+    const index = j + 1
+
+    const pt1 = mars3d.PointUtil.getPositionByDirectionAndLen(position, 225, result.radius)
+    const pt2 = mars3d.PointUtil.getPositionByDirectionAndLen(position, 315, result.radius)
+
+    const graphic = new mars3d.graphic.DynamicRiver({
+      positions: [pt1, position, pt2],
+      style: {
+        image: "https://data.mars3d.cn/img/textures/poly-rivers.png",
+        width: 280,
+        height: 30,
+        speed: 10
+      },
+      attr: { index }
+    })
+    graphicLayer.addGraphic(graphic)
+  }
+
+  graphicLayer.enabledEvent = true // 恢复事件
+  return result.points.length
+}
+
+// 开始绘制
+export async function startDrawGraphic() {
+  const graphic = await graphicLayer.startDraw({
+    type: "dynamicRiver",
+    style: {
+      image: "https://data.mars3d.cn/img/textures/poly-rivers.png",
+      width: 280,
+      height: 30,
+      speed: 10
+    }
+  })
+  console.log("标绘完成", graphic.toJSON())
+}
+
+let dynamicRiver
+export function getGraphic(graphicId) {
+  dynamicRiver = graphicLayer.getGraphicById(graphicId)
+  return dynamicRiver
+}
+
+// 宽发生改变
+export function widthChange(value) {
+  if (dynamicRiver) {
+    dynamicRiver.width = value
+  }
+}
+
+// 高发生改变
+export function heightChange(value) {
+  if (dynamicRiver) {
+    dynamicRiver.height = value
+  }
+}
+
+// 速度发生改变
+export function speedChange(value) {
+  if (dynamicRiver) {
+    dynamicRiver.speed = value
+  }
+}
+
+let onOff = true
+// 升高30米动画
+export function addHeight() {
+  if (!dynamicRiver) {
+    return
+  }
+  if (!onOff) {
+    globalMsg("上次操作未完成")
+    return
+  }
+  dynamicRiver.setOffsetHeight(30, 5) // 5秒内抬高30米
+  throttle()
+}
+
+// 下降30米动画
+export function lowerHeight() {
+  if (!dynamicRiver) {
+    return
+  }
+  if (!onOff) {
+    globalMsg("上次操作未完成")
+    return
+  }
+  dynamicRiver.setOffsetHeight(-30, 5) // 5秒内降低30米
+  throttle()
+}
+
+function throttle() {
+  setTimeout(() => {
+    onOff = true
+  }, 2000)
+
+  onOff = false
+}
+
+// 清除
+export function clear() {
+  graphicLayer.clear()
+}
+
+// 在图层绑定Popup弹窗
+export function bindLayerPopup() {
+  graphicLayer.bindPopup(function (event) {
+    const attr = event.graphic.attr || {}
+    attr["类型"] = event.graphic.type
+    attr["来源"] = "我是layer上绑定的Popup"
+    attr["备注"] = "我支持鼠标交互"
+
+    return mars3d.Util.getTemplateHtml({ title: "矢量图层", template: "all", attr })
+  })
+}
+
+// 绑定右键菜单
+export function bindLayerContextMenu() {
+  graphicLayer.bindContextMenu([
+    {
+      text: "开始编辑对象",
+      icon: "fa fa-edit",
+      show: function (e) {
+        const graphic = e.graphic
+        if (!graphic || !graphic.hasEdit) {
+          return false
+        }
+        return !graphic.isEditing
+      },
+      callback: (e) => {
+        const graphic = e.graphic
+        if (!graphic) {
+          return false
+        }
+        if (graphic) {
+          graphicLayer.startEditing(graphic)
+        }
+      }
+    },
+    {
+      text: "停止编辑对象",
+      icon: "fa fa-edit",
+      show: function (e) {
+        const graphic = e.graphic
+        if (!graphic || !graphic.hasEdit) {
+          return false
+        }
+        return graphic.isEditing
+      },
+      callback: (e) => {
+        const graphic = e.graphic
+        if (!graphic) {
+          return false
+        }
+        if (graphic) {
+          graphic.stopEditing()
+        }
+      }
+    },
+    {
+      text: "复制",
+      icon: "fa fa-copy",
+      callback: (e) => {
+        const graphic = e.graphic
+        if (!graphic) {
+          return false
+        }
+        if (graphic) {
+          map.contextmenu.copyGraphic = graphic.toJSON() // map内置右键中"粘贴"菜单使用
+          map.contextmenu.copyGraphic.layerId = graphicLayer.id
+        }
+      }
+    },
+    {
+      text: "剪切",
+      icon: "fa fa-scissors",
+      callback: (e) => {
+        const graphic = e.graphic
+        if (!graphic) {
+          return false
+        }
+        if (graphic) {
+          map.contextmenu.copyGraphic = graphic.toJSON() // map内置右键中"粘贴"菜单使用
+          map.contextmenu.copyGraphic.layerId = graphicLayer.id
+
+          graphic.remove(true) // 移除原有对象
+        }
+      }
+    },
+    {
+      text: "还原编辑(还原到初始)",
+      icon: "fa fa-pencil",
+      show: (event) => {
+        function hasRestore(graphic) {
+          if (!graphic || !graphic.hasEdit || !graphic.isEditing) {
+            return false
+          }
+          return graphic.editing?.hasRestore()
+        }
+
+        const graphic = event.graphic
+        if (hasRestore(graphic)) {
+          return true
+        }
+        if (graphic.isPrivate && graphic.parent) {
+          return hasRestore(graphic.parent) // 右击是编辑点时
+        }
+        return false
+      },
+      callback: (event) => {
+        const graphic = event.graphic
+        if (graphic.editing?.restore) {
+          graphic.editing.restore() // 撤销编辑,可直接调用
+        } else if (graphic.parent?.editing?.restore) {
+          graphic.parent.editing.restore() // 右击是编辑点时
+        }
+      }
+    },
+    {
+      text: "撤销编辑(还原到上一步)",
+      icon: "fa fa-pencil",
+      show: (event) => {
+        function hasRevoke(graphic) {
+          if (!graphic || !graphic.hasEdit || !graphic.isEditing) {
+            return false
+          }
+          return graphic.editing?.hasRevoke()
+        }
+
+        const graphic = event.graphic
+        if (hasRevoke(graphic)) {
+          return true
+        }
+        if (graphic.isPrivate && graphic.parent) {
+          return hasRevoke(graphic.parent) // 右击是编辑点时
+        }
+        return false
+      },
+      callback: (event) => {
+        const graphic = event.graphic
+        if (graphic.editing?.revoke) {
+          graphic.editing.revoke() // 撤销编辑,可直接调用
+        } else if (graphic.parent?.editing?.revoke) {
+          graphic.parent.editing.revoke() // 右击是编辑点时
+        }
+      }
+    },
+    {
+      text: "删除对象",
+      icon: "fa fa-trash-o",
+      show: (event) => {
+        const graphic = event.graphic
+        if (!graphic || graphic.isDestroy || graphic.isPrivate || graphic.graphicIds) {
+          return false
+        } else {
+          return true
+        }
+      },
+      callback: (e) => {
+        const graphic = e.graphic
+        if (!graphic) {
+          return
+        }
+        const parent = graphic.parent // 右击是编辑点时
+        graphicLayer.removeGraphic(graphic)
+        if (parent) {
+          graphicLayer.removeGraphic(parent)
+        }
+      }
+    },
+    {
+      text: "查看聚合列表",
+      icon: "fa fa-info",
+      show: (event) => {
+        const graphic = event.graphic
+        if (graphic.cluster && graphic.graphics) {
+          return true
+        } else {
+          return false
+        }
+      },
+      callback: (e) => {
+        const graphics = e.graphic?.graphics
+        if (graphics) {
+          const names = []
+          for (let index = 0; index < graphics.length; index++) {
+            const g = graphics[index]
+            names.push(g.attr.name || g.attr.text || g.id)
+          }
+          return globalAlert(`${names.join(",")}`, `共${graphics.length}个聚合对象`)
+        }
+      }
+    }
+  ])
+}

+ 9 - 4
public/config/config.json

@@ -16,7 +16,7 @@
       "globe": {
         "depthTestAgainstTerrain": false,
         "baseColor": "#546a53",
-        "showGroundAtmosphere": true,
+        "showGroundAtmosphere": false,
         "enableLighting": false
       },
       "cameraController": {
@@ -46,6 +46,11 @@
       "contextmenu": { "hasDefault": true },
       "mouseDownView": true
     },
+    "terrain": {
+      "url": "//data.mars3d.cn/terrain",
+      "show": false,
+      "clip": false
+    },
     "basemaps": [
       { "id": 10, "name": "地图底图", "type": "group" },
       {
@@ -56,8 +61,7 @@
         "layers": [
           { "name": "底图", "type": "tdt", "layer": "img_d" },
           { "name": "注记", "type": "tdt", "layer": "img_z" }
-        ],
-        "show": true
+        ]
       },
       {
         "pid": 10,
@@ -77,7 +81,8 @@
         "layers": [
           { "name": "底图", "type": "gaode", "layer": "img_d" },
           { "name": "注记", "type": "gaode", "layer": "img_z" }
-        ]
+        ],
+        "show": true
       },
       {
         "pid": 10,

+ 27 - 3
src/mixins/index.js

@@ -15,15 +15,39 @@ export const echartMixin = {
     this.$nextTick(() => this.initChart())
   },
   beforeDestroy() {
+    window.removeEventListener('resize', this.resizeChart)
     if (this.chartObj) {
-      this.chartObj.dispose() // 销毁图表实例
+      try {
+        // 清除所有高亮和定时器
+        this.chartObj.dispatchAction({ type: 'downplay' })
+        // 清除 zrender 动画
+        this.chartObj.clear()
+        // 销毁实例
+        this.chartObj.dispose()
+      } catch (e) {
+        console.error('销毁图表实例时出错:', e)
+      }
+      this.chartObj = null
     }
-    window.removeEventListener('resize', this.resizeChart)
   },
   methods: {
     resizeChart() {
       if (this.chartObj) {
-        this.chartObj.resize() // 调整图表大小
+        this.chartObj.resize()
+      }
+    },
+    // 初始化图表时禁用 emphasis
+    initChartWithOption(option) {
+      // 禁用所有系列的 emphasis
+      if (option.series) {
+        option.series.forEach(series => {
+          if (!series.emphasis) {
+            series.emphasis = { disabled: true }
+          }
+        })
+      }
+      if (this.chartObj) {
+        this.chartObj.setOption(option)
       }
     }
   },

Файловите разлики са ограничени, защото са твърде много
+ 277 - 277
src/utils/EasyPlayer-component.min.js


+ 8 - 5
src/views/components/layerList/index.vue

@@ -314,15 +314,15 @@ export default {
     getStyleByName(name) {
       console.info(name)
       if (name === '兴平市生态区界限' || name === '生态区界限' ) {
-        return { type: 'polyline', styleOptions: { color: '#0c5b0f', width: 2 } }
+        return { type: 'polyline', styleOptions: { color: '#0c5b0f', width: 2 ,clampToGround: true} }
       } else if (name === '兴平市堤防外坡脚线' || name === '堤防外坡脚线') {
-        return { type: 'polyline', styleOptions: { color: '#c53632', width: 2 } }
+        return { type: 'polyline', styleOptions: { color: '#c53632', width: 2 ,clampToGround: true} }
       } else if (name === '兴平市河道管理范围线' || name === '河道管理范围线') {
-        return { type: 'polyline', styleOptions: { color: '#12641c', width: 2 } }
-      } else if (name === '兴平市一级管控区线' || name === '一级管控区线') {
+        return { type: 'polyline', styleOptions: { color: '#12641c', width: 2 ,clampToGround: true} }
+      } else if (name === '兴平市一级管控区线' || name === '一级管控区线') {
         return {
           type: 'polyline',
-          styleOptions: { width: 2, materialType: mars3d.MaterialType.PolylineDash, materialOptions: { color: '#12641c', dashLength: 60 } }
+          styleOptions: { width: 2,clampToGround: true,materialType: mars3d.MaterialType.PolylineDash, materialOptions: { color: '#12641c', dashLength: 60 } }
         }
       } else if (name === '城市核心区' || name === '农村区段') {
         return {
@@ -332,6 +332,7 @@ export default {
             opacity: 0.6,
             outline: true,
             outlineWidth: 1,
+            clampToGround: true,
             outlineColor: '#57e0a9'
           }
         }
@@ -343,6 +344,7 @@ export default {
             opacity: 0.3,
             outline: true,
             outlineWidth: 1,
+            clampToGround: true,
             outlineColor: '#57e0a9'
           }
         }
@@ -391,6 +393,7 @@ export default {
             materialOptions: { color: '#cc9648', cellAlpha: 0.5 },
             outline: true,
             outlineWidth: 1,
+            clampToGround: true,
             outlineColor: '#cc9648'
           }
         }

+ 50 - 4
src/views/components/tools/index.vue

@@ -9,9 +9,30 @@
       <div class="measuring-tool" :class="{ clToolHide: !measureShow }">
         <div class="ranging" :class="{ active: rangingActive }" @click="measureRanging">测距</div>
         <div class="measureArea" :class="{ active: measureActive }" @click="measureArea">测面</div>
+        <div class="flowSpeed" :class="{ active: flowSpeedActive }" @click="openFlowSpeedDialog">流速</div>
       </div>
     </div>
     <Controls v-if="isMapActive" />
+    <!-- 流速输入框 -->
+    <el-dialog
+      :visible.sync="flowSpeedDialogVisible"
+      title="设置流速"
+      width="300px"
+      :before-close="handleClose"
+    >
+      <el-input-number
+        v-model="flowSpeedValue"
+        :min="1"
+        :max="200"
+        :step="1"
+        controls-position="right"
+        style="width: 100%"
+      />
+      <span slot="footer">
+        <el-button @click="handleClose">取消</el-button>
+        <el-button type="primary" @click="confirmFlowSpeed">确定</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
 
@@ -31,7 +52,10 @@ export default {
       rightPanelHide:false,
       distanceMeasure: null, // 测距工具实例
       isMeasuring: false, // 是否正在测量
-      measureResult: '' // 测量结果
+      measureResult: '', // 测量结果
+      flowSpeedActive: false,
+      flowSpeedDialogVisible: false,
+      flowSpeedValue: 10
     }
   },
   components: {
@@ -102,11 +126,12 @@ export default {
       this.measureActive = !this.measureActive
       if (this.measureActive) {
         this.rangingActive = false
+        this.flowSpeedActive = false
         const graphic = this.distanceMeasure.area({
           style: {
             color: '#4F9FFF',
             fill: true,
-            materialType:"Color",
+            materialType: "Color",
             fillColor: 'rgba(73,142,227,0.2)',
             outline:true,
             outlineColor: '#4F9FFF',
@@ -115,7 +140,7 @@ export default {
           }
         })
 
-        // 下面代码抬升面的高度到一个平面,来示意“水平”
+        // 下面代码抬升面的高度到一个平面,来示意"水平"
         if (window.map.scene.mode === this.Cesium.SceneMode.SCENE3D) {
           const oldPositions = graphic.positionsShow
           const rang = this.mars3d.PolyUtil.getHeightRangeByDepth(oldPositions, window.map.scene)
@@ -124,6 +149,26 @@ export default {
       } else {
         this.distanceMeasure.clear()
       }
+    },
+    openFlowSpeedDialog() {
+      this.flowSpeedActive = !this.flowSpeedActive
+      if (this.flowSpeedActive) {
+        this.measureActive = false
+        this.rangingActive = false
+        this.flowSpeedDialogVisible = true
+      } else {
+        this.distanceMeasure.clear()
+      }
+    },
+    handleClose() {
+      this.flowSpeedDialogVisible = false
+      this.flowSpeedActive = false
+    },
+    confirmFlowSpeed() {
+      // 触发全局事件,通知 index.vue 更新流速
+      this.$globalEventBus.$emit('updateFlowSpeed', this.flowSpeedValue)
+      this.flowSpeedDialogVisible = false
+      this.flowSpeedActive = false
     }
   },
   destroyed() {
@@ -169,7 +214,8 @@ export default {
       padding: px-to-rem(10);
     }
     .ranging.active,
-    .measureArea.active {
+    .measureArea.active,
+    .flowSpeed.active {
       background: rgba(79, 159, 255, 0.4);
       color: #4f9fff;
     }

+ 0 - 10
src/views/hydrologic-info/right.vue

@@ -343,11 +343,6 @@ export default {
                     color: '#ffff', // 点颜色
                     borderColor: '#66DC95', // 点的边框颜色
                     borderWidth: 2 // 点的边框宽度
-                  },
-                  emphasis: {
-                    borderWidth: 4, // 鼠标悬停时边框加粗
-                    shadowBlur: 10, // 阴影模糊大小,实现放大的效果
-                    shadowColor: 'rgba(0, 0, 0, 0.3)' // 阴影颜色
                   }
                 },
                 areaStyle: {
@@ -442,11 +437,6 @@ export default {
                     color: '#ffff', // 点颜色
                     borderColor: '#4487D7', // 点的边框颜色
                     borderWidth: 2 // 点的边框宽度
-                  },
-                  emphasis: {
-                    borderWidth: 4, // 鼠标悬停时边框加粗
-                    shadowBlur: 10, // 阴影模糊大小,实现放大的效果
-                    shadowColor: 'rgba(0, 0, 0, 0.3)' // 阴影颜色
                   }
                 },
                 areaStyle: {

Файловите разлики са ограничени, защото са твърде много
+ 204 - 43
src/views/index.vue


+ 0 - 5
src/views/water-station-popup/index.vue

@@ -312,11 +312,6 @@ export default {
                       color: '#ffff', // 点颜色
                       borderColor: '#66DC95', // 点的边框颜色
                       borderWidth: 2 // 点的边框宽度
-                    },
-                    emphasis: {
-                      borderWidth: 4, // 鼠标悬停时边框加粗
-                      shadowBlur: 10, // 阴影模糊大小,实现放大的效果
-                      shadowColor: 'rgba(0, 0, 0, 0.3)' // 阴影颜色
                     }
                   },
                   areaStyle: {

+ 712 - 0
wall.js

@@ -0,0 +1,712 @@
+import * as mars3d from "mars3d"
+
+export let map // mars3d.Map三维地图对象
+export let graphicLayer // 矢量图层对象
+export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中
+
+// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
+export const mapOptions = {
+  scene: {
+    center: { lat: 30.402686, lng: 116.303632, alt: 48692, heading: 3, pitch: -43 }
+  }
+}
+
+// 初始化地图业务,生命周期钩子函数(必须),框架在地图初始化完成后自动调用该函数
+export function onMounted(mapInstance) {
+  map = mapInstance // 记录首次创建的map
+
+  // map.on(mars3d.EventType.removeLayer, function (event) {
+  //   console.log("移除了图层", event)
+  // })
+
+  showDraw()
+}
+
+// 释放当前地图业务的生命周期函数,具体项目中时必须写onMounted的反向操作(如解绑事件、对象销毁、变量置空)
+export function onUnmounted() {
+  map = null
+}
+
+function removeLayer() {
+  if (graphicLayer) {
+    graphicLayer.clear()
+    map.removeLayer(graphicLayer, true)
+    graphicLayer = null
+  }
+  if (tilesetLayer) {
+    map.removeLayer(tilesetLayer, true)
+    tilesetLayer = null
+  }
+}
+
+/**
+ * 平台通过draw标绘后保存的geojosn数据(已经内置style了,无需配置symbol)
+ */
+export function showDraw(isFlyTo) {
+  removeLayer()
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "标绘示例数据",
+    url: "https://data.mars3d.cn/file/geojson/mars3d-draw.json",
+    popup: "{type} {name}",
+    queryParameters: {
+      token: "mars3d" // 可以传自定义url参数,如token等
+    },
+    symbol: {
+      merge: true,
+      styleOptions: {
+        // 高亮时的样式
+        highlight: {
+          type: "click",
+          opacity: 0.9
+        }
+      }
+    },
+    flyTo: isFlyTo
+  })
+  map.addLayer(graphicLayer)
+
+  // load事件,必须在load完成前绑定才能监听
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+
+  setTimeout(() => {
+    // readyPromise是可以load加载数据完成后去获取
+    graphicLayer.readyPromise.then(function (layer) {
+      console.log("readyPromise:数据加载完成", layer)
+    })
+  }, 5000)
+
+  // 单击事件
+  graphicLayer.on(mars3d.EventType.click, function (event) {
+    console.log("单击了图层", event)
+  })
+}
+
+/**
+ * 点数据
+ */
+export function showPoint() {
+  removeLayer()
+
+  window._test_button_click = function (attr) {
+    globalAlert(JSON.stringify(attr), "测试查看详情")
+  }
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "体育设施点",
+    url: "https://data.mars3d.cn/file/geojson/hfty-point.json",
+    symbol: {
+      styleOptions: {
+        image: "https://data.mars3d.cn/img/marker/mark-red.png",
+        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+        scale: 1,
+        scaleByDistance: true,
+        scaleByDistance_far: 20000,
+        scaleByDistance_farValue: 0.5,
+        scaleByDistance_near: 1000,
+        scaleByDistance_nearValue: 1,
+        // setHeight: 5000, //指定高度
+        label: {
+          text: "{项目名称}",
+          font_size: 25,
+          color: "#ffffff",
+          outline: true,
+          outlineColor: "#000000",
+          pixelOffsetY: -25,
+          scaleByDistance: true,
+          scaleByDistance_far: 80000,
+          scaleByDistance_farValue: 0.5,
+          scaleByDistance_near: 1000,
+          scaleByDistance_nearValue: 1,
+          distanceDisplayCondition: true,
+          distanceDisplayCondition_far: 80000,
+          distanceDisplayCondition_near: 0
+        }
+      }
+    },
+    popup: [
+      { field: "项目名称", name: "项目名称" },
+      { field: "建设性质", name: "建设性质" },
+      { field: "设施级别", name: "设施级别" },
+      { field: "所属区县", name: "所属区县" },
+      { field: "建筑内容及", name: "建筑内容" },
+      { field: "新增用地(", name: "新增用地" },
+      { field: "开工", name: "开工" },
+      { field: "总投资(万", name: "总投资" },
+      { field: "资金来源", name: "资金来源" },
+      { field: "初步选址", name: "初步选址" },
+      { field: "设施类型", name: "设施类型" },
+      { field: "设施等级", name: "设施等级" },
+      { field: "所在区县", name: "所在区县" },
+      { field: "具体位置", name: "具体位置" },
+      { field: "建设内容(", name: "建设内容" },
+      { field: "用地面积(", name: "用地面积", format: "mars3d.MeasureUtil.formatArea" },
+      { field: "设施规模(", name: "设施规模" },
+      { field: "举办者类型", name: "举办者类型" },
+      { field: "开工时间", name: "开工时间" },
+      { field: "总投资额(", name: "总投资额", unit: "亿元" },
+      { field: "项目推进主", name: "项目推进主体" },
+      { field: "项目进度", name: "项目进度" },
+      { field: "项目来源", name: "项目来源" },
+      { field: "备注", name: "备注" },
+      { name: "详情", type: "button", className: "mars3d-popup-btn-custom", callback: "_test_button_click" }
+    ],
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+
+  graphicLayer.on(mars3d.EventType.click, function (event) {
+    console.log("单击了图层", event)
+  })
+}
+
+export function showPointForHeat() {
+  removeLayer()
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "体育设施点-按热力图渲染",
+    url: "https://data.mars3d.cn/file/geojson/hfty-point.json",
+    symbol: {
+      type: "heat", // 按热力图来渲染数据
+      // 下面参数支持mars3d.layer.HeatLayer的所有构造参数
+      heatStyle: {
+        radius: 20,
+        minOpacity: 0,
+        maxOpacity: 0.4,
+        blur: 0.3,
+        gradient: {
+          0: "#e9ec36",
+          0.25: "#ffdd2f",
+          0.5: "#fa6c20",
+          0.75: "#fe4a33",
+          1: "#ff0000"
+        }
+      },
+      // 以下为矩形矢量对象的样式参数
+      style: {
+        opacity: 1.0,
+        outline: true, // 显示范围线,方便对照
+        outlineColor: "#ffffff",
+        outlineWidth: 1
+      }
+    },
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+  })
+}
+
+/**
+ * 全国省界
+ */
+export function showChinaLine() {
+  removeLayer()
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "全国省界",
+    url: "https://data.mars3d.cn/file/geojson/areas/100000_full.json",
+    format: simplifyGeoJSON, // 用于自定义处理geojson
+    // simplify: { tolerance: 0.00001 },
+    symbol: {
+      type: "polylineP",
+      styleOptions: {
+        width: 2,
+        materialType: mars3d.MaterialType.LineFlow,
+        materialOptions: {
+          color: "#00ffff",
+          image: "https://data.mars3d.cn/img/textures/fence-line.png",
+          speed: 10,
+          repeat_x: 10
+        },
+        distanceDisplayCondition: true,
+        distanceDisplayCondition_far: 12000000,
+        distanceDisplayCondition_near: 100000,
+        label: {
+          text: "{name}",
+          position: "{center}", // 省会位置center
+          font_size: 30,
+          color: "#ffffff",
+          outline: true,
+          outlineColor: "#000000",
+          scaleByDistance: true,
+          scaleByDistance_far: 60000000,
+          scaleByDistance_farValue: 0.2,
+          scaleByDistance_near: 1000000,
+          scaleByDistance_nearValue: 1,
+          distanceDisplayCondition: true,
+          distanceDisplayCondition_far: 10000000,
+          distanceDisplayCondition_near: 100000,
+          setHeight: 10000
+        }
+      }
+    },
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+}
+
+// 简化geojson的坐标
+function simplifyGeoJSON(geojson) {
+  try {
+    geojson = turf.simplify(geojson, { tolerance: 0.0001, highQuality: true, mutate: true })
+  } catch (e) {
+    //
+  }
+  return geojson
+}
+
+/**
+ * 显示合肥区域面
+ */
+export function showRegion() {
+  removeLayer()
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "合肥市",
+    url: "https://data.mars3d.cn/file/geojson/areas/340100_full.json",
+    symbol: {
+      styleOptions: {
+        fill: true,
+        randomColor: true, // 随机色
+        opacity: 0.3,
+        outline: true,
+        outlineStyle: {
+          color: "#FED976",
+          width: 3,
+          opacity: 1
+        },
+        // 高亮时的样式
+        highlight: {
+          opacity: 0.9,
+          outlineStyle: {
+            width: 6,
+            color: "#ff0000",
+            addHeight: 100
+          },
+          label: { show: true }
+        },
+        label: {
+          show: false,
+          // 面中心点,显示文字的配置
+          text: "{name}", // 对应的属性名称
+          opacity: 1,
+          font_size: 40,
+          color: "#ffffff",
+
+          font_family: "楷体",
+          outline: true,
+          outlineColor: "#000000",
+          outlineWidth: 3,
+
+          background: false,
+          backgroundColor: "#000000",
+          backgroundOpacity: 0.1,
+
+          font_weight: "normal",
+          font_style: "normal",
+
+          scaleByDistance: true,
+          scaleByDistance_far: 20000000,
+          scaleByDistance_farValue: 0.1,
+          scaleByDistance_near: 1000,
+          scaleByDistance_nearValue: 1,
+
+          distanceDisplayCondition: false,
+          distanceDisplayCondition_far: 10000,
+          distanceDisplayCondition_near: 0,
+          visibleDepth: false
+        }
+      }
+    },
+    popup: "{name}",
+    // "tooltip": "{name}",
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+  graphicLayer.on(mars3d.EventType.click, function (event) {
+    console.log("单击了图层", event)
+  })
+}
+
+// 规划面
+export function showPlanningSurface() {
+  removeLayer()
+
+  map.setCameraView({ lat: 31.591382, lng: 120.718945, alt: 784, heading: 279, pitch: -67 })
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    id: 1987,
+    name: "用地规划",
+    // 1.支持URL
+    url: "https://data.mars3d.cn/file/geojson/guihua.json",
+    // 2.也支持直接传入数据
+    // data: {
+    //   type: "FeatureCollection",
+    //   name: "用地规划",
+    //   features: [] //数据已省略,可以从上面guihua.json中复制
+    // },
+    symbol: {
+      type: "polygonC",
+      styleOptions: {
+        opacity: 0.6,
+        color: "#0000FF"
+      },
+      styleField: "类型",
+      styleFieldOptions: {
+        一类居住用地: { color: "#FFDF7F" },
+        二类居住用地: { color: "#FFFF00" },
+        社区服务用地: { color: "#FF6A38" },
+        幼托用地: { color: "#FF6A38" },
+        商住混合用地: { color: "#FF850A" },
+        行政办公用地: { color: "#FF00FF" },
+        文化设施用地: { color: "#FF00FF" },
+        小学用地: { color: "#FF7FFF" },
+        初中用地: { color: "#FF7FFF" },
+        体育场用地: { color: "#00A57C" },
+        医院用地: { color: "#A5527C" },
+        社会福利用地: { color: "#FF7F9F" },
+        商业用地: { color: "#FF0000" },
+        商务用地: { color: "#7F0000" },
+        营业网点用地: { color: "#FF7F7F" },
+        一类工业用地: { color: "#A57C52" },
+        社会停车场用地: { color: "#C0C0C0" },
+        通信用地: { color: "#007CA5" },
+        排水用地: { color: "#00BFFF" },
+        公园绿地: { color: "#00FF00" },
+        防护绿地: { color: "#007F00" },
+        河流水域: { color: "#7FFFFF" },
+        配建停车场: { color: "#ffffff" },
+        道路用地: { color: "#ffffff" }
+      }
+    },
+    popup: "类型:{类型}"
+    // flyTo: true,
+  })
+  map.addLayer(graphicLayer)
+
+  // 下面代码演示如果再config.json中配置的图层,如何绑定额外事件方法
+  // 绑定config.json中对应图层配置的"id"值图层的单击事件(比如下面是id:1987对应图层)
+  const layerTest = map.getLayerById(1987)
+  // 绑定事件
+  layerTest.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+
+  layerTest.on(mars3d.EventType.click, function (event) {
+    // 单击事件
+    console.log("单击了图层", event)
+  })
+}
+
+/**
+ * 立体建筑物
+ */
+export function showBuilding() {
+  removeLayer()
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "建筑物面",
+    url: "https://data.mars3d.cn/file/geojson/buildings-demo.json",
+    // filter: "floors>30", // 筛选数据
+    symbol: {
+      styleOptions: {
+        color: "#0d3685",
+        outlineColor: "#0d3685",
+        opacity: 0.8
+      },
+      // styleFieldOptions: {
+      //   "floors<20": { color: "#ff0000" },
+      //   "floors>20 && floors<30": { color: "#fff000" },
+      //   "floors>30": { color: "#00ffff" }
+      // },
+      callback: function (attr, styleOpt) {
+        const diffHeight = Number(attr.floors || 1) * Number(attr.flo_height)
+        return { height: 0, diffHeight }
+      }
+    },
+    center: { lat: 31.928659, lng: 120.420654, alt: 838, heading: 344, pitch: -42 },
+    popup: "all",
+    popupOptions: {
+      showNull: true
+    },
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+}
+
+/**
+ *  分层分户立体建筑物
+ */
+export function showFloor() {
+  removeLayer()
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "分层分户建筑物面",
+    url: "https://data.mars3d.cn/file/geojson/huxing.json",
+    symbol: {
+      styleOptions: {
+        color: "#ffffff",
+        opacity: 0.2,
+        outline: true,
+        outlineColor: "#63AEFF",
+        outlineOpacity: 0.3,
+
+        highlight: {
+          type: "click",
+          color: "#00ffff",
+          opacity: 0.6
+        }
+      },
+      callback: function (attr, styleOpt) {
+        const flrH = attr.floorh || 0 // 底面高度
+        const lyrH = attr.layerh || 0 // 楼层高度
+
+        return { height: flrH, diffHeight: lyrH }
+      }
+    },
+    // popup: "all",
+    center: { lat: 31.821524, lng: 117.179329, alt: 255, heading: 25, pitch: -48 },
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+}
+
+/**
+ * 行政区划 ,转为wall显示
+ */
+export function showBoundaryWall() {
+  removeLayer()
+
+  map.setCameraView({ lat: 30.561661, lng: 117.663884, alt: 113078, heading: 346, pitch: -43 })
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "合肥市",
+    url: "https://data.mars3d.cn/file/geojson/areas/340100_full.json",
+    symbol: {
+      type: "wall",
+      styleOptions: {
+        diffHeight: 5000, // 墙高
+        materialType: mars3d.MaterialType.LineFlow,
+        materialOptions: {
+          color: "#00ffff", // 颜色
+          opacity: 0.6, // 透明度
+          image: "https://data.mars3d.cn/img/textures/fence.png", // 图片
+          repeatX: 1, // 重复数量
+          axisY: true, // 竖直方向
+          speed: 10 // 速度
+        },
+        // 高亮时的样式
+        highlight: {
+          type: "click",
+          color: "#ffff00"
+        }
+      }
+    },
+    popup: "{name}"
+    // "tooltip": "{name}",
+    // flyTo: true,
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+  graphicLayer.on(mars3d.EventType.click, function (event) {
+    console.log("单击了图层", event)
+  })
+}
+
+/**
+ * 显示特殊面数据(单体化)
+ */
+let tilesetLayer
+export function showMonomer() {
+  removeLayer()
+
+  // 三维模型
+  if (!tilesetLayer) {
+    tilesetLayer = new mars3d.layer.TilesetLayer({
+      name: "文庙",
+      type: "3dtiles",
+      url: "https://data.mars3d.cn/3dtiles/qx-simiao/tileset.json",
+      position: { alt: 38.8 },
+      maximumScreenSpaceError: 1,
+      show: true
+    })
+    map.addLayer(tilesetLayer)
+  }
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "文庙-单体化",
+    url: " //data.mars3d.cn/file/geojson/dth-wm.json",
+    symbol: {
+      type: "polygonP",
+      styleOptions: {
+        // 单体化默认显示样式
+        color: "rgba(255, 255, 255, 0.01)",
+        clampToGround: true,
+        classification: true,
+        // 单体化鼠标移入或单击后高亮的样式
+        highlight: {
+          // type: mars3d.EventType.click,
+          color: "rgba(255,255,0,0.4)"
+        }
+      }
+    },
+    popup: [
+      { field: "name", name: "房屋名称" },
+      { field: "jznf", name: "建造年份" },
+      { field: "ssdw", name: "所属单位" },
+      { field: "remark", name: "备注信息" }
+    ],
+    center: { lat: 33.589442, lng: 119.031613, alt: 254, heading: 5, pitch: -37 },
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+}
+
+/**
+ * 显示世界各国
+ */
+export function showWorld() {
+  removeLayer()
+
+  map.setCameraView({ lat: 22.564341, lng: 89.44688, alt: 10817167, heading: 0, pitch: -87 })
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "国界线",
+    url: "https://data.mars3d.cn/file/geojson/world.json",
+    symbol: {
+      type: "polygonP",
+      styleOptions: {
+        fill: true,
+        // color: '#ffffff',
+        // opacity: 0.01,
+        randomColor: true,
+        opacity: 0.5,
+
+        // 高亮时的样式
+        highlight: {
+          type: "click",
+          color: "#ffff00"
+        }
+      },
+      styleField: "name",
+      styleFieldOptions: {
+        Russia: { clampToGround: true }
+      }
+    },
+    popup: "{name} {name_cn}"
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+  graphicLayer.on(mars3d.EventType.click, function (event) {
+    console.log("单击了图层", event)
+  })
+}
+
+// 加载GCJ数据进行纠偏
+export function showGCJ02Data() {
+  removeLayer()
+
+  const gcjLayer = new mars3d.layer.GeoJsonLayer({
+    name: "纠偏前",
+    url: "https://data.mars3d.cn/file/geojson/areas/340303.json",
+    symbol: {
+      styleOptions: {
+        fill: false,
+        outline: true,
+        outlineStyle: {
+          color: "#FF0000",
+          width: 3
+        }
+      }
+    },
+    popup: "纠偏前GCJ02坐标"
+  })
+  map.addLayer(gcjLayer)
+
+  graphicLayer = new mars3d.layer.GeoJsonLayer({
+    name: "纠偏后",
+    url: "https://data.mars3d.cn/file/geojson/areas/340303.json",
+    chinaCRS: mars3d.ChinaCRS.GCJ02, // 标识数据坐标,内部会纠偏
+    symbol: {
+      styleOptions: {
+        fill: false,
+        outline: true,
+        outlineStyle: {
+          color: "#00ffff",
+          width: 3
+        }
+      }
+    },
+    popup: "纠偏后WGS坐标",
+    flyTo: true
+  })
+  map.addLayer(graphicLayer)
+
+  // 绑定事件
+  graphicLayer.on(mars3d.EventType.load, function (event) {
+    console.log("数据加载完成", event)
+    eventTarget.fire("refTree")
+  })
+}
+
+export function getGraphicsTree(options) {
+  return graphicLayer.getGraphicsTree(options)
+}
+
+export function getGraphicById(id) {
+  return graphicLayer.getGraphicById(id)
+}