您的当前位置:首页正文

在vue上使用cesium开发三维地图的详细过程

2024-11-03 来源:个人技术集锦

需要注意的是,Cesium 使用 WebGL 技术,所以您需要确保浏览器支持 WebGL。

一:安装Cesium

可以通过 NPM 安装 Cesium。打开命令行界面,输入以下命令:

npm install cesium

安装完成后,您可以在 node_modules/cesium 目录下找到 Cesium 的 JavaScript 文件和相关文件。

二:在 Vue 项目中使用 Cesium

接下来,在 Vue 项目中引入 Cesium,可以使用以下几种方式。

方式一:在 index.html 文件中引入 Cesium

在您的 index.html 文件中添加以下代码:

<script src="./node_modules/cesium/Build/Cesium/Cesium.js"></script>
<link rel="stylesheet" href="./node_modules/cesium/Build/Cesium/Widgets/widgets.css" rel="external nofollow"  />

这将在整个 Vue 应用程序中加载 Cesium。

方式二:使用模块设置

在 main.js 文件中添加以下代码:

import Cesium from 'cesium/Cesium'
import 'cesium/Build/Cesium/Widgets/widgets.css'
Vue.prototype.Cesium = Cesium  // 将 Cesium 注册为 Vue 实例的属性

这样,您就可以在整个 Vue 应用程序中通过 this.Cesium 访问 Cesium 相关的类和方法。

三:创建一个 Cesium 场景

使用 Cesium 创建一个场景需要一个 HTML 元素来展示它。可以在 Vue 中使用 mounted() 钩子函数将 Cesium 场景添加到您的 Vue 组件中。

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

<script>
  export default {
    mounted() {
      Cesium.Ion.defaultAccessToken =你的token
      this.viewer = new this.Cesium.Viewer('cesiumContainer'); // 创建 Cesium 场景
    }
  }
</script>

<style>
  #cesiumContainer {
    height: 100%;
    width: 100%;
  }
</style>

这只是一个简单的示例,您可以通过查看 Cesium 的文档和示例来学习如何使用更高级的功能。

注意:Cesium报错VM2395:1 Blocked script execution in 'about:blank' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.

这个错误信息通常出现在脚本尝试在沙盒框架中运行,但是'allow-scripts'权限没有被设置。

沙盒是一种安全特性,将潜在风险的代码(例如第三方脚本)与系统的其余部分隔离开来,防止脚本对浏览器的恶意操作。'allow-scripts'是一个权限选项,允许在沙箱环境中运行脚本。如果未设置此权限,浏览器将阻止脚本在沙箱中运行并显示此错误消息。

可能是因为infoBox中使用复杂的HTML标记和JavaScript脚本

禁用infobox就可以解决

const viewer = new Viewer('cesiumContainer', {
  infoBox: false, // If set to false, the InfoBox widget will not be created.
});

中文API文档: 

官方API文档:

