首页 > 其他分享 >Vue3 结合 Cesium 动态绘制矩形

Vue3 结合 Cesium 动态绘制矩形

时间:2024-09-14 16:50:59浏览次数:16  
标签:viewer lat let Vue3 Cesium lng 矩形 startPoint

相关概念

  • Viewer:new Cesium.Viewer (container, options )

  • 介绍:用于构建应用程序的基本小部件。它将所有标准Cesium小部件组合到一个可重用的程序包中。

  • Entity:new Cesium.Entity ( options )

  • 介绍:实体实例将多种形式的可视化聚集到单个高级对象中。可以手动创建它们并将其添加到 Viewer#entities 

  • rectangle:略

  • 介绍:描述 Rectangle 的图形。矩形符合地球的曲率,可以放置在表面或可以选择将其挤出成一定体积。

  • coordinates:Cesium.Rectangle.fromDegrees ( west , south , east , north , result )

  • 介绍:定义了矩形的坐标

  • material:略

  • 介绍:定义了矩形的材质


demo效果


完整代码展示

其中用到了EventBus来进行组件通讯,来触发相应的逻辑,大家可以用点击事件等来代替。

<template>
  <div id="CesiumMapOne"></div>
  <div class="cesium-lnglat-info" v-show="showLngLat">
    {{ lngNum }},{{ latNum }}
  </div>
</template>

<script setup>
// vue
import {
  ref,
  reactive,
  watch,
  watchEffect,
  computed,
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  defineProps,
  defineEmits,
} from "vue";

// cesium
import * as Cesium from "cesium";

import "cesium/Build/CesiumUnminified/Widgets/widgets.css";

window.CESIUM_BASE_URL = "../../../node_modules/cesium/Build/CesiumUnminified/";

// eventbus
import EventBus from "@/eventbus";


// 变量
let _viewer = null;

// 经纬度
let lngNum = ref(0);
let latNum = ref(0);

// 是否显示经纬度
let showLngLat = ref(false);

// 裁剪AOI
let drawFlag = false;
// 开始点击位置
let startPoint = null;
// 结束点击位置
let endPoint = null;
// 绘制动态矩形数组
let pointsArr = [];
// 裁剪矩形 实体
let JXBox = null;

