当前位置: 首页 > news >正文

【cesium】在vue2中使用cesium(持续更新)

在vue2中使用cesium

  • 在项目中使用步骤
    • 1. npm install cesium --save
    • 2. 接入项目 cesium
    • 3. index.html中引入cesium
    • 4. 完成后重启项目!
    • 5. 定义组件并初始化一个简单的cesium
  • 功能方法
    • 1. 使用天地图影像
    • 2. 销毁 cesium
    • 3. 地图放大缩小
    • 3. 获取可视区域、高度、层级
    • 4. 搜索地名后定位到该位置(`高德地图搜索POI功能`)
      • 4.1 实现效果图
      • 4.2 搜索组件完整代码
      • 4.3 cesium与高德地图经纬度不匹配导致定位偏移问题解决
        • 4.3.1 安装coordtransform
        • 4.3.2 封装转为WGS-84坐标的方法
        • 4.3.3 组件中使用转换方法
      • 4.4 [高德地图申请key](https://console.amap.com/dev/key/app)
    • 5. 标注点添加鼠标移入显示其名称
      • 5.1 实现效果图
      • 5.2 tooltip组件完整代码
      • 5.3 鼠标移入显示其名称-关键代码

在项目中使用步骤

1. npm install cesium --save

2. 接入项目 cesium

node_modules中找到cesium,复制build文件夹下Cesium文件夹到public文件夹下。复制完后就是下图

在这里插入图片描述

3. index.html中引入cesium

在项目 index.html 文件中,head 标签里面引入 cesium 的全局样式,在body标签中引入cesium 源码。

<link rel="stylesheet" href="./Cesium/Widgets/widgets.css">
<script type="text/javascript" src="./Cesium/Cesium.js"></script>

如下图:
在这里插入图片描述

4. 完成后重启项目!

5. 定义组件并初始化一个简单的cesium

<template>
  <div id="my-map"></div>
</template>

<script>
  export default {
    name: "CesiumView",
    methods: {
      init() {
        this.viewer = new Cesium.Viewer("my-map", {
          homeButton: false,
          sceneModePicker: false,
          baseLayerPicker: false, // 影像切换
          animation: true, // 是否显示动画控件
          infoBox: false, // 是否显示点击要素之后显示的信息
          selectionIndicator: false, // 要素选中框
          geocoder: false, // 是否显示地名查找控件
          timeline: true, // 是否显示时间线控件
          fullscreenButton: false,
          shouldAnimate: false,
          navigationHelpButton: false, // 是否显示帮助信息控件
        });
      },
    },
    mounted() {
      this.init();
    },
  };
</script>

<style scoped>
  #my-map {
    width: 100%;
    height: 100%;
    background-color: black;
  }
</style>

功能方法

1. 使用天地图影像

const imageLayers = this.viewer.scene.imageryLayers;
imageLayers.remove(imageLayers.get(0)); //移除默认影像图层
const TDTTK = "key"; //填入你自己的天地图Key
// 天地图影像
const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
  url: `http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
  layer: "tdt",
  style: "default",
  format: "image/jpeg",
  tileMatrixSetID: "w",
  maximumLevel: 18,
  show: false,
});
this.viewer.imageryLayers.addImageryProvider(tdtLayer);
// 天地图注记
const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
  url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
  layer: "tdtAnno",
  style: "default",
  format: "image/jpeg",
  tileMatrixSetID: "w",
  maximumLevel: 18,
  show: false,
});
this.viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);

使用天地图影像完整初始化代码如下:

<template>
  <div id="my-map"></div>
</template>

<script>
  export default {
    name: "CesiumView",
    data() {
      return {
        TDT_SL: null,
      };
    },
    methods: {
      init() {
        Cesium.Ion.defaultAccessToken =
          "cesium_key";
        this.viewer = new Cesium.Viewer("my-map", {
          homeButton: true,
          sceneModePicker: true,
          baseLayerPicker: true, // 影像切换
          animation: false, // 是否显示动画控件
          infoBox: false, // 是否显示点击要素之后显示的信息
          selectionIndicator: false, // 要素选中框
          geocoder: true, // 是否显示地名查找控件
          timeline: false, // 是否显示时间线控件
          fullscreenButton: false,
          shouldAnimate: false,
          navigationHelpButton: false, // 是否显示帮助信息控件
        });

        // 注释版权信息
        this.viewer._cesiumWidget._creditContainer.style.display = "none";

        const imageLayers = this.viewer.scene.imageryLayers;
        imageLayers.remove(imageLayers.get(0)); //移除默认影像图层
        const TDTTK = "key"; //填入你自己的天地图Key
        // 天地图影像
        const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
          url: `http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
          layer: "tdt",
          style: "default",
          format: "image/jpeg",
          tileMatrixSetID: "w",
          maximumLevel: 18,
          show: false,
        });
        this.viewer.imageryLayers.addImageryProvider(tdtLayer);
        // 天地图注记
        const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
          url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
          layer: "tdtAnno",
          style: "default",
          format: "image/jpeg",
          tileMatrixSetID: "w",
          maximumLevel: 18,
          show: false,
        });
        this.viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
      },
    },
    mounted() {
      this.init();
    },
  };