this.viewer = new Cesium.Viewer(dom, {
      baseLayerPicker: true, // 如果设置为false,将不会创建右上角图层按钮。
      geocoder: true, // 如果设置为false,将不会创建右上角查询(放大镜)按钮。
      navigationHelpButton: true, // 如果设置为false,则不会创建右上角帮助(问号)按钮。
      homeButton: true, // 如果设置为false,将不会创建右上角主页(房子)按钮。
      sceneModePicker: true, // 如果设置为false,将不会创建右上角投影方式控件(显示二三维切换按钮)。
      animation: true, // 如果设置为false,将不会创建左下角动画小部件。
      timeline: true, // 如果设置为false,则不会创建正下方时间轴小部件。
      fullscreenButton: true, // 如果设置为false,将不会创建右下角全屏按钮。
      scene3DOnly: true, // 为 true 时,每个几何实例将仅以3D渲染以节省GPU内存。
      shouldAnimate: true, // 默认true ,否则为 false 。此选项优先于设置 Viewer#clockViewModel 。
      // ps. Viewer#clockViewModel 是用于控制当前时间的时钟视图模型。我们这里用不到时钟,就把shouldAnimate设为false
      infoBox: false, // 是否显示点击要素之后显示的信息,原生自带右上角弹窗
      sceneMode: 3, // 初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
      requestRenderMode: false, // 启用请求渲染模式,不需要渲染,节约资源吧
      selectionIndicator: false, // Cesium 关闭点击绿色框
      // fullscreenElement: document.body, // 全屏时渲染的HTML元素 暂时没发现用处,虽然我关闭了全屏按钮,但是键盘按F11 浏览器也还是会进入全屏
      imageryProvider: layer0, //影像地图修改
      // imageryProviderViewModels: [img_tdt_yx, img_tdt_dx, img_tdt_sl], //可供BaseLayerPicker选择的图像图层ProviderViewModel数组
      terrainProvider: Cesium.createWorldTerrain(), //提供地形
    });
    //通过指定的url模板请求图块提供图像
    var layer0 = new Cesium.UrlTemplateImageryProvider({
      tileWidth: 256, //默认贴图宽度
      tileHeight: 256,
      url: "http://t{R}.tianditu.gov.cn/DataServer?T=img_w&amp;x={x}&amp;y={y}&amp;l={z}&amp;tk=7254799da9b1f3d1f335f09497cd8848",
      maximumLevel: 18,
      customTags: {
        R: function (imageryProvider, x, y, level) {
          return Math.floor(Math.random() * 6);
        },
      },
    });

四:三维球定位到中国 

flyto:将相机从当前位置移动到新位置。会有一个飞行动画 ; setview设置相机的位置,方向和变换。直接定位

// 三维球定位到中国
viewer.camera.flyTo({
  destination: Cesium.Cartesian3.fromDegrees(121.871337890625,30.893386706430803,178500),//定位的位置
  orientation: {
    heading :  Cesium.Math.toRadians(0),// 水平偏角,默认正北 0
    pitch : Cesium.Math.toRadians(-90),// 俯视角,-90,垂直向下
    roll : Cesium.Math.toRadians(0)
  },
  complete:function callback() {
    // 定位完成之后的回调函数
    setTimeout(()=>{
      getview()
    },2000) 
  }
});
var position = Cesium.Cartesian3.fromDegrees(86.889, 27.991, 84000);
//相机定位到珠穆朗玛峰
viewer.camera.setView({
    destination: position,
    orientation:{
        heading:Cesium.Math.toRadians(0.0), //正北
        pitch:Cesium.Math.toDegrees(-10), //平视
        roll: 0.0
    }
});

五:添加entities实体