// 初始化地图
function initMap() {
  Cesium.Ion.defaultAccessToken =
    "在这里输入你在Cesium申请的开发token";
  //开发token


  const viewer = new Cesium.Viewer("CesiumMapOne", {
    //第二个参数是个对象

    // terrainProvider: Cesium.createWorldTerrainAsync(),
    // 地形服务
    timeline: false,
    // 时间轴控件
    animation: false,
    // 动画控件
    geocoder: false,
    //搜索框控件
    navigationHelpButton: false,
    // 帮助按钮
    sceneModePicker: true,
    // 场景模式选择器
    fullscreenButton: false,
    // 全屏按钮
    baseLayerPicker: false,
    // 底图选择器
    infoBox: false,
    // 信息框
    selectionIndicator: false,
    // 选中指示器
    homeButton: false,
    // 首页按钮
    // scene3DOnly: true,
    // 3D模式
    // creditContainer: "cesiumjsdiv",
    // 显示版权信息
    // creditViewport:"cesiumjsdiv",
    // 显示版权信息
  });
  //关键的一步,之后所有的API从这里开始

  _viewer = viewer;

  // Cesium鼠标移动事件
  _viewer.screenSpaceEventHandler.setInputAction(function (movement) {
    //获取当前鼠标位置
    var cartesian = _viewer.camera.pickEllipsoid(
      movement.endPosition,
      _viewer.scene.globe.ellipsoid
    );
    //判断鼠标位置是否在模型上
    if (cartesian) {
      //获取当前鼠标位置的经纬度
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      // console.log(cartographic, "当前鼠标位置");
      let longitude = Cesium.Math.toDegrees(cartographic.longitude);
      let latitude = Cesium.Math.toDegrees(cartographic.latitude);

      showLngLat.value = true;

      if (longitude < 0) {
        lngNum.value = Math.abs(longitude).toFixed(6) + "°W";
      } else {
        lngNum.value = longitude.toFixed(6) + "°E";
      }

      if (latitude < 0) {
        latNum.value = Math.abs(latitude).toFixed(6) + "°S";
      } else {
        latNum.value = latitude.toFixed(6) + "°N";
      }

      if (drawFlag) {
        endPoint = {
          lng: longitude,
          lat: latitude,
        };
        
        //这段代码允许 以任意方向来动态绘制矩形
        if (endPoint.lng < startPoint.lng && endPoint.lat > startPoint.lat) {
          // 第二象限
          pointsArr = Cesium.Rectangle.fromDegrees(
            endPoint.lng,
            startPoint.lat,
            startPoint.lng,
            endPoint.lat
          );
        } else if (
          endPoint.lng > startPoint.lng &&
          endPoint.lat > startPoint.lat
        ) {
          // 第一象限
          pointsArr = Cesium.Rectangle.fromDegrees(
            startPoint.lng,
            startPoint.lat,
            endPoint.lng,
            endPoint.lat
          );
        } else if (
          endPoint.lng < startPoint.lng &&
          endPoint.lat < startPoint.lat
        ) {
          // 第三象限
          pointsArr = Cesium.Rectangle.fromDegrees(
            endPoint.lng,
            endPoint.lat,
            startPoint.lng,
            startPoint.lat
          );
        } else {
          // 第四象限
          pointsArr = Cesium.Rectangle.fromDegrees(
            startPoint.lng,
            endPoint.lat,
            endPoint.lng,
            startPoint.lat
          );
        }
      }
    } else {
      showLngLat.value = false;
    }
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}

// 开始绘制矩形 函数
function clipAoi() {
  //鼠标左点击 事件
  _viewer.screenSpaceEventHandler.setInputAction(function (e) {
    // 获取鼠标点击位置
    let cartesian = _viewer.camera.pickEllipsoid(
      e.position,
      _viewer.scene.globe.ellipsoid
    );
    // 判断 是否作用在地球上
    if (cartesian && !drawFlag) {
      // 获取经纬度
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      let longitude = Cesium.Math.toDegrees(cartographic.longitude);
      let latitude = Cesium.Math.toDegrees(cartographic.latitude);

      // 获取当前相机高度
      // let height = _viewer.camera.positionCartographic.height;

      startPoint = {
        lng: longitude,
        lat: latitude,
      };

      drawFlag = true;

      // 初始化矩形
      pointsArr = Cesium.Rectangle.fromDegrees(0, 0, 0, 0);

      //删除矩形实体
      if (JXBox) {
        _viewer.entities.remove(JXBox);
      }

      // 添加动态矩形实体
      JXBox = _viewer.entities.add({
        rectangle: {
          coordinates: new Cesium.CallbackProperty(() => {
            return pointsArr;
          }, false),
          material: Cesium.Color.fromCssColorString("rgba(0, 255, 255, .5)"),
          outline: true, //多边形是否显示边缘线
          outlineColor: Cesium.Color.YELLOW.withAlpha(0.8), //定义多边形边缘线的颜色。
          outlineWidth: 2, //控制多边形边缘线的宽度。
          height: 5, //指定多边形相对于椭球表面的高度。
          extrudedHeight: 10, //创建一个拉伸的多边形(即具有高度的立体),可以设置此参数为多边形顶部的高度。
        },
      });
    } else if (cartesian && drawFlag) {
      drawFlag = false;

      EventBus.emit("drawOK", pointsArr);
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}

// 重置矩形函数
function resetAoi() {
  if (JXBox) {
    _viewer.entities.remove(JXBox);
  }
  // 移除 Cesium 的鼠标左点击事件
  _viewer.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_CLICK
  );
  //
  EventBus.emit("resetAoi");
}

// 页面挂载后
onMounted(() => {
  initMap();

  EventBus.on("header", (data) => {
    console.log(data, "header-msg");
    // 触发 对应逻辑
    switch (data) {
      case "裁剪AOI":
        clipAoi();
        break;
      case "重置AOI":
        resetAoi();
        break;

      default:
        break;
    }
  });
});

// 页面销毁前
onBeforeUnmount(() => {
  //   销毁
  EventBus.off("header");
  if (_viewer) {
    _viewer.destroy();
  }
});
</script>

<style lang="scss" scoped>
#CesiumMapOne {
  width: 100%;
  height: 100%;

  overflow: hidden;
}

.cesium-lnglat-info {
  width: 290px;
  height: 46px;

  font-weight: 600;
  font-size: 18px;
  color: #3bde80;

  display: flex;
  justify-content: center;
  align-items: center;

  border-radius: 23px;
  border: 1px solid #fff;

  background-color: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(10px);
  /* 背景模糊效果 */

  position: absolute;
  bottom: 30px;
  right: 30px;

  z-index: 10;
}
</style>

部分代码描述

  • coordinates是矩形的坐标,它使用callbackProperty来动态更新

  • callbackProperty是一个特殊的属性类型,用于允许属性值动态更新。回调函数返回的是 pointsArr,它表示矩形的坐标数组。

  • 第二个参数 false 表示该回调函数的更新频率是静态的(即不需要每帧都更新),只有当 this.posArr 发生变化时才会重新计算。

标签:viewer,lat,let,Vue3,Cesium,lng,矩形,startPoint
From: https://blog.csdn.net/weixin_59259086/article/details/142259691

相关文章

  • SpringBoot+Vue3项目邮箱验证码注册详细教程
    引言该篇文章是以SpringBoot+Vue3技术栈搭建的项目的邮箱注册登录流程,注册用户使用邮箱校验,使用qq邮箱发送验证码,并且把验证码存入Redis以备校验使用的详细介绍干货部分1.在SpringBoot项目的application.yaml文件中配置qq邮箱spring:#mail邮箱mail:#SMTP......
  • Vue3中组件通信的几种方式
    Vue3组件通信和Vue2的区别:移出事件总线,使用mitt代替。vuex换成了pinia。把.sync优化到了v-model里面了。把$listeners所有的东西,合并到$attrs中了。$children被砍掉了。【1】props概述:props是使用频率最高的一种通信方式,常用与:父↔子。若父传子:属性值是非函数。若子传父:属性......
  • Vue3中Pinia存储和修改数据应用实践
    安装pinia:npminstallpiniamain.ts中使用pinia://引入createApp用于创建应用import{createApp}from'vue'//引入App根组件importAppfrom'./App.vue'//引入路由器importrouterfrom'./router'//创建一个应用constapp=createApp(App)//使用路由器app.use......
  • Vue3中路由传参的几种方式实践
    【1】RouterLink+query父组件脚本如下:<scriptsetuplang="ts"name="News">import{reactive}from'vue'import{RouterView,RouterLink}from'vue-router'constnewsList=reactive([{id:'asfdtrfay01',......
  • Vue2/Vue3中编程式路由导航实践总结
    【1】Vue2编程式路由导航①router.push除了使用<router-link>创建a标签来定义导航链接,我们还可以借助router的实例方法,通过编写代码来实现。router.push(location,onComplete?,onAbort?)注意:在Vue实例内部,你可以通过$router访问路由实例。因此你可以调用this.$router......
  • vscode下vue3+vite+ts+eslint项目配置
    一、创建项目pnpmcreatevue@latest注意:是否引入ESLint用于代码质量检测?选择否二、安装依赖pnpmi-Deslint@antfu/eslint-config三、在项目根目录创建文件:eslint.config.js//eslint.config.jsimportantfufrom'@antfu/eslint-config'exportdefaultantfu({......
  • Vue3 + Echarts 实现中国地图
    基本概念    echarts是一个基于JavaScript的开源可视化库,用于创建和展示各种交互式图表和图形。它可以用于数据分析、数据可视化、数据探索和数据报告等方面。我们一般使用echarts来实现数据可视化,本文我们使用vue3+echars来实现中国地图。准备echarts基本结构首......
  • vue3 登录页视频背景 开发
    方法比较笨,可以参考,思路如下:    我把这个页面看成三层。最里面是视频,中间挂个蒙板,然后最上层放内容,这样简单粗暴的达到效果 然后来说说中间这个蒙板吧,主要是两个想法,      一个就是客户,领导们的想法比较多,如果仅仅只是说有个视频虚化啥的,有可能并不能完全解......
  • MATLAB:rect 矩形函数
    rect函数functiony=rect(x)%初始化输出数组y,大小与输入x相同,初始值为0%当|x|<=0.5时,函数值为1;否则为0。y=zeros(size(x));y(abs(x)<=0.5)=1;end示例:%定义时间向量,范围从-1到1,步长为0.01t=-1:0.01:1;%调用rect函数计算矩形脉冲的值y=rect(......
  • 程序员的 AI 启蒙:ChatGPT+ Copilot开发Vue3 仿简书项目 90%代码AI生成
    在人工智能技术日益成熟的今天,程序员们正在迎来一场全新的编程革命。ChatGPT和Copilot等AI工具的出现,让代码生成不再是遥不可及的梦想。本文将带你体验如何利用这些先进技术,仅用90%的代码量,开发出一个基于Vue3的仿简书项目,感受AI在编程领域的革新力量。一、引言ChatGPT和C......