vue-cesium 使用方法

本文介绍如何使用Vue Cesium构建一个3D地图应用,包括加载Bing Maps和自定义图层,展示地形,添加交互式点数据,以及集成视频播放功能。通过Vue组件方式设置Cesium Ion的accessToken,实现地图的导航、定位和弹窗展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mate
Life is Like a Fuxking Movie

安装

npm i vue-cesium@2.2.6

使用

public > index.html

  <!-- include VueCesium -->
  <script src="https://unpkg.com/vue-cesium@latest/lib/index.umd.js"></script>

main.js

import VueCesium from 'vue-cesium'
import 'video.js/dist/video-js.css'
Vue.use(VueCesium, {
  // cesiumPath 是指引用的Cesium.js路径,如
  // 项目本地的Cesium Build包,vue项目需要将Cesium Build包放static目录:
  // cesiumPath: /static/Cesium/Cesium.js
  // 个人在线Cesium Build包:
  // cesiumPath: 'https://zouyaoji.top/vue-cesium/statics/Cesium/Cesium.js'
  // 个人在线SuperMap Cesium Build包(在官方基础上二次开发出来的):
  // cesiumPath: 'https://zouyaoji.top/vue-cesium/statics/SuperMapCesium/Cesium.js'
  // 官方在线Cesium Build包,有CDN加速,推荐用这个:
  cesiumPath: 'https://unpkg.com/cesium/Build/Cesium/Cesium.js',
  // 指定Cesium.Ion.defaultAccessToken,使用Cesium ion的数据源需要到https://cesium.com/ion/申请一个账户,获取Access Token。不指定的话可能导致 Cesium 在线影像加载不了
  accessToken: '自己申请的Access Token'
})

vue

/*** 
 * @Author: Mo ke
 * @Date: 2021-08-16 15:56:46
 * @LastEditTime: 2021-10-25 14:17:08
 * @LastEditors: Moke
 * @Description: 
 * 
 */
<template>
  <div class="viewer" style="width: 100%; height: 100%">
    <vc-viewer @ready="ready">
      <!-- 坐标显示start -->
      <vc-navigation ref="navigation" :options="options"></vc-navigation>
      <!-- 坐标end -->

      <!-- 图层start -->
      <vc-layer-imagery>
        <vc-provider-imagery-bingmaps
          url="https://dev.virtualearth.net"
          bmKey="AgcbDCAOb9zMfquaT4Z-MdHX4AsHUNvs7xgdHefEA5myMHxZk87NTNgdLbG90IE-"
          mapStyle="Aerial"
        ></vc-provider-imagery-bingmaps>
      </vc-layer-imagery>
      <vc-layer-imagery>
        <vc-provider-imagery-urltemplate
          :url="jsonurl"
        ></vc-provider-imagery-urltemplate>
      </vc-layer-imagery>

      <!-- <vc-layer-imagery ref="wms">
        <vc-provider-imagery-wms
          :url="wmsurl"
          :layers="layers"
          :parameters="parameters"
        ></vc-provider-imagery-wms>
      </vc-layer-imagery> -->
      <!-- 图层end -->

      <!-- 地形 -->
      <vc-provider-terrain-cesium ref="terrain"></vc-provider-terrain-cesium>

      <!-- 弹框start -->
      <vc-overlay-html
        :position="positionModal"
        :pixelOffset="{ x: 0, y: -250 }"
      >
        <div class="vc-dialog" v-show="showModal">
          <div class="line"></div>

          <div class="main">
            <div class="close" @click="close"></div>
            <div
              v-html="Element"
              v-show="show"
              style="width: 100%; height: 100%"
            ></div>
            <div
              v-show="!show"
              id="video-div"
              style="width: 100%; height: 100%"
            >
              <video
                id="videos"
                style="width: 90%; height: 96%"
                ref="video"
                class="video-js vjs-default-skin"
                loop
                muted
                autoplay
                preload
              ></video>
            </div>
          </div>
        </div>
      </vc-overlay-html>
      <!-- 弹框end -->
      <!-- 雷达扫描start -->
      <!-- <vc-scan-radar
        :radius="30"
        :interval="3000"
        :color="'#fff'"
        :position="position"
      ></vc-scan-radar> -->
      <!-- 雷达扫描end -->
      <!-- 3dtitles start -->
      <vc-primitive-tileset
        :url="url"
        @readyPromise="readyPromise"
        @initialTilesLoaded="initialTilesLoaded"
        @allTilesLoaded="allTilesLoaded"
        @loadProgress="loadProgress"
        @tileFailed="tileFailed"
        @tileLoad="tileLoad"
        @tileUnload="tileUnload"
        @tileVisible="tileVisible"
      >
      </vc-primitive-tileset>
      <!-- 3dtitles end -->
      <a href="javascript:;" class="location">
        <div
          type="submit"
          @click="btn"
          class="iconfont icon-dizhidingweiweizhi"
        ></div>
      </a>
      <div
        style="
          position: absolute;
          color: #fff;
          z-index: 3;
          padding: 10px;
          font-size: 27px;
          user-select: none;
        "
      >
        地质灾害监测系统
      </div>
    </vc-viewer>
  </div>