</script>

<style scoped>
  #my-map {
    width: 100%;
    height: 100%;
    background-color: black;
  }
</style>

2. 销毁 cesium

this.viewer.destroy()

3. 地图放大缩小

cesium 的放大缩小和百度地图他们不一样。cesium 的放大缩小其实就是相机高度,相机高度变小就是放大,相机高度变大就是缩小。理解吧?相机高了,视角大了,蓝星上面东西就小了。

/**
 * 地图放大
 */
zoomIn() {
  // viewer 为 Viewer 对象
  let position = this.viewer.camera.position;
  let cameraHeight = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height;
  // 每次缩小 20 倍,参数可改
  let moveRate = cameraHeight / 20.0;
  this.viewer.camera.moveForward(moveRate);
}
/**
 * 地图缩小
 */
zoomOut() {
  // viewer 为 Viewer 对象
  let position = this.viewer.camera.position;
  let cameraHeight = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height;
  // 每次缩小 20 倍,参数可改
  let moveRate = cameraHeight / 20.0;
  this.viewer.camera.moveBackward(moveRate);
}

3. 获取可视区域、高度、层级

let rectangle = this.viewer.camera.computeViewRectangle();

  • 转换为地理坐标:
let rectangle = this.viewer.camera.computeViewRectangle();
let east = Cesium.Math.toDegrees(rectangle.east).toFixed(6);  // 转地理坐标
console.log(rectangle, east)
  • 获取相机高度,单位是米哈:
let height = Math.ceil(this.viewer.camera.positionCartographic.height).toFixed(0);
console.log("相机高度----->> ", height)

  • 获取层级:
let zoom = this.heightToZoom(height).toFixed(0)
console.log("层级----->> ", zoom)
// 定义的方法
heightToZoom(height) {
  let A = 40487.57;
  let B = 0.00007096758;
  let C = 91610.74;
  let D = -40467.74;
  return Math.round(D + (A - D) / (1 + Math.pow(height / C, B)));
}

