DESKTOP-CRQ4N2U\jintian 1 year ago
parent
commit
9b70e2e5c4

+ 12 - 6
src/components/CrMap.vue

@@ -1812,8 +1812,9 @@
 					count: 5,
 					duration: 3000
 				});
-				CircleObject.then(function(entity, flyEntity) {
-					debugger
+				CircleObject.then(function(entity) {
+					crMap._viewer.entities.add(entity);
+
 					let options = {};
 					// 初始化参数默认值
 					options.duration = Cesium.defaultValue(options.duration, 2);
@@ -1821,10 +1822,15 @@
 					options.pitch = Cesium.defaultValue(options.pitch, -60);
 					options.range = Cesium.defaultValue(options.range, 1000);
 
-					let flyToEntity = crMap.LocateUtil.flyToEntity(entity, options);
-					flyToEntity.then(function(entity11) {
-						// alert(1111)
-					});
+					crMap._viewer.flyTo(entity).then(function(entity) {
+							debugger
+						});
+
+
+					// let flyToEntity = crMap.LocateUtil.flyToEntity(entity, options);
+					// flyToEntity.then(function(entity11) {
+					// 	// alert(1111)
+					// });
 				});
 
 			},

+ 143 - 0
src/components/Heatmap.vue

@@ -0,0 +1,143 @@
+<template>
+  <div id="cesiumContainer">
+    <div class="canvas-main">
+      <el-button size="mini" @click="startDraw" :disabled="bool"
+        >开始绘制</el-button
+      >
+      <el-button size="mini" @click="autoUpdate" :disabled="!bool"
+        >自动更新</el-button
+      >
+    </div>
+  </div>
+</template>
+<script>
+import HeatmapIntensity from "./HeatmapIntensity";
+const Cesium = window.Cesium;
+let viewer = undefined;
+export default {
+  data() {
+    return {
+      mapData: [],
+      bool: false,
+    };
+  },
+  mounted() {
+    let key =
+      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwZDhhOThhNy0zMzUzLTRiZDktYWM3Ni00NGI5MGY2N2UwZDUiLCJpZCI6MjQzMjYsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODUwMzUwNDh9.DYuDF_RPKe5_8w849_y-sutM68LM51O9o3bTt_3rF1w";
+    Cesium.Ion.defaultAccessToken = key;
+    window.viewer = viewer = new Cesium.Viewer("cesiumContainer", {
+      imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
+        url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
+      }),
+      terrainProvider: Cesium.createWorldTerrain(),
+      geocoder: true,
+      homeButton: true,
+      sceneModePicker: true,
+      baseLayerPicker: true,
+      navigationHelpButton: true,
+      animation: true,
+      timeline: true,
+      fullscreenButton: true,
+      vrButton: true,
+      //关闭点选出现的提示框
+      selectionIndicator: true,
+      infoBox: true,
+    });
+    viewer._cesiumWidget._creditContainer.style.display = "none"; // 隐藏版权
+    this.initData();
+  },
+  methods: {
+    startDraw() {
+      const option = {
+        min: 0,
+        max: 100,
+        size: 20,
+      };
+      window.heatmapObj = new HeatmapIntensity(viewer, option);
+      const box = {
+        west: 110,
+        south: 40.5,
+        east: 110.5,
+        north: 41,
+      };
+      window.heatmapObj.createHeatmap(box, this.mapData);
+      this.bool = true;
+    },
+    autoUpdate() {
+      setInterval(() => {
+        let data = [];
+        for (let i = 0; i < 100; i++) {
+          let obj = {};
+          obj.x = this.randomNum(110, 110.5, 5);
+          obj.y = this.randomNum(40.5, 41, 5);
+          obj.value = this.randomNum(0, 100, 2);
+          data.push(obj);
+        }
+        window.heatmapObj.setData(data);
+      }, 1000);
+    },
+    initData() {
+      this.mapData = [];
+      for (let i = 0; i < 100; i++) {
+        let obj = {};
+        obj.x = this.randomNum(110, 110.5, 5);
+        obj.y = this.randomNum(40.5, 41, 5);
+        obj.value = this.randomNum(0, 100, 2);
+        this.mapData.push(obj);
+      }
+      this.mapData.forEach((element) => {
+        viewer.entities.add({
+          position: Cesium.Cartesian3.fromDegrees(
+            Number(element.x),
+            Number(element.y)
+          ),
+          point: {
+            pixelSize: 5,
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+          },
+        });
+      });
+      viewer.flyTo(viewer.entities);
+    },
+    randomNum(maxNum, minNum, decimalNum) {
+      // 获取指定范围内的随机数, decimalNum指小数保留多少位
+      let max = 0,
+        min = 0;
+      minNum <= maxNum
+        ? ((min = minNum), (max = maxNum))
+        : ((min = maxNum), (max = minNum));
+      let result = undefined;
+      switch (arguments.length) {
+        case 1:
+          result = Math.floor(Math.random() * (max + 1));
+          break;
+        case 2:
+          result = Math.floor(Math.random() * (max - min + 1) + min);
+          break;
+        case 3:
+          result = (Math.random() * (max - min) + min).toFixed(decimalNum);
+          break;
+        default:
+          result = Math.random();
+          break;
+      }
+      return result;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+#cesiumContainer {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  background: rgba(255, 0, 0, 0.322);
+  .canvas-main {
+    position: absolute;
+    margin: 10px;
+    padding: 10px;
+    z-index: 10;
+    background: rgba(255, 255, 0, 0.329);
+  }
+}
+</style>

+ 375 - 0
src/components/new_file.js

@@ -0,0 +1,375 @@
+/*
+ * 坡度坡向分析类
+ * @Author: Wang jianLei
+ * @Date: 2022-04-25 20:21:34
+ * @Last Modified by: Wang JianLei
+ * @Last Modified time: 2022-04-28 21:31:24
+ */
+import CreatePolygonOnGround from "./lib/CreatePolygonOnGround";
+import CreateRemindertip from "./lib/ReminderTip";
+import * as turf from "@turf/turf";
+const Cesium = window.Cesium;
+class SlopeAspect {
+  constructor(viewer) {
+    if (!viewer) throw new Error("no viewer object!");
+    this.viewer = viewer;
+    this.result = []; //存储创建的坡度分析结果,primitive集合
+    this.handler = undefined;
+    this.toolTip = "";
+  }
+  openTip() {
+    const $this = this;
+    const viewer = this.viewer;
+    this.handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
+    this.handler.setInputAction(function (movement) {
+      let endPos = movement.endPosition;
+      var pick = viewer.scene.pick(endPos);
+      if (pick && pick.id && pick.id.type === "SlopeAspect") {
+        $this.toolTip = pick.id.value.toFixed(2);
+        CreateRemindertip($this.toolTip, endPos, true);
+      } else {
+        $this.toolTip = "";
+        CreateRemindertip($this.toolTip, endPos, false);
+      }
+    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
+  }
+  closeTip() {
+    if (this.handler) {
+      this.handler.destroy();
+      this.handler = undefined;
+    }
+  }
+  //等距离切分网格
+  createNew4Distance(distance) {
+    distance = distance || 0.1; //默认0.1km精度
+    let width = distance * 200 > 35 ? 35 : distance * 200;
+    this.arrowWidth = width < 15 ? 15 : width;
+    const $this = this;
+    const viewer = this.viewer;
+    CreatePolygonOnGround(
+      viewer,
+      [],
+      {
+        color: Cesium.Color.RED.withAlpha(0.1),
+        outlineColor: Cesium.Color.YELLOW,
+        outlineWidth: 2,
+      },
+      function (polygon) {
+        let degrees = $this.Cartesian3ListToWGS84(polygon.pottingPoint);
+        viewer.entities.remove(polygon);
+        let boundary = [];
+        let minX = 10000,
+          minY = 10000,
+          maxX = -10000,
+          maxY = -1000;
+        for (let index = 0; index < degrees.length; index++) {
+          const element = degrees[index];
+          const x = element.lng;
+          const y = element.lat;
+          boundary.push([x, y]);
+          minX = x < minX ? x : minX;
+          minY = y < minY ? y : minY;
+          maxX = x > maxX ? x : maxX;
+          maxY = y > maxY ? y : maxY;
+        }
+        boundary.push(boundary[0]);
+        let bbox = [minX, minY, maxX, maxY];
+        let mask = turf.polygon([boundary]);
+        let gridSquare = turf.squareGrid(bbox, distance, { mask: mask });
+        $this.createEllipse(gridSquare);
+      }
+    );
+  }
+  // 等分切分网格,切分成一个num*num的网格
+  createNew4Num(num) {
+    const $this = this;
+    const viewer = this.viewer;
+    CreatePolygonOnGround(
+      viewer,
+      [],
+      {
+        color: Cesium.Color.RED.withAlpha(0.1),
+        outlineColor: Cesium.Color.YELLOW,
+        outlineWidth: 2,
+      },
+      function (polygon) {
+        let degrees = $this.Cartesian3ListToWGS84(polygon.pottingPoint);
+        viewer.entities.remove(polygon);
+        let boundary = [];
+        let minX = 10000,
+          minY = 10000,
+          maxX = -10000,
+          maxY = -1000;
+        for (let index = 0; index < degrees.length; index++) {
+          const element = degrees[index];
+          const x = element.lng;
+          const y = element.lat;
+          boundary.push([x, y]);
+          minX = x < minX ? x : minX;
+          minY = y < minY ? y : minY;
+          maxX = x > maxX ? x : maxX;
+          maxY = y > maxY ? y : maxY;
+        }
+        boundary.push(boundary[0]);
+        let bbox = [minX, minY, maxX, maxY];
+        let a = maxX - minX;
+        let b = maxY - minY;
+        b = b > a ? b : a;
+        const step = b / num;
+        let width = step * 2000 > 35 ? 35 : step * 2000;
+        $this.arrowWidth = width < 15 ? 15 : width;
+        let mask = turf.polygon([boundary]);
+        let gridSquare = turf.squareGrid(bbox, step, {
+          units: "degrees",
+          mask: mask,
+        });
+        $this.createEllipse(gridSquare);
+      }
+    );
+  }
+  createEllipse(gridSquare) {
+    let boxResults = [];
+    for (let index = 0; index < gridSquare.features.length; index++) {
+      const feature = gridSquare.features[index];
+      const coordinates = feature.geometry.coordinates[0];
+      const centerdegree = [
+        (coordinates[0][0] + coordinates[2][0]) / 2,
+        (coordinates[0][1] + coordinates[2][1]) / 2,
+      ];
+      let centerCartographic = Cesium.Cartographic.fromDegrees(
+        centerdegree[0],
+        centerdegree[1]
+      );
+      boxResults.push(centerCartographic);
+      for (let i = 0; i < coordinates.length; i++) {
+        const coord = coordinates[i];
+        let cartographic = Cesium.Cartographic.fromDegrees(coord[0], coord[1]);
+        boxResults.push(cartographic);
+        const coord1 = coordinates[i + 1];
+        if (coord1) {
+          let newCoord = [
+            (coord[0] + coord1[0]) / 2,
+            (coord[1] + coord1[1]) / 2,
+          ];
+          let newCartographic = Cesium.Cartographic.fromDegrees(
+            newCoord[0],
+            newCoord[1]
+          );
+          boxResults.push(newCartographic);
+        }
+      }
+    }
+    Cesium.sampleTerrainMostDetailed(
+      this.viewer.scene.terrainProvider,
+      boxResults
+    ).then((updatePositions) => {
+      let arrr = [];
+      let ellipseResults = updatePositions.reduce(function (
+        pre,
+        item,
+        index,
+        updatePositions
+      ) {
+        var begin = index * 10;
+        var end = begin + 10;
+        var res = updatePositions.slice(begin, end);
+        if (res.length != 0) {
+          arrr[index] = res;
+        }
+        return arrr;
+      },
+      []);
+      this.calculateSlope(ellipseResults);
+    });
+  }
+ 
+  createPolygonInsrance(points, color) {
+    let positions = [];
+    for (let index = 1; index < points.length - 1; index++) {
+      const element = points[index];
+      positions.push(Cesium.Cartographic.toCartesian(element));
+    }
+    let polygon = new Cesium.PolygonGeometry({
+      polygonHierarchy: new Cesium.PolygonHierarchy(positions),
+    });
+ 
+    let polygonInstance = new Cesium.GeometryInstance({
+      geometry: polygon,
+      attributes: {
+        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
+          Cesium.Color.fromCssColorString(color)
+        ),
+        show: new Cesium.ShowGeometryInstanceAttribute(true), //显示或者隐藏
+      },
+    });
+    return polygonInstance;
+  }
+  createArrowInstance(
+    targetPoint,
+    center,
+    diagonalPoint,
+    heightDifference,
+    curSlope
+  ) {
+    let cartographic_0 = new Cesium.Cartographic(
+      (targetPoint.longitude + center.longitude) / 2,
+      (targetPoint.latitude + center.latitude) / 2,
+      (targetPoint.height + center.height) / 2
+    );
+    let cartographic_1 = new Cesium.Cartographic(
+      (diagonalPoint.longitude + center.longitude) / 2,
+      (diagonalPoint.latitude + center.latitude) / 2,
+      (diagonalPoint.height + center.height) / 2
+    );
+    //偏移的
+    let positions1 =
+      heightDifference > 0
+        ? [
+            Cesium.Cartographic.toCartesian(cartographic_0),
+            Cesium.Cartographic.toCartesian(cartographic_1),
+          ]
+        : [
+            Cesium.Cartographic.toCartesian(cartographic_1),
+            Cesium.Cartographic.toCartesian(cartographic_0),
+          ];
+    //箭头线
+    const instance = new Cesium.GeometryInstance({
+      id: {
+        type: "SlopeAspect",
+        value: curSlope,
+      },
+      geometry: new Cesium.GroundPolylineGeometry({
+        positions: positions1,
+        width: this.arrowWidth,
+      }),
+      attributes: {
+        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
+          Cesium.Color.BLUE.withAlpha(0.6)
+        ),
+        show: new Cesium.ShowGeometryInstanceAttribute(true), //显示或者隐藏
+      },
+    });
+    return instance;
+  }
+  calculateSlope(ellipseResults) {
+    let instances = [];
+    let polygonInstance = [];
+    for (let index = 0; index < ellipseResults.length; index++) {
+      const ellipse = ellipseResults[index];
+ 
+      const center = ellipse[0];
+      let heightDifference = 0;
+      let maxIndex = 0;
+      for (let i = 1; i < ellipse.length - 1; i++) {
+        const point = ellipse[i];
+        let curHD = point.height - center.height;
+        if (Math.abs(curHD) > heightDifference) {
+          heightDifference = curHD;
+          maxIndex = i;
+        }
+      }
+      let pos0 = new Cesium.Cartographic(center.longitude, center.latitude, 0);
+      let pos1 = new Cesium.Cartographic(
+        ellipse[maxIndex].longitude,
+        ellipse[maxIndex].latitude,
+        0
+      );
+      let distance = Cesium.Cartesian3.distance(
+        Cesium.Cartographic.toCartesian(pos0),
+        Cesium.Cartographic.toCartesian(pos1)
+      );
+      let curSlope = Math.abs(heightDifference / distance); //坡度的tan值
+      let curColor = this.calculateSlopeColor(curSlope, 0.4);
+      const curPolygonInstance = this.createPolygonInsrance(ellipse, curColor);
+      polygonInstance.push(curPolygonInstance);
+ 
+      let diagonalPoint =
+        maxIndex > 4 ? ellipse[maxIndex - 4] : ellipse[maxIndex + 4]; //对角点
+      let targetPoint = ellipse[maxIndex];
+      const arrowInstance = this.createArrowInstance(
+        targetPoint,
+        center,
+        diagonalPoint,
+        heightDifference,
+        curSlope
+      );
+      instances.push(arrowInstance);
+    }
+    const mapPrimitive = this.viewer.scene.primitives.add(
+      new Cesium.GroundPrimitive({
+        geometryInstances: polygonInstance,
+        appearance: new Cesium.PerInstanceColorAppearance({
+          translucent: true, //false时透明度无效
+          closed: false,
+        }),
+      })
+    );
+    const arrowPrimitive = this.viewer.scene.primitives.add(
+      new Cesium.GroundPolylinePrimitive({
+        geometryInstances: instances,
+        appearance: new Cesium.PolylineMaterialAppearance({
+          material: new Cesium.Material({
+            fabric: {
+              type: "PolylineArrow",
+              uniforms: {
+                color: new Cesium.Color(1.0, 1.0, 0.0, 0.8),
+              },
+            },
+          }),
+        }),
+      })
+    );
+    this.result.push(arrowPrimitive, mapPrimitive);
+  }
+  clearAll() {
+    this.result.forEach((element) => {
+      this.viewer.scene.primitives.remove(element);
+    });
+    this.result = [];
+  }
+  //根据坡度值赋值颜色
+  calculateSlopeColor(value, alpha) {
+    // 0°~0.5°为平原0.00872686779075879,rgb(85,182,43)
+    // 0.5°~2°为微斜坡0.03492076949174773,rgb(135,211,43)
+    // 2°~5°为缓斜坡0.08748866352592401,rgb(204,244,44)
+    // 5°~15°为斜坡0.2679491924311227,rgb(245,233,44)
+    // 15°~35°为陡坡0.7002075382097097,rgb(255,138,43)
+    // 35°~55°为峭坡1.4281480067421144,rgb(255,84,43)
+    // 55°~90°为垂直壁,rgb(255,32,43)
+    if (value < 0.00872686779075879) {
+      return "rgba(85,182,43," + alpha + ")";
+    } else if (value < 0.03492076949174773) {
+      return "rgba(135,211,43," + alpha + ")";
+    } else if (value < 0.08748866352592401) {
+      return "rgba(204,244,44," + alpha + ")";
+    } else if (value < 0.2679491924311227) {
+      return "rgba(245,233,44," + alpha + ")";
+    } else if (value < 0.7002075382097097) {
+      return "rgba(255,138,43," + alpha + ")";
+    } else if (value < 1.4281480067421144) {
+      return "rgba(255,84,43," + alpha + ")";
+    } else {
+      return "rgba(255,32,43," + alpha + ")";
+    }
+  }
+  /**
+   * 笛卡尔坐标数组转WGS84
+   * @param {Array} cartesianList 笛卡尔坐标数组
+   * @returns {Array} WGS84经纬度坐标数组
+   */
+  Cartesian3ListToWGS84(cartesianList) {
+    let ellipsoid = Cesium.Ellipsoid.WGS84;
+    let result = [];
+    for (let index = 0; index < cartesianList.length; index++) {
+      const cartesian = cartesianList[index];
+      let cartographic = ellipsoid.cartesianToCartographic(cartesian);
+      result.push({
+        lng: Cesium.Math.toDegrees(cartographic.longitude),
+        lat: Cesium.Math.toDegrees(cartographic.latitude),
+        alt: cartographic.height,
+      });
+    }
+    return result;
+  }
+}
+export default SlopeAspect;

+ 128 - 0
src/components/terrain-excavation.vue

@@ -0,0 +1,128 @@
+<template>
+  <div id="cesiumContainer">
+    <div class="terrain-excavation-tools">
+      <el-button size="mini" @click="terrainClip(true)">开始创建</el-button>
+      <div style="margin-top: 5px">
+        开挖高度:
+        <el-input-number
+          size="mini"
+          controls-position="right"
+          v-model="height"
+          :step="100"
+          :min="100"
+          :max="3000"
+          @change="heightChange"
+        ></el-input-number>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+const Cesium = window.Cesium;
+let viewer = undefined;
+let terrainClipPlanObj = undefined;
+import TerrainExcavation from "./TerrainExcavation";
+export default {
+  data() {
+    return {
+      height: 200,
+    };
+  },
+  mounted() {
+    let key =
+      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwZDhhOThhNy0zMzUzLTRiZDktYWM3Ni00NGI5MGY2N2UwZDUiLCJpZCI6MjQzMjYsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODUwMzUwNDh9.DYuDF_RPKe5_8w849_y-sutM68LM51O9o3bTt_3rF1w";
+    Cesium.Ion.defaultAccessToken = key;
+    window.viewer = viewer = new Cesium.Viewer("cesiumContainer", {
+      imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
+        url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
+      }),
+      terrainProvider: Cesium.createWorldTerrain(),
+      geocoder: true,
+      homeButton: true,
+      sceneModePicker: true,
+      baseLayerPicker: true,
+      navigationHelpButton: true,
+      animation: true,
+      timeline: true,
+      fullscreenButton: true,
+      vrButton: true,
+      //关闭点选出现的提示框
+      selectionIndicator: false,
+      infoBox: false,
+    });
+    viewer._cesiumWidget._creditContainer.style.display = "none"; // 隐藏版权
+    this.initCamera();
+  },
+  methods: {
+    heightChange(val) {
+      if (terrainClipPlanObj) {
+        terrainClipPlanObj.height = val;
+      }
+    },
+    terrainClip(bool) {
+      if (!terrainClipPlanObj) {
+        terrainClipPlanObj = new TerrainExcavation(window.viewer, {
+          height: this.height,
+          splitNum: 1000,
+          bottomImg: require("./images/terrain-clip-bottom.jpeg"),
+          wallImg: require("./images/terrain-clip-aside.jpeg"),
+        });
+      }
+      if (bool) {
+        console.log("开始地形开挖");
+        terrainClipPlanObj.startCreate();
+      } else {
+        console.log("结束地形开挖");
+        terrainClipPlanObj.clear();
+      }
+    },
+    initCamera() {
+      viewer.camera.flyTo({
+        destination: window.Cesium.Cartesian3.fromDegrees(110, 40, 10000.0),
+        orientation: {
+          heading: 0.09085393067733083,
+          pitch: -1.5329743385768886,
+          roll: 0.0,
+        },
+        duration: 3,
+      });
+    },
+    getLocation() {
+      let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
+      handler.setInputAction(function (event) {
+        let earthPosition = viewer.scene.pickPosition(event.position);
+        if (Cesium.defined(earthPosition)) {
+          let cartographic = Cesium.Cartographic.fromCartesian(earthPosition);
+          let lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(5);
+          let lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(5);
+          let height = cartographic.height.toFixed(2);
+          console.log(earthPosition, {
+            lon: lon,
+            lat: lat,
+            height: height,
+          });
+        }
+      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+#cesiumContainer {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  .terrain-excavation-tools {
+    position: absolute;
+    margin: 10px;
+    padding: 10px;
+    z-index: 10;
+    display: flex;
+    flex-direction: column;
+    border: 1px solid rgb(24, 24, 24);
+    background-color: rgba(67, 68, 68, 0.7);
+    border-radius: 5px;
+    color: white;
+  }
+}
+</style>

+ 143 - 0
src/components/underground.vue

@@ -0,0 +1,143 @@
+<template>
+  <div id="cesiumContainer">
+    <div class="underground-tools">
+      <el-switch
+        v-model="boolUnderground"
+        active-text="地下模式已开启"
+        inactive-text="地下模式已关闭"
+      >
+      </el-switch>
+      <div class="alpha-control">
+        <span>透明度:</span>
+        <el-slider
+          v-model="alpha"
+          :min="0"
+          :max="1"
+          :step="0.1"
+          :disabled="!boolUnderground"
+        >
+        </el-slider>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+const Cesium = window.Cesium;
+let viewer = undefined;
+export default {
+  watch: {
+    alpha(val) {
+      console.log("透明度变化了", val);
+      if (this.boolUnderground) {
+        this.setAlpha(val);
+      }
+    },
+    boolUnderground(val) {
+      console.log("地下模式变化了", val);
+ 
+      this.setUnderground(val);
+    },
+  },
+  data() {
+    return {
+      alpha: 0.5,
+      boolUnderground: false,
+    };
+  },
+  mounted() {
+    let key =
+      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwZDhhOThhNy0zMzUzLTRiZDktYWM3Ni00NGI5MGY2N2UwZDUiLCJpZCI6MjQzMjYsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODUwMzUwNDh9.DYuDF_RPKe5_8w849_y-sutM68LM51O9o3bTt_3rF1w";
+    Cesium.Ion.defaultAccessToken = key;
+    window.viewer = viewer = new Cesium.Viewer("cesiumContainer", {
+      imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
+        url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
+      }),
+      terrainProvider: Cesium.createWorldTerrain(),
+      geocoder: true,
+      homeButton: true,
+      sceneModePicker: true,
+      baseLayerPicker: true,
+      navigationHelpButton: true,
+      animation: true,
+      timeline: true,
+      fullscreenButton: true,
+      vrButton: true,
+      //关闭点选出现的提示框
+      selectionIndicator: false,
+      infoBox: false,
+    });
+    viewer._cesiumWidget._creditContainer.style.display = "none"; // 隐藏版权
+    this.initModel();
+    this.getLocation();
+  },
+  methods: {
+    initModel() {
+      const position = Cesium.Cartesian3.fromDegrees(119.5, 35.5, 20);
+      const model = viewer.entities.add({
+        name: "地铁站",
+        position: position,
+        model: {
+          uri: `${window.location.origin}/data/model/metro_station/scene.gltf`,
+        },
+      });
+      viewer.flyTo(model);
+    },
+    // 设置地表透明度
+    setAlpha(alpha) {
+      const frontFaceAlphaByDistance =
+        viewer.scene.globe.translucency.frontFaceAlphaByDistance;
+      frontFaceAlphaByDistance.nearValue = alpha;
+      frontFaceAlphaByDistance.farValue = alpha;
+    },
+    //是否开启地下模式
+    setUnderground(bool) {
+      viewer.scene.screenSpaceCameraController.enableCollisionDetection = !bool; //相机与地形的碰撞检测
+      viewer.scene.globe.translucency.frontFaceAlphaByDistance =
+        new Cesium.NearFarScalar(1.5e2, 0.5, 8.0e6, 1.0);
+      viewer.scene.globe.translucency.enabled = bool; //是否开启透明
+      this.setAlpha(this.alpha);
+    },
+    getLocation() {
+      let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
+      handler.setInputAction(function (event) {
+        let earthPosition = viewer.scene.pickPosition(event.position);
+        if (Cesium.defined(earthPosition)) {
+          let cartographic = Cesium.Cartographic.fromCartesian(earthPosition);
+          let lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(5);
+          let lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(5);
+          let height = cartographic.height.toFixed(2);
+          console.log(earthPosition, {
+            lon: lon,
+            lat: lat,
+            height: height,
+          });
+        }
+      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+#cesiumContainer {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  .underground-tools {
+    position: absolute;
+    z-index: 10;
+    margin: 10px;
+    padding: 10px;
+    border: 1px solid rgb(32, 32, 32);
+    background-color: rgba(99, 100, 100, 0.8);
+    border-radius: 5px;
+    .alpha-control {
+      display: flex;
+      align-items: center;
+      color: white;
+      .el-slider {
+        width: 75%;
+      }
+    }
+  }
+}
+</style>

+ 2 - 2
src/jtMap3d/Widgets/CircleObject.js

@@ -149,9 +149,9 @@ Object.assign(CircleObject.prototype, /** @lends CircleObject.prototype */ {
 				}
 			});
 
-			let flyEntity = viewer.entities.add(entity);
+			// let flyEntity = viewer.entities.add(entity);
 
-			resolve(entity, flyEntity)
+			resolve(entity)
 
 		});
 	},