</template>

<script>
import videojs from "video.js";
import "vue-cesium/lib/vc-navigation.css";
import "vue-cesium/lib/style.css";
export default {
  data() {
    return {
      tileset: null, //生成的模型
      playerList: [], //播放源
      show: false, //视频的显示
      showModal: false, //popup框显示
      jsonurl: "http://IP/C12C13_3857_tiles/{z}/{x}/{y}.png",
      wmsurl: "http://localhost:8080/geoserver/mo/wms",
      layers: "mo:C12C13",
      parameters: {
        service: "WMS",
        format: "image/png",
        transparent: true,
      },

      // position: { lng: 115.91899, lat: 40.14371 },
      positionModal: { lng: x坐标, lat: y坐标, height: 660 },

      Element: null,
      url: "http://IP/data/3dtiles3857/tileset.json",
      options: {
        enableCompass: true,
        enableZoomControl: true,
        // enableZoomControl: {
        //   // 缩放比例
        //    zoomAmount: 2,
        //   // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是经纬度{lng: number, lat: number, height: number}或者 rectangle{west: number,south: number,east: number,north: number}
        //   defaultResetView: {
        //     lng: 105, lat: 29.999999999999993, height: 19059568.497290563, heading: 360, pitch: -90, roll: 0
        //   },
        //   overrideCamera: false
        // },
        enableDistanceLegend: true,
        enableLocationBar: true,
        // enableLocationBar: {
        //   // 获取更精确的高程
        //   gridFileUrl: './statics/SampleData/WW15MGH.DAC'
        // },
        enableCompassOuterRing: true,
        enablePrintView: true,
        // enablePrintView: {
        //   // 是否添加 Credit
        //   showCredit: true,
        //   // 是否自动打印
        //   printAutomatically: false
        // },
        // enableMyLocation: true,
        enableMyLocation: {
          // 使用高德api定位
          amap: {
            key: "42d22e6ed83f077bc28b7864718726de",
          },
        },
      },
      // 点数据
      AddspotDatas: [
        {
          id: 1, //唯一id
          x: 115.95551, //经度
          y: 40.14098, //纬度
          z: 660, //高度
          icon: require("../assets/铁塔.png"), //图标
          HtmlVal: ` <ul>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >传感器型号:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >C-201923</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >温度:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >30℃</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >x偏移:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >30</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >y偏移:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >30</span
                >
              </li>
            </ul>`, //弹出框内容
          description: ``, //默认弹出框内容
        },
        {
          id: 2,
          x: 115.96176,
          y: 40.14075,
          z: 500,
          icon: require("../assets/logo3.png"),
          HtmlVal: ``,
          description: ``,
        },
        {
          id: 3,
          x: 115.96983,
          y: 40.13983,
          z: 500,
          icon: require("../assets/房子.png"),
          HtmlVal: ` <ul>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >地址:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >小沙村</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >温度:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >25℃</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >区域:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >山区</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >湿度:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >适中</span
                >
              </li>
            </ul>`, //弹出框内容

          description: ``,
        },
        {
          id: 4,
          x: 115.9763,
          y: 40.13926,
          z: 400,
          icon: require("../assets/配电站.png"),
          HtmlVal: ` <ul>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >地址:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >电-00045</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >温度:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >25℃</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >设备情况:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >正常</span
                >
              </li>
              <li style="font-size: 18px; width: 300px; list-style: none">
                <span
                  style="
                    text-align: right;
                    margin-right: 20px;
                    display: inline-block;
                    width: 116px;
                    font-size: 18px;
                    font-weight: 900;
                  "
                  >运行时间:</span
                ><span
                  style="
                    text-align: left;

                    display: inline-block;
                    width: 116px;
                  "
                  >1100H</span
                >
              </li>
            </ul>`, //弹出框内容

          description: ``,
        },
        {
          id: 5,
          x: 115.98615,
          y: 40.13863,
          z: 500,
          icon: require("../assets/logo3.png"),
          HtmlVal: ``,
          description: ``,
        },
      ],
    };
  },

  methods: {
    clicked(a) {
      console.log(a);
    },
    close() {
      this.showModal = false;
      this.show = false;
    },
    ready(cesiumInstance) {
      var self = this;
      this.cesiumInstance = cesiumInstance;
      const { Cesium, viewer } = cesiumInstance;
      // viewer.imageryProvider = new Cesium.BingMapsImageryProvider({
      //   url: "https://dev.virtualearth.net",
      //   key: "AgcbDCAOb9zMfquaT4Z-MdHX4AsHUNvs7xgdHefEA5myMHxZk87NTNgdLbG90IE-",
      //   mapStyle: Cesium.BingMapsStyle.AERIAL,
      // });
      // viewer.terrainProvider = Cesium.createWorldTerrain();
      // viewer.imageryLayers.addImageryProvider(
      //   new Cesium.WebMapServiceImageryProvider({
      //     url: "http://localhost:8080/geoserver/mo/wms?", //服务地址
      //     layers: "mo:C12C13", //服务图层,修改成自己发布的名称
      //     parameters: {
      //       service: "WMS",
      //       format: "image/png",
      //       transparent: true,
      //     },
      //   })
      // );

      // 循环加点

      self.AddspotDatas.map((item) => {
        self.Addspot(item);
      });

      viewer.screenSpaceEventHandler.removeInputAction(
        Cesium.ScreenSpaceEventType.LEFT_CLICK
      );
      var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
      //绑定鼠标单击
      handler.setInputAction((movement) => {
        var pick = viewer.scene.pick(movement.position);
        if (Cesium.defined(pick) && pick.primitive) {
          let WorldCoordinates = pick.primitive._position;
          let HtmlVal = pick.id._HtmlVal;

          switch (Cesium.defined(pick) && pick.id._id) {
            case 2:
              self.show = false;
              self.Popup({ WorldCoordinates });

              self.play({
                src: "m3u8格式链接",
                type: "application/x-mpegURL",
              });

              break;
            case 5:
              self.show = false;
              self.Popup({ WorldCoordinates });

              self.play({
                src: "/video2.mp4",
                type: "video/mp4",
              });

              break;

            default:
              self.Popup({ WorldCoordinates, HtmlVal });
              self.show = true;
              break;
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    },
    // 添加点函数
    Addspot(data) {
      const { Cesium, viewer } = this.cesiumInstance;
      viewer.entities.add({
        description: data.description,
        id: data.id,
        HtmlVal: data.HtmlVal,
        position: Cesium.Cartesian3.fromDegrees(data.x, data.y, data.z),
        billboard: {
          // 图像地址,URI或Canvas的属性
          image: data.icon,
          // 设置颜色和透明度
          color: Cesium.Color.WHITE.withAlpha(0.8),
          // 高度(以像素为单位)
          height: 30,
          // 宽度(以像素为单位)
          width: 30,
          // 逆时针旋转
          rotation: 0,
          // 大小是否以米为单位
          sizeInMeters: false,
          // 相对于坐标的垂直位置
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          // 相对于坐标的水平位置
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          // 该属性指定标签在屏幕空间中距此标签原点的像素偏移量
          // pixelOffset: new Cesium.Cartesian2(10, 0),
          // 应用于图像的统一比例。比例大于会1.0放大标签,而比例小于会1.0缩小标签。
          scale: 1.0,
          // 是否显示
          show: true,
        },
      });
    },
    // 显示信息并绑定坐标
    Popup(data) {
      let { WorldCoordinates, HtmlVal } = data;

      const { Cesium, viewer } = this.cesiumInstance;
      // 世界坐标转经纬度 start
      var ellipsoid = viewer.scene.globe.ellipsoid;
      var cartograhpinc = ellipsoid.cartesianToCartographic(WorldCoordinates);
      var lat = Cesium.Math.toDegrees(cartograhpinc.latitude);
      var lng = Cesium.Math.toDegrees(cartograhpinc.longitude);
      var height = cartograhpinc.height;
      // 世界坐标转经纬度end
      this.Element = HtmlVal;
      this.showModal = true; //控制popup框显示
      this.positionModal = { lng, lat, height }; //popup显示的坐标绑定
    },
    // 播放视频
    play(data) {
      this.playerList = [];

      var myPlayer = videojs(
        "videos",
        {
          muted: true,
          controls: true,
          loop: false,
          autoplay: false,
          sources: [
            {
              src: data.src,
              type: data.type,
            },
          ],
        },
        function onPlayerReady() {
          console.log("muted", this.muted());
          this.muted(false);

          this.volume(0.5); //调整音量 0~1
          this.play();
          videojs.log("播放开始了1!");
        }
      );

      //改变播放内容
      myPlayer.src(data);

      // videojs.getPlayer("videos").on("ended", function () {
      //   videojs.log("播放结束了2!");
      //   this.dispose(); //销毁该实例,解除所有绑定事件并移除对应video元素
      //   console.log("是否已销毁", this.isDisposed());
      // });
    },
    btn() {
      const { Cesium, viewer } = this.cesiumInstance;

      // this.viewer.zoomTo(this.tileset, new Cesium.HeadingPitchRange(0.0, -0.5, this.tileset.boundingSphere.radius * 2.0))
      viewer.camera.flyTo({
        //定位过去115.91899, 40.09571,
        destination: Cesium.Cartesian3.fromDegrees(x坐标, y坐标,镜头高),
        orientation: {
          heading: Cesium.Math.toRadians(0), // east, default value is 0.0 (north) //东西南北朝向
          pitch: Cesium.Math.toRadians(-50), // default value (looking down)  //俯视仰视视觉
          roll: 0.0, // default value
        },
        duration: 6, //3秒到达战场
      });
    },

    readyPromise(tileset) {
      const { Cesium, viewer } = this.cesiumInstance;
    },
    allTilesLoaded() {},
    initialTilesLoaded() {},
    loadProgress(numberOfPendingRequests, numberOfTilesProcessing) {
      if (numberOfPendingRequests === 0 && numberOfTilesProcessing === 0) {
        return;
      }
    },
    tileFailed(error) {},
    tileLoad(tile) {},
    tileUnload(tile) {},
    tileVisible(tile) {},
  },
};
</script>
<style>
* {
  padding: 0;
  margin: 0;
}
.vc-box {
  width: 200px;
  line-height: 30px;
  background-color: rgba(0, 0, 0, 0.8);
  color: #fff;
  padding: 8px 16px;
}
.vc-dialog {
  /*重要*/
  user-select: none; /*禁止选中*/
  pointer-events: none; /*鼠标穿透*/
  top: 0;
  left: 0;
  min-width: 320px;
  min-height: 250px;
  z-index: 99999;
  position: absolute;
}
.vc-dialog .line {
  position: absolute;
  left: 0;
  width: 0;
  height: 100px;
  bottom: 0;
  background: url("/line.png");
  animation: goLine 0.5s forwards;
}
@keyframes goLine {
  from {
    width: 0;
  }
  to {
    width: 50px;
  }
}
.vc-dialog .main {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 100px;
  background: url("/bg.png") no-repeat;
  background-size: 100% 100%;
  color: white;
  padding: 20px 5px 5px 10px;
  font-size: 14px;
  user-select: text;
  pointer-events: auto;
  opacity: 0;
  animation: goDynamicLayer 0.5s forwards;
  animation-delay: 0.5s;
}
.vc-dialog .main .close {
  position: absolute;
  top: 3px;
  right: 8px;
  transition: 1s;
  text-decoration: none;
}

.vc-dialog .main .close:hover {
  transform: rotate(180deg);
}
.vc-dialog .main .close::before {
  content: "✖";
  color: #f1f2f6;
}
@keyframes goDynamicLayer {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
.vc-dialog .light {
  position: absolute;
  z-index: 2;
  width: 100%;
  height: 100%;
}
.cesium-infoBox-visible {
  opacity: 0;
}
.cesium-infoBox {
  display: none !important;
}
.cesium-viewer-bottom {
  display: none !important;
}
.vc-location-distance {
  display: none !important;
}
.vc-navigation-controls {
  display: none !important;
}

.location {
  font-size: 22px;
  font-weight: 900;
  background: rgb(255, 255, 255);
  position: absolute;
  color: rgb(81, 12, 0);
  z-index: 1001;
  right: 28px;
  top: 235px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  line-height: 30px;
  text-align: center;
  user-select: none;
  text-decoration: none;
}
.location:hover {
  cursor: pointer;
}
</style>
<think>好的,我现在需要帮助用户解决在Vue-Cesium中实现点击弹框后的平移功能的问题。首先,我得理解用户的需求。用户希望在点击弹框的时候,地图视图能够平滑地移动到某个位置,可能还带有动画效果,比如flyTo这样的方法。 接下来,我需要回顾一下Cesium中相关的API,特别是视图移动的方法。根据引用[1],cesium的flyTo方法可以通过设置offset来调整相机的俯仰角、方位角和距离。比如使用viewer.flyTo(entities, { offset: new Cesium.HeadingPitchRange(...) })。这可能对调整视角有帮助。 然后,用户提到的是在Vue-Cesium环境中实现。Vue-Cesium是对Cesium的封装,所以大部分Cesium的API应该仍然适用。需要确保在Vue组件中正确获取到viewer实例,通常可以通过this.viewer或者类似的方式访问。 接下来要考虑点击弹框的事件处理。用户点击某个元素(比如一个按钮或标记)后触发平移。因此,需要给弹框中的元素绑定点击事件,并在事件处理函数中调用flyTo方法。可能需要用到Cesium的ScreenSpaceEventHandler来监听点击事件,或者直接在Vue的模板中使用@click事件。 另外,引用[4]中提到OpenLayers的平移动画效果,虽然技术栈不同,但思路类似,即调用相应的方法实现平滑移动。在Cesium中,flyTo本身就支持动画效果,所以应该使用这个方法。 还需要考虑弹框的位置可能跟随点击的位置,这时候需要获取点击的坐标,并将其转换为地图的经纬度。引用[2]中提到的坐标拾取方法可能会有用,比如使用viewer.scene.pickPosition或者其他的坐标转换方法。 另外,引用[3]中关于修改DOM元素的内容,可能用户之前处理过界面本地化的问题,但当前问题可能不需要这部分,不过需要确保弹框的DOM元素正确绑定事件。 现在,我需要将这些步骤整合到Vue-Cesium的实现中。可能的步骤如下: 1.Vue组件中初始化Cesium Viewer,并确保能够通过ref或类似方法获取到viewer实例。 2. 给需要触发平移的弹框元素添加点击事件处理,比如@click="handleFlyTo"。 3. 在handleFlyTo方法中,确定目标位置的经纬度和高度,可能还需要调整相机的方位角、俯仰角等参数。 4. 使用viewer.camera.flyTo或者viewer.flyTo方法,并传入合适的参数,比如目标坐标、偏移量、动画持续时间等。 5. 可能需要处理坐标转换,比如屏幕坐标到世界坐标的转换,特别是在点击地图获取位置时。 还需要注意Vue-Cesium的版本和Cesium的版本是否兼容,以及是否正确导入所需的模块,比如Cesium的HeadingPitchRange类。 最后,可能需要处理一些边界情况,比如在平移过程中用户再次点击的处理,或者确保弹框在平移后仍然正确显示。同时,根据引用[1]中的例子,设置offset参数可以调整视角,避免视图偏移,所以需要正确计算偏移量,确保平移后的视图符合预期。</think>在Vue-Cesium中实现点击弹框后的视图平移功能,可以通过以下步骤实现: ### 一、核心实现步骤 1. **绑定点击事件** ```vue <vc-viewer @ready="onViewerReady" @click="handleMapClick"> <vc-entity ref="marker" :position="clickPosition"></vc-entity> </vc-viewer> ``` 2. **弹框显示与坐标获取** ```javascript handleMapClick(e) { const position = e.position const cartesian = this.viewer.scene.pickPosition(position) const cartographic = Cesium.Cartographic.fromCartesian(cartesian) this.clickPosition = [Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)] this.showPopup = true } ``` 3. **执行平移动画** ```javascript flyToTarget() { const headingPitchRange = new Cesium.HeadingPitchRange( Cesium.Math.toRadians(0), // 朝向角 Cesium.Math.toRadians(-30), // 俯仰角 100000 // 视距 ) this.viewer.flyTo(this.$refs.marker, { offset: headingPitchRange, duration: 2 // 动画持续时间 }) } ``` ### 二、关键参数说明 1. **HeadingPitchRange** 控制视角参数: - `heading`:0表示正北方向(默认) - `pitch`:负数表示向下俯视(-30度效果最佳)[^1] 2. **flyTo参数**: - `duration`:建议2-3秒实现平滑过渡 - `offset`:保持与目标点的相对位置关系 ### 三、弹框跟随实现 ```vue <div v-if="showPopup" :style="popupStyle"> <button @click="flyToTarget">定位到目标</button> </div> // 计算弹框位置 computed: { popupStyle() { return { position: 'fixed', left: `${this.clickPixel.x}px`, top: `${this.clickPixel.y}px` } } } ``` ### 四、注意事项 1. 使用`pickPosition`而非`getPickRay`可提高坐标精度[^2] 2. 飞行结束后建议重置相机参数: ```javascript this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY) ``` 3. 对移动端需添加触摸事件适配
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值