4. 搜索地名后定位到该位置(高德地图搜索POI功能

4.1 实现效果图

在这里插入图片描述

4.2 搜索组件完整代码

<template>
  <div class="bs-search">
    <div class="bs-title">
      <div class="title">搜索</div>
      <span class="el-icon-close" @click="searchHandle"></span>
    </div>
    <div class="search-box">
      <div style="margin-top: 15px">
        <el-select
          v-model="inputV"
          filterable
          remote
          reserve-keyword
          placeholder="请输入"
          :remote-method="remoteMethod"
          :loading="loading"
          @change="changeFun"
        >
          <el-option
            v-for="item in options"
            :key="item.location"
            :label="item.name"
            :value="item.location"
          >
          </el-option>
        </el-select>
      </div>
    </div>
  </div>
</template>

<script>
import { mapState, mapMutations } from "vuex";
import searchIcon from "@/assets/largeScreen/searchIcon.png";
import { gcj02ToWgs84 } from "@/utils/coordtransform.js";
export default {
  computed: {
    ...mapState({
      bsParams: (state) => state.Layout.bsParams,
    }),
  },
  data() {
    return {
      inputV: "",
      loading: false,
      options: [],
      lastEntity: null,
    };
  },
  methods: {
    ...mapMutations(["searchHandle"]),
    async remoteMethod(query) {
      if (!query) return;
      this.loading = true;
      try {
        const response = await fetch(
          `https://restapi.amap.com/v5/place/text?key=${你的高德key}&keywords=${query}`
        );
        const res = await response.json();
        this.options = res?.pois || [];
      } catch (error) {
        console.error(error);
      } finally {
        this.loading = false;
      }
    },
    changeFun(val) {
      const location = val.split(",");
      if (location.length !== 2) {
        console.error("无效坐标: ", val);
        return;
      }

      const [longitudeStr, latitudeStr] = location;
      const longitude = parseFloat(longitudeStr.trim());
      const latitude = parseFloat(latitudeStr.trim());

      if (isNaN(longitude) || isNaN(latitude)) {
        console.error("无效坐标: ", val);
        return;
      }

      const [wgsLng, wgsLat] = gcj02ToWgs84(longitude, latitude);

      if (this.lastEntity) {
        window.viewer.entities.remove(this.lastEntity);
        this.lastEntity = null;
      }

      window.viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(wgsLng, wgsLat, 1000),
      });

      this.lastEntity = window.viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(wgsLng, wgsLat),
        billboard: {
          image: searchIcon,
          width: 32,
          height: 32,
          scale: 1.0,
          disableDepthTestDistance: Number.POSITIVE_INFINITY, // 避免图标被地形遮挡
        },
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.bs-search {
  background-color: rgba(19, 37, 69, 0.6);
  padding: 1.25rem;
  border-radius: 0.25rem;

  .bs-title{
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #fff;

    .title {
      font-family: PangMenZhengDao;
      font-size: 1.125rem;
    }

    span {
      font-weight: 700;
      font-size: 1.125rem;
      cursor: pointer;
    }

    .title:before {
      content: "";
      display: inline-block;
      width: 0.375rem;
      height: 1rem;
      margin-right: 0.25rem;
      background-color: #3ba0ff;
    }
  }

  .search-box {
    margin: 0.625rem 0;

    .el-select .el-input {
      width: 130px;
    }
    .input-with-select .el-input-group__prepend {
      background-color: #fff;
    }
  }
}
</style>

4.3 cesium与高德地图经纬度不匹配导致定位偏移问题解决

4.3.1 安装coordtransform
npm install coordtransform
4.3.2 封装转为WGS-84坐标的方法
import { gcj02towgs84 } from "coordtransform";

// 修正后的 WGS-84 坐标‌
export function gcj02ToWgs84(lng, lat) {
  return gcj02towgs84(lng, lat);
}
4.3.3 组件中使用转换方法
import { gcj02ToWgs84 } from "@/utils/coordtransform.js"; // 引入
const [wgsLng, wgsLat] = gcj02ToWgs84(longitude, latitude); // 调用

4.4 高德地图申请key

在这里插入图片描述

5. 标注点添加鼠标移入显示其名称

5.1 实现效果图

在这里插入图片描述

5.2 tooltip组件完整代码

<template>
  <div id="tooltip"></div>
</template>

<style scoped>
#tooltip {
  position: absolute;
  background: #fff;
  padding: 5px 10px;
  border: 1px solid #ccc;
  border-radius: 3px;
  pointer-events: none;
  display: none;
  font-family: Arial, sans-serif;
  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
  z-index: 9999;
}
</style>

5.3 鼠标移入显示其名称-关键代码

      // 创建工具提示元素
      const tooltip = document.getElementById("tooltip");

      // 初始化屏幕空间事件处理器
      const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

      // 监听鼠标移动事件
      handler.setInputAction((movement) => {
        // 检测当前鼠标位置的实体
        const picked = viewer.scene.pick(movement.endPosition);

        if (Cesium.defined(picked) && picked.id && picked.id.name) {
          // 获取名称并更新工具提示
          tooltip.innerHTML = picked.id.name;
          tooltip.style.display = "block";

          // 将鼠标坐标转换为Canvas坐标
          const canvasPosition =
            Cesium.SceneTransforms.wgs84ToWindowCoordinates(
              viewer.scene,
              picked.id.position.getValue(viewer.clock.currentTime)
            );

          if (canvasPosition) {
            // 定位工具提示
            tooltip.style.left = `${canvasPosition.x + 10}px`;
            tooltip.style.top = `${canvasPosition.y + 10}px`;
          }
        } else {
          tooltip.style.display = "none";
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

参考文章:https://blog.csdn.net/qq_46123200/article/details/146258229

相关文章:

  • 基于VSCode的Qt开发‘#include ui_test.h’报错没有该文件
  • 沐渥科技详解氮气柜操作指南
  • C++程序诗篇的灵动赋形:多态
  • 李沐《动手学深度学习》 | 线性神经网络-线性回归
  • 《USB技术应用与开发》第二讲:连接和枚举
  • Python实例题:Python3实现命令行动态进度条
  • WebGPU:前端图形技术的革命性进化与WebGL的未来
  • [ctfshow web入门] web39
  • 深入理解 RxSwift 中的 Driver:用法与实践
  • NI labview数据采集程序
  • wait 和notify ,notifyAll,sleep
  • ecovadis认证有什么好处?ecovadis认证有什么要求 有哪些勋章
  • C++函数签名
  • 工作的意义,在工作以外的地方
  • 从0到1打造一套适合自己接单的脚手架03用户登录注册
  • 触摸屏触摸坐标与画面对齐
  • 前端性能优化核弹级方案:CSS分层渲染+Wasm,首屏提速300%!
  • MySQL:事务的理解
  • Spring Cloud Alibaba微服务治理实战:Nacos+Sentinel深度解析
  • 纳米软件矿用电源模块自动化测试方案分享