const boundingSphere = new Cesium.BoundingSphere(
   Cesium.Cartesian3.fromDegrees(120.55538, 31.87532, 100),
   15000
);
// 定位到初始位置 将相机移到当前视图包含所提供的包围球的位置
this.viewer.camera.flyToBoundingSphere(boundingSphere, {
// 动画,定位到初始位置的过渡时间,设置成0,就没有动画
   duration: 0,
});
//初始点位数据
    loadPoints() {
      // 用模拟数据测试
      this.pointInfo = [
        {
          id: "392f7fbb-ae25-4eef-ac43-58fd91148d1f",
          latitude: "31.87532",
          longitude: "120.55538",
          psName: "点位1",
        },
        {
          id: "0278a88c-b4f4-4d64-9ccb-65831b3fb19d",
          latitude: "31.991057",
          longitude: "120.700713",
          psName: "点位2",
        },
        {
          id: "248f6853-2ced-4aa6-b679-ea6422a5f3ac",
          latitude: "31.94181",
          longitude: "120.51517",
          psName: "点位3",
        },
        {
          id: "F8DADA95-A438-49E1-B263-63AE3BD7DAC4",
          latitude: "31.97416",
          longitude: "120.56132",
          psName: "点位4",
        },
        {
          id: "9402a911-78c5-466a-9162-d5b04d0e48f0",
          latitude: "31.91604",
          longitude: "120.57771",
          psName: "点位5",
        },
        {
          id: "EB392DD3-6998-437F-8DCB-F805AD4DB340",
          latitude: "31.88727",
          longitude: "120.48887",
          psName: "点位6",
        },
      ];
      this.addMarker();
    },
    //初始化加载点位
    addMarker() {
      // 自定义label颜色
      const _textColor = "rgb(11, 255, 244)";
      // 清除上一次加载的点位
      this.clearMarker();
      // foreach循环加载点位
      this.pointInfo.forEach((pointObj) => {
        this.viewer.entities.add({
          name: pointObj.psName,
          code: pointObj.id,
          id: pointObj.id,
          position: Cesium.Cartesian3.fromDegrees(
            pointObj.longitude * 1,
            pointObj.latitude * 1
          ),

          点
          point: {
            pixelSize: 5,
            color: Cesium.Color.RED,
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 5,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //设置HeightReference高度参考类型为CLAMP_TO_GROUND贴地类型
          },
          // 文字标签
          label: {
            // show: false,
            text: pointObj.psName,
            font: "12px monospace",
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            // fillColor: Cesium.Color.LIME,
            fillColor: Cesium.Color.fromCssColorString(_textColor),
            outlineWidth: 4,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
            pixelOffset: new Cesium.Cartesian2(0, -20), // 偏移量
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //设置HeightReference高度参考类型为CLAMP_TO_GROUND贴地类型
          },
          // 图标
          billboard: {
            image: require("../../assets/images/profile.jpg"),
            width: 18,
            height: 24,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //设置HeightReference高度参考类型为CLAMP_TO_GROUND贴地类型
          },
        });
      });
    },

六:添加点击事件

// 监听地图点击事件
      const handler = new Cesium.ScreenSpaceEventHandler(
        this.viewer.scene.canvas
      );
      handler.setInputAction((e) => {
        console.log("鼠标点击事件", e.position.x * 1, e.position.y * 1);
        //清除之前的点位
        this.clearMarker();

        // 屏幕坐标转世界坐标——关键点
        const cartesian = this.viewer.camera.pickEllipsoid(
          e.position,
          this.viewer.scene.globe.ellipsoid
        );
        // 将笛卡尔坐标转换为地理坐标
        const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        // 将弧度转为度的十进制度表示,保留5位小数
        const lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(5);
        const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(5);
        console.log(lon, lat);
        //新增点位
        this.viewer.entities.add({
          name: "1",
          id: "1",
          position: Cesium.Cartesian3.fromDegrees(lon, lat),
          // 点
          point: {
            pixelSize: 5,
            color: Cesium.Color.RED,
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 5,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //设置HeightReference高度参考类型为CLAMP_TO_GROUND贴地类型
          },
          label: {
            // show: false,
            text: "新增点位",
            font: "12px monospace",
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            // fillColor: Cesium.Color.LIME,
            fillColor: Cesium.Color.fromCssColorString("rgb(11, 255, 244)"),
            outlineWidth: 4,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
            pixelOffset: new Cesium.Cartesian2(0, -20), // 偏移量
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //设置HeightReference高度参考类型为CLAMP_TO_GROUND贴地类型
          },
          billboard: {
            image: require("../../assets/images/profile.jpg"),
            width: 18,
            height: 24,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //设置HeightReference高度参考类型为CLAMP_TO_GROUND贴地类型
          },
        });

        this.viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(lon, lat, 15000),
        });

        // 获取地图上的点位实体(entity)坐标
        const pick = this.viewer.scene.pick(e.position);
      }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

七:通过JSON加载范围线 

let res = Cesium.GeoJsonDataSource.load(jsonUrl, {
  stroke: {red: 1, green: 1, blue: 1, alpha: 0.4},
  fill: Cesium.Color.BLUE.withAlpha(0.4), //注意:颜色必须大写,即不能为blue
  strokeWidth: 3,
  clampToGround: true
});
  res.then(buffersource => {
  viewer.dataSources.add(buffersource);
  buffersource.name = "XXX";
})

总结 

您可能感兴趣的文章:
显示全文