+ 573 - 0
src/jtMap3d/Widgets/Roaming/Roaming - 副本.js

@@ -0,0 +1,573 @@
+/*
+ * @Description: 漫游
+ * @Version: 1.0
+ * @Author: joy
+ * @Date: 2023-04-12 21:42:26
+ * @LastEditors: joy
+ * @LastEditTime: 2023-04-13 16:32:25
+ */
+export default class Roaming {
+	/**
+	 * 创建一个漫游实例
+	 * @param {Object} viewer 三维场景viewer对象
+	 * @param {Array<Cesium.Cartesian3>/Array<[lng,lat,height]>} positions 坐标串,点集合
+	 * @param {Object} options 具有以下属性:
+	 * @param {Number} options.time 漫游时间
+	 * @param {Number} options.speed 速度
+	 * @param {Number} options.followedX 距离运动点的距离(后方) 
+	 * @param {Number} options.followedZ 距离运动点的高度(上方)
+	 * @param {Number} options.height 高度差
+	 * @param {Number} options.role 0自由模式 1跟随模式 2第一视角 3上帝视角
+	 * 第一人称摄像头放置在主角的前面
+	 * 第三人称摄像头放置在主角的背后
+	 * 
+	 * @param {Object} [options.model] model的样式,具有以下属性:
+	 * @param {Number} [options.model.url] 模型的url
+	 * 
+	 * @param {Object} [options.billboard] 广告牌的样式,具有以下属性:
+	 * @param {Number} [options.billboard.imgUrl] 广告牌图片
+	 * @param {Number} [options.billboard.scale=1] 尺寸
+	 * @param {Object} [options.billboard.scaleByDistance] 距离相机的距离缩放点。
+	 * @param {Number} [options.billboard.scaleByDistance.near=0] 相机范围的下界。
+	 * @param {String} [options.billboard.scaleByDistance.nearValue=0] 相机范围下界的值。
+	 * @param {String} [options.billboard.scaleByDistance.far=1] 相机范围的上限。
+	 * @param {Number} [options.billboard.scaleByDistance.farValue=0] 该值位于摄像机范围的上界。
+	 * 
+	 * @param {Object} [options.point] point的样式,具有以下属性:
+	 * @param {Number} [options.point.pixelSize=10] 指定点的大小,以像素为单位
+	 * @param {Array} [options.point.color=[255,255,255,0]] 点位颜色,颜色数组,[0~255,0~255,0~255,0~1],[red 红色,green 绿色,blue 蓝色,alpha 透明度]
+	 * @param {String} [options.point.outlineColor=[255,255,255,0]] 指定点轮廓的颜色,,颜色数组,[0~255,0~255,0~255,0~1],[red 红色,green 绿色,blue 蓝色,alpha 透明,
+	 * @param {Number} [options.point.outlineWidth=0] 指定点轮廓的宽度
+	 * 
+	 * @param {Object} [options.label] label的样式,具有以下属性:
+	 * @param {Number} [options.label.text=""] 文字
+	 * @param {String} [options.label.font="24px Helvetica"] 字体样式
+	 * @param {String} [options.label.fillColor=[255,255,255,0]] 字体颜色
+	 * @param {String} [options.label.outlineColor=[255,255,255,0]] 字体边框颜色
+	 * @param {Number} [options.label.outlineWidth=1] 边框宽度	
+	 * @param {Number} [options.label.showBackground=false] 是否显示背景颜色	
+	 * @param {Number} [options.label.backgroundColor=[255,255,255,0]] 背景颜色		
+	 * @param {Number} [options.label.pixelOffset] 偏移像素
+	 * @param {Number} [options.label.pixelOffset.x=0] 横向偏移像素
+	 * @param {Number} [options.label.pixelOffset.y=0] 纵向偏移像素
+	 * @param {Number} [options.label.scale=1] 尺寸
+	 * @param {Number} [options.label.scaleByDistance] 相机范围
+	 * @param {Number} [options.label.scaleByDistance.near=1.5e2] 相机范围的下界。
+	 * @param {String} [options.label.scaleByDistance.nearValue=1] 相机范围下界的值。
+	 * @param {String} [options.label.scaleByDistance.far=2400] 相机范围的上限。
+	 * @param {Number} [options.label.scaleByDistance.farValue=0] 该值位于摄像机范围的上界。
+	 * @memberof Roaming
+	 */
+	constructor(viewer, positions, options) {
+		if (!viewer) throw new Cesium.DeveloperError('no viewer object!');
+		if (!positions) throw new Cesium.DeveloperError('no positions Array!');
+
+		this.viewer = viewer;
+		this.entity = undefined;
+
+		options = options || {};
+		options.time = Cesium.defaultValue(options.time, 360);
+		options.speed = Cesium.defaultValue(options.speed, 10);
+		options.isPathShow = Cesium.defaultValue(options.isPathShow, true);
+		options.height = Cesium.defaultValue(options.height, 5);
+		options.role = Cesium.defaultValue(options.role, 1);
+		options.followedX = Cesium.defaultValue(options.followedX, 50);
+		options.followedZ = Cesium.defaultValue(options.followedZ, 10);
+
+		this.time = options.time;
+		this.speed = options.speed;
+		this.isPathShow = options.isPathShow;
+		this.height = options.height;
+		this.role = options.role;
+		this.followedX = options.followedX;
+		this.followedZ = options.followedZ;
+
+		this.model = options.model;
+		this.billboard = options.billboard;
+		this.point = options.point;
+		this.label = options.label;
+
+		this.property = this.ComputeRoamingLineProperty(positions, this.time);
+	}
+
+	/**
+	 * @ignore
+	 * @param {*} Lines 点集合
+	 * @param {*} time 漫游时间
+	 * @returns
+	 * @memberof Roaming
+	 */
+	ComputeRoamingLineProperty(Lines, time) {
+		let _self = this;
+
+		let positions = [];
+		if (Lines[0] instanceof Cesium.Cartesian3) {
+			positions = Lines;
+		} else {
+			positions = Lines.map(point => {
+				return Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2] || 0);
+			});
+		}
+
+		//总距离
+		let distance = [];
+		for (let i = 0; i < positions.length - 1; i++) {
+			let dis = Cesium.Cartesian3.distance(positions[i], positions[i + 1])
+			distance.push(dis)
+		}
+
+		//点与点之间间隔时间
+		let times = [Cesium.JulianDate.fromDate(new Date())]
+		times.push(Cesium.JulianDate.addSeconds(times[0], time, new Cesium.JulianDate()))
+		for (let i = 1; i < positions.length - 1; i++) {
+			let s = Cesium.JulianDate.addSeconds(times[i], time * (distance[i] / distance[0]), new Cesium.JulianDate())
+			times.push(s)
+		}
+
+		//一种属性,其值在给定时间内从提供的样本集和指定的插值算法和插值度中插值。
+		let oriSamples = new Cesium.SampledProperty(Cesium.Cartesian3);
+		oriSamples.addSamples(times, positions);
+
+		let startTime = times[0]; // 起始时间
+		let stopTime = times[times.length - 1]; // 结束时间
+		this.viewer.clock.startTime = startTime.clone(); // 设置始时钟始时间
+		this.viewer.clock.stopTime = stopTime.clone(); // 设置始终停止时间
+		this.viewer.clock.currentTime = startTime.clone(); // 设置时钟当前时间
+		this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //循环执行
+		this.viewer.clock.multiplier = this.speed; // 时间速率,数字越大时间过的越快
+
+		// 计算提供的实例之间的天数差。
+		let timeOfResolution = 6;
+		let samplesNum = Math.floor(
+			Cesium.JulianDate.secondsDifference(stopTime, startTime) / timeOfResolution
+		);
+
+		let sampledPositions = [];
+		let sampledTimes = [];
+		for (let i = 0; i < samplesNum + 1; i++) {
+			let sampleTime = Cesium.JulianDate.addSeconds(
+				startTime,
+				i * timeOfResolution,
+				new Cesium.JulianDate()
+			);
+			let tmpPos = oriSamples.getValue(sampleTime);
+			sampledPositions.push(Cesium.Cartographic.fromCartesian(tmpPos));
+			sampledTimes.push(sampleTime);
+		}
+
+		let promise = Cesium.sampleTerrainMostDetailed(
+			this.viewer.terrainProvider,
+			sampledPositions
+		).then(updatedPositions => {
+
+			let carPositionProperty = new Cesium.SampledPositionProperty();
+
+			//高度
+			for (let i = 0; i < sampledPositions.length; i++) {
+				sampledPositions[i].height = sampledPositions[i].height + this.height
+			}
+
+			for (let i = 0; i < samplesNum + 1; i++) {
+				carPositionProperty.addSample(
+					sampledTimes[i],
+					Cesium.Ellipsoid.WGS84.cartographicToCartesian(sampledPositions[i])
+				);
+			}
+
+			var position = carPositionProperty;
+			this.InitRoaming(position, startTime, stopTime, this.isPathShow)
+		});
+	}
+
+	/**
+	 * @ignore
+	 * @param {*} position computeRoamingLineProperty计算的属性
+	 * @param {*} start 开始时间节点
+	 * @param {*} stop 结束时间节点
+	 * @param {*} isPathShow path路径是否显示
+	 * @memberof Roaming
+	 */
+	InitRoaming(position, start, stop, isPathShow) {
+		let _self = this;
+		this.entity = this.viewer.entities.add({
+			// 和时间轴关联
+			availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
+				start: start,
+				stop: stop
+			})]),
+			// 位置
+			position: position,
+			//基于位置移动自动计算方向.
+			orientation: new Cesium.VelocityOrientationProperty(position),
+			//路径
+			path: {
+				resolution: 1,
+				//设置航线样式,线条颜色,内发光粗细,航线宽度等
+				material: new Cesium.PolylineGlowMaterialProperty({
+					glowPower: 0.1,
+					color: Cesium.Color.YELLOW
+				}),
+				width: 10,
+				show: isPathShow
+			}
+		})
+
+		if (this.model) {
+			let model = this.model;
+
+			// 加载模型,	模型数据,跨域,模型文件必须放本地
+			this.entity.model = {
+				// 模型路径
+				uri: model.url,
+				// 模型最小刻度
+				minimumPixelSize: 64,
+				maximumSize: 128,
+				// 设置模型最大放大大小
+				maximumScale: 200,
+				// 模型是否可见
+				show: true,
+				// 模型轮廓颜色
+				silhouetteColor: Cesium.Color.WHITE,
+				// 模型颜色  ,这里可以设置颜色的变化
+				// color: color,
+				// 仅用于调试,显示魔仙绘制时的线框
+				debugWireframe: false,
+				// 仅用于调试。显示模型绘制时的边界球。
+				debugShowBoundingVolume: false,
+
+				scale: 20,
+				runAnimations: true // 是否运行模型中的动画效果
+			};
+		} else if (this.billboard) {
+			let billboard = this.billboard;
+
+			billboard.imgUrl = Cesium.defaultValue(billboard.imgUrl, 'jt3dSDK/imgs/point/point3.png');
+
+			this.entity.billboard = {
+				image: billboard.imgUrl, // default: undefined
+				show: true, // default
+				width: 30, // default: undefined
+				scale: 1,
+				height: 30, // default: undefined
+				pixelOffset: new Cesium.Cartesian2(0, -14), // default: (0, 0)
+				// disableDepthTestDistance: 0,
+			}
+
+		} else {
+			let point = {};
+			if (this.point) {
+				point = this.point;
+			}
+
+			//点的大小
+			point.pixelSize = Cesium.defaultValue(point.pixelSize, 10);
+			//点位颜色
+			if (point.color) {
+				if (point.color instanceof Array) {
+					point.color = new Cesium.Color(point.color[0] / 255, point.color[1] / 255, point.color[2] / 255, point.color[3]);
+				} else if (typeof(point.color) === 'string') {
+					point.color = new Cesium.Color.fromCssColorString(point.color);
+				} else {
+					point.color = new Cesium.Color.fromCssColorString("#FFFF00");
+				}
+			}
+
+			//点位轮廓颜色
+			if (point.outlineColor) {
+				if (point.outlineColor instanceof Array) {
+					point.outlineColor = new Cesium.Color(point.outlineColor[0] / 255, point.outlineColor[1] / 255, point.outlineColor[2] / 255, point.outlineColor[3]);
+				} else if (typeof(point.outlineColor) === 'string') {
+					point.outlineColor = new Cesium.Color.fromCssColorString(point.outlineColor);
+				} else {
+					point.outlineColor = new Cesium.Color.fromCssColorString("#FFFF00");
+				}
+			}
+
+			//点位轮廓宽度
+			point.outlineWidth = Cesium.defaultValue(point.outlineWidth, 2);
+
+			this.entity.point = point
+		}
+
+		/* 判断是否需要绘制文字 */
+		if (this.label) {
+
+			let label = this.label;
+
+			label.text = Cesium.defaultValue(label.text, "");
+			label.font = Cesium.defaultValue(label.font, "24px Helvetica"); //字体样式
+
+			//字体颜色
+			if (label.fillColor) {
+				if (label.fillColor instanceof Array) {
+					label.fillColor = new Cesium.Color(label.fillColor[0] / 255, label.fillColor[1] / 255, label.fillColor[2] / 255, label.fillColor[3]);
+				} else if (typeof(label.fillColor) === 'string') {
+					label.fillColor = new Cesium.Color.fromCssColorString(label.fillColor);
+				} else {
+					label.fillColor = new Cesium.Color.fromCssColorString("#FFFF00");
+				}
+			}
+
+			//字体边框颜色
+			if (label.outlineColor) {
+				if (label.outlineColor instanceof Array) {
+					label.outlineColor = new Cesium.Color(label.outlineColor[0] / 255, label.outlineColor[1] / 255, label.outlineColor[2] / 255, label.outlineColor[3]);
+				} else if (typeof(label.outlineColor) === 'string') {
+					label.outlineColor = new Cesium.Color.fromCssColorString(label.outlineColor);
+				} else {
+					label.outlineColor = new Cesium.Color.fromCssColorString("#FFFF00");
+				}
+			}
+
+			//字体边框宽度
+			label.outlineWidth = Cesium.defaultValue(label.outlineWidth, 1);
+
+			//是否显示背景颜色
+			label.showBackground = Cesium.defaultValue(label.showBackground, false);
+			//背景颜色
+			if (label.backgroundColor) {
+				if (label.backgroundColor instanceof Array) {
+					label.backgroundColor = new Cesium.Color(label.backgroundColor[0] / 255, label.backgroundColor[1] / 255, label.backgroundColor[2] / 255, label.backgroundColor[3]);
+				} else if (typeof(label.backgroundColor) === 'string') {
+					label.backgroundColor = new Cesium.Color.fromCssColorString(label.backgroundColor);
+				} else {
+					label.backgroundColor = new Cesium.Color.fromCssColorString("#FFFF00");
+				}
+			}
+
+			label.pixelOffset = Cesium.defaultValue(label.pixelOffset, 0);
+			label.scale = Cesium.defaultValue(label.scale, 1);
+
+
+			this.entity.label = {
+				text: label.text,
+				font: label.font, //字体样式
+				fillColor: label.fillColor, //字体颜色
+				outlineColor: label.outlineColor, //字体边框颜色
+				outlineWidth: label.outlineWidth, //边框宽度	
+				style: Cesium.LabelStyle.FILL_AND_OUTLINE, //FILL不要轮廓 , OUTLINE只要轮廓,FILL_AND_OUTLINE轮廓加填充
+
+				verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+				showBackground: label.showBackground, //是否显示背景颜色
+				backgroundColor: label.backgroundColor, // 背景颜色
+				backgroundPadding: new Cesium.Cartesian2(6, 6), //指定以像素为单位的水平和垂直背景填充padding
+				disableDepthTestDistance: Number.POSITIVE_INFINITY,
+
+				scale: label.scale, //尺寸
+
+			}
+
+			//偏移量
+			if (label.pixelOffset) {
+				label.pixelOffset.x = Cesium.defaultValue(label.pixelOffset.x, 0);
+				label.pixelOffset.y = Cesium.defaultValue(label.pixelOffset.y, 0);
+				this.entity.label.pixelOffset = new Cesium.Cartesian2(label.pixelOffset.x, label.pixelOffset.y);
+			}
+
+			if (label.scaleByDistance) {
+				label.scaleByDistance.near = Cesium.defaultValue(label.scaleByDistance.near, 0);
+				label.scaleByDistance.nearValue = Cesium.defaultValue(label.scaleByDistance.nearValue, 0);
+				label.scaleByDistance.far = Cesium.defaultValue(label.scaleByDistance.far, 1);
+				label.scaleByDistance.farValue = Cesium.defaultValue(label.scaleByDistance.farValue, 0);
+
+				this.entity.label.scaleByDistance = new Cesium.NearFarScalar(label.scaleByDistance.near, label.scaleByDistance.nearValue, label.scaleByDistance.far, label.scaleByDistance.farValue) //按距离缩放,即距离大于180米时,图标不显示  Cesium.NearFarScalar(near, nearValue, far, farValue)相机范围的下界。相机范围下界的值。相机范围的上限。该值位于摄像机范围的上界。
+			}
+		}
+
+
+		this.entity.position.setInterpolationOptions({ // 点插值
+			interpolationDegree: 5,
+			interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
+		})
+
+		this.initRole(this.role);
+	}
+
+	/**
+	 * @param {Object} role 0自由模式 1跟随模式 2第一视角 3 第三视角  后方、前方、俯视(上帝视角)、左侧、右侧
+	 */
+	initRole(role) {
+		let _self = this;
+
+		if (role == 0) { //自由模式
+			this.viewer.trackedEntity = undefined;
+
+			//获取被clock监听的全部事件数量
+			let len = _self.viewer.clock.onTick.numberOfListeners;
+			for (let i = 0; i < len; i++) {
+				//将被监听的方法移除来停止方法
+				_self.viewer.clock.onTick.removeEventListener(_self.viewer.clock.onTick._listeners[i]);
+			}
+		} else if (role == 1) { //跟随模式
+
+			this.viewer.trackedEntity = this.entity;
+
+			//获取被clock监听的全部事件数量
+			let len = _self.viewer.clock.onTick.numberOfListeners;
+			for (let i = 0; i < len; i++) {
+				//将被监听的方法移除来停止方法
+				_self.viewer.clock.onTick.removeEventListener(_self.viewer.clock.onTick._listeners[i]);
+			}
+
+		} else if (role == 2) { //第一视角
+
+			this.viewer.trackedEntity = this.entity;
+
+			let exection = function TimeExecution() {
+				if (_self.viewer.clock.shouldAnimate === true) {
+					//获取位置
+					let center = _self.entity.position.getValue(
+						_self.viewer.clock.currentTime
+					);
+					//获取偏向角
+					let orientation = _self.entity.orientation.getValue(
+						_self.viewer.clock.currentTime
+					)
+					let transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
+					transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation), center);
+
+					var transformX = _self.followedX || 50; //距离运动点的距离(后方) 
+					var transformZ = _self.followedZ || 10; //距离运动点的高度(上方)
+
+					_self.viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(transformX, 0, transformZ))
+				}
+			};
+			//监听时间变化 让cesium的时钟方法来监听该方法
+			this.viewer.clock.onTick.addEventListener(exection);
+
+			// //视角变换
+			// var matrix3Scratch = new Cesium.Matrix3();
+
+			// function getModelMatrix(entity, time, result) {
+			// 	var position = Cesium.Property.getValueOrUndefined(entity.position, time, new Cesium.Cartesian3());
+			// 	if (!Cesium.defined(position)) {
+			// 		return undefined;
+			// 	}
+			// 	var orientation = Cesium.Property.getValueOrUndefined(entity.orientation, time, new Cesium.Quaternion());
+			// 	if (!Cesium.defined(orientation)) {
+			// 		result = Cesium.Transforms.eastNorthUpToFixedFrame(position, undefined, result);
+			// 	} else {
+			// 		result = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation, matrix3Scratch),
+			// 			position, result);
+			// 	}
+			// 	return result;
+			// }
+
+			// var scratch = new Cesium.Matrix4();
+			// let renderListener = function(e) {
+			// 	var time = _self.viewer.clock.currentTime.secondsOfDay - _self.viewer.clock.startTime.secondsOfDay;
+
+			// 	getModelMatrix(_self.entity, _self.viewer.clock.currentTime, scratch);
+
+			// 	var transformX = _self.followedX || 50; //距离运动点的距离(后方) 
+			// 	var transformZ = _self.followedZ || 10; //距离运动点的高度(上方)
+			// 	_self.viewer.scene.camera.lookAtTransform(scratch, new Cesium.Cartesian3(-transformX, 0, transformZ));
+			// }
+			// this.viewer.scene.preRender.addEventListener(renderListener);
+
+		} else if (role == 3) { //第三视角  上帝视角
+
+			this.viewer.trackedEntity = this.entity;
+
+			let exection = function TimeExecution() {
+				if (_self.viewer.clock.shouldAnimate === true) {
+					//获取位置
+					// let center = _self.entity.position.getValue(
+					// 	_self.viewer.clock.currentTime
+					// );
+					// // 更新相机位置(上帝视角)
+					// _self.viewer.camera.lookAt(center, new Cesium.Cartesian3(0, 0, 1000))
+
+					let center = _self.entity.position.getValue(
+						_self.viewer.clock.currentTime
+					);
+					let orientation = _self.entity.orientation.getValue(
+						_self.viewer.clock.currentTime
+					)
+					let transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
+					transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation), center);
+
+					var transformX = -50; //距离运动点的距离(后方)
+					var transformZ = 250; //距离运动点的高度(上方)
+
+					_self.viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(transformX, 0, transformZ))
+				}
+			};
+			//监听时间变化 让cesium的时钟方法来监听该方法
+			this.viewer.clock.onTick.addEventListener(exection);
+		}
+	}
+
+	/**
+	 * 漫游的暂停和继续
+	 * @param {Boolean} state bool类型 false为暂停,ture为继续
+	 * @memberof Roaming
+	 */
+	PauseOrContinue(state) {
+		this.viewer.clock.shouldAnimate = state;
+	}
+
+	/**
+	 * 向前飞行
+	 */
+	forwardFly() {
+		// var clockViewModel = this.viewer.clockViewModel;
+		// var multiplier = clockViewModel.multiplier;
+		// if (multiplier < 0) {
+		// 	clockViewModel.multiplier = -multiplier;
+		// }
+		// clockViewModel.shouldAnimate = true;
+
+		var multiplier = this.viewer.clock.multiplier;
+		if (multiplier < 0) {
+			this.viewer.clock.multiplier = -multiplier;
+		}
+		this.viewer.clock.shouldAnimate = true;
+	}
+
+	/**
+	 * 向后飞行
+	 */
+	backwardsFly() {
+		// var clockViewModel = this.viewer.clockViewModel;
+		// var multiplier = clockViewModel.multiplier;
+		// if (multiplier > 0) {
+		// 	clockViewModel.multiplier = -multiplier;
+		// }
+		// clockViewModel.shouldAnimate = true;
+
+		var multiplier = this.viewer.clock.multiplier;
+		if (multiplier > 0) {
+			this.viewer.clock.multiplier = -multiplier;
+		}
+		this.viewer.clock.shouldAnimate = true;
+	}
+
+	/**
+	 * 改变飞行的速度
+	 * @param {Number} value  整数类型
+	 * @memberof Roaming
+	 */
+	ChangeRoamingSpeed(value) {
+		this.viewer.clock.multiplier = value;
+	}
+
+	/**
+	 * 取消漫游
+	 * @memberof Roaming
+	 */
+	EndRoaming() {
+		if (this.entity !== undefined) {
+			this.viewer.entities.remove(this.entity);
+		}
+		this.viewer.trackedEntity = undefined;
+		this.viewer.clock.shouldAnimate = false;
+
+		//获取被clock监听的全部事件数量
+		let len = this.viewer.clock.onTick.numberOfListeners;
+		for (let i = 0; i < len; i++) {
+			//将被监听的方法移除来停止方法
+			this.viewer.clock.onTick.removeEventListener(this.viewer.clock.onTick._listeners[i]);
+		}
+	}
+}

+ 1 - 1
src/jtMap3d/Widgets/layer.js

@@ -1364,7 +1364,7 @@ Object.assign(LoadMapData.prototype, /** @lends LoadMapData.prototype */ {
 			}
 			tileset.style = new Cesium.Cesium3DTileStyle({
 				color: options.color,
-				// color: 'vec4(0, 0.2, 1.0,1.0)',
+				// color: 'vec4(0.0, 0.58, 0.86, 1.0)',
 			});
 			tileset.tileVisible.addEventListener((tile) => {
 				//console.log("tile:",tile);