【WebGis开发 - Cesium】三维可视化项目教程---图层管理拓展图层顺序调整功能

目录

  • 引言
  • 一、为什么要开发图层顺序调整功能
  • 二、开发思路整理
    • 1. 拖拽库方案选择
    • 2. cesium图层api查询
  • 三、代码编写
    • 1. 编写拖拽组件代码
    • 2. 修改原有图层管理代码
      • 2.1 图层加载移除的调整
      • 2.2 图层顺序与拖拽列表的矛盾
    • 3. 编写图层移动代码
  • 四、总结

引言

本教程主要是围绕Cesium这一开源三维框架开展的可视化项目教程。总结一下相关从业经验,如果有什么疑问或更好的见解,欢迎评论、私聊探讨,共同进步。教程依托于vue3前端框架,参考初始化内容:【WebGis开发 - Cesium】三维可视化项目教程—初始化场景

在【WebGis开发 - Cesium】三维可视化项目教程—图层管理基础 文中我们已经搭建了图层管理的基础框架代码。在本篇中我们将针对二维图层的叠加问题,拓展图层顺序调换功能。


一、为什么要开发图层顺序调整功能

cesium中二维图层由 ImageryLayerCollection 对象存储。二维图层没有高度,按照加载先后顺序重叠在一起。如果内容存在遮挡,则只显示最后加载的图层(好比一摞画册只能看到最上边的一幅画)。开发图层顺序调整功能就好比切牌,将最底下的图层切到上层,或者把最上层的图层切到下层,图层在 ImageryLayerCollection 中的 index 值越大,层级越靠上(越优先被看到)。


二、开发思路整理

首先整理一下要实现这个功能需要准备哪些东西:

  • 切换图层顺序最直观的操作方式就是鼠标拖拽切换顺序,所以需要一个前端的拖拽功能。
  • 直接拖拽图层树节点会导致数据错乱且逻辑复杂,最佳的体验方式是将已经加载的二维图层以列表形式单独展示并支持拖拽。
  • 查询cesium官方是否存在调整图层顺序的api接口,方便我们整合为通用方法。

1. 拖拽库方案选择

开发一个拖拽库的成本较高,不如直接选择成熟的开源拖拽库:

  1. Draggable
    • 项目地址:https://github.com/Shopify/draggable
    • 在线演示:https://shopify.github.io/draggable/examples/
  2. Sortablejs
    • 项目地址:https://github.com/SortableJS/Sortable
    • 在线演示:https://sortablejs.github.io/Sortable/

本项目基于vue3.5.6前端框架开发,为了方便开发,我选择了Sortablejs的vue3版本插件 vue.draggable.next

在项目根目录下打开cmd输入:

yarn add vuedraggable@next
或
npm i -S vuedraggable@next

2. cesium图层api查询

在cesium的api文档页面中搜索 ImageryLayerCollection 查询相关图层方法

文档地址:cesium api 文档

根据我们的需求,我们需要图层查询方法以及排序方法如图所示:

  • 查询图层方法
    在这里插入图片描述
  • 排序图层方法
    在这里插入图片描述
    在这里插入图片描述

三、代码编写

1. 编写拖拽组件代码

在原有图层管理的页面中继续添加拖拽组件

<template><div id="mapContainer"><div class="layerManager"><!-- 图层管理部分代码略 --><div>已选图层</div><draggablev-model="layerStore.imageryLayers"@change="dragChange"item-key="id"ghostClass="ghost"><template #item="{ element }"><div class="dragItem">{{ element.label }}</div></template></draggable></div></div>
</template><script setup>
import draggable from "vuedraggable";
import { useLayerStore } from "@/stores/layer.js";
import { useLayerManager } from "@/hooks/useLayerManager.js";
const layerStore = useLayerStore();
const { changeImageryLayerOrder } = useLayerManager();
/*** @description: 拖拽方法* @param {*} e 拖拽节点返回信息* @return {*}*/
const dragChange = (e) => {const move = e.moved;// 取出拖拽节点的layerId和index变化。const data = {layerId: move.element.layerId,oldIndex: move.oldIndex,newIndex: move.newIndex,};changeImageryLayerOrder(data);
};
</script>

解释下以上代码:

  • 引入 draggable 组件,将组件绑定上 pinia 存储的 imageryLayers 列表,此处需要联动【WebGis开发 - Cesium】三维可视化项目教程—图层管理基础 的全局状态部分内容,忘记的可以回看一下。
  • 绑定 draggable 组件的change事件,将拖拽后的信息收集起来,我们需要imageryLayers中存储的图层 layerId (用于查询图层),和节点拖拽前后列表节点的index变化(用于判断图层移动了多少层)。
  • 将处理后的数据传入 changeImageryLayerOrder 方法中实现图层切换层级顺序。

2. 修改原有图层管理代码

在图层管理基础一文中所写的添加、移除图层的方法只适应图层控制显隐这个单一功能,当添加图层顺序调整时需要对原有代码做出一些调整。

2.1 图层加载移除的调整

在原有的设计逻辑是二维 imageryLayer 图层在移除时不做删除仅作隐藏。当再次加载该图层时,先判断是否存在于 piniaimageryLayers 列表中,如果存在则直接显示不再进行初始化加载以便节省加载时长。

当新增了图层顺序调整的功能后,原有的设计逻辑就不适用了。取消图层选中后,我希望已选图层的拖拽列表中该项消失。然而拖拽列表的数据绑定了imageryLayers 列表,原有的设计逻辑并不会移除 imageryLayers 列表中的该项,所以在拖拽列表中会存在一个已经取消勾选的图层。

在明白了这个逻辑后,对原有的加载移除方法进行修改:

调整stores/layer.js文件内容:

import { defineStore } from "pinia";
export const useLayerStore = defineStore("LayerStore", {
// 其他内容略actions: {// 其他内容略// 新增移除图层信息方法removeImageryLayer(id) {this.imageryLayers = this.imageryLayers.filter((item) => item.id !== id);},},
});

调整hooks/useLayerManager.js文件内容:

  const addWmtsLayer = (data) => {// 直接注释加载前判断是否存在的代码逻辑  *******************************************// // 先查询是否已经加载图层// const layerData = layerStore.getImageryLayer(data.id);// // 存在图层数据直接显示图层, 并返回// if (layerData) {//   //  获取图层数据并设置显示为false//   //   const layer = viewer.imageryLayers.get(layerData.layerId);//   //  获取图层数据并设置显示为false//   const layer = viewer.imageryLayers._layers.find(//     (item) => item.layerId === layerData.layerId//   );//   layer.show = true;//   layerData.show = true;//   return;// }const imageMap = new Cesium.WebMapTileServiceImageryProvider({url: data.url,});// 添加图层const layer = viewer.imageryLayers.addImageryProvider(imageMap);layer.layerId = GenerateId(18);// 向全局状态输入图层数据layerStore.addImageryLayer({ ...data, show: true, layerId: layer.layerId });};/*** @description: 移除wmts图层* @param {*} data* @return {*}*/const removeWmtsLayer = (data) => {const layerData = layerStore.getImageryLayer(data.id);if (layerData) {//  获取图层数据并设置显示为falseconst layer = viewer.imageryLayers._layers.find((item) => item.layerId === layerData.layerId);// 移除图层控制隐藏逻辑// layer.show = false;// layerData.show = false;// 新增图层删除逻辑viewer.imageryLayers.remove(layer);// 新增pinia中removeImageryLayer方法,将图层数据从imageryLayers列表中移除layerStore.removeImageryLayer(data.id);}};

看下此时的效果,已经可以正确的将图层控制与拖拽列表联动

在这里插入图片描述

2.2 图层顺序与拖拽列表的矛盾

这里有个逻辑矛盾。当新增图层时,我们会在 imageryLayers 列表中推入一个图层信息数据,正序排列。然而在已选图层列表里我们希望新增加的在最上边,感官上代表该图层在最上方。

调整stores/layer.js文件内容:

import { defineStore } from "pinia";
export const useLayerStore = defineStore("LayerStore", {
// 其他内容略actions: {// 其他内容略addImageryLayer(data) {// 移除末尾推入数据的方法// this.imageryLayers.push(data);// 修改为头部推入数据this.imageryLayers.unshift(data);},},
});

这样拖拽列表的顺序就和感官上保持一致了。

3. 编写图层移动代码

在hooks/useLayerManager.js文件中继续添加方法,注意最后将方法导出:

  /*** @description: 二维图层移动方法* @param { Object } data 包含layerId、newIndex、oldIndex* @return {*}*/const changeImageryLayerOrder = (data) => {// 获取图层const layer = viewer.imageryLayers._layers.find((item) => item.layerId === data.layerId);const diff = data.newIndex - data.oldIndex;if (diff > 0) {// 向下移动//   判断移动多少层// if (data.newIndex == layerStore.imageryLayers.length - 1) {//   // 移动到最底部//   console.log("移动到最底部");//   viewer.imageryLayers.lowerToBottom(layer);// } else {// 移动到中间态console.log("移动到中间态");for (let i = 0; i < Math.abs(diff); i++) {viewer.imageryLayers.lower(layer);}// }} else {// 向上移动if (data.newIndex == 0) {// 移动到顶部console.log("移动到顶部");viewer.imageryLayers.raiseToTop(layer);} else {// 移动到中间态console.log("移动到中间态");for (let i = 0; i < Math.abs(diff); i++) {viewer.imageryLayers.raise(layer);}}}};

解释下以上代码:

  • 首先通过 layerIdviewer.imageryLayers 中查询到指定图层。
  • 计算图层拖拽前后的index变化 diff
    • 当diff大于0,说明新的图层位置的序号大于原有的位置的序号(注意这里的序号仅为拖拽列表的排序号)需要图层向下移动。
    • 当diff小于0,说明新的图层位置的序号小于原有的位置的序号(注意这里的序号仅为拖拽列表的排序号)需要图层向上移动。
    • 因为cesium提供的移动图层方法为 lowerraise,所以无需关心图层具体在 viewer.imageryLayers 的图层序号。这里的图层序号和拖拽列表的图层序号在概念上是完全相反的。不过幸运的是你无需关心这里的差别也可以根据字面含义的方法正确的操作图层顺序。
  • diff的数值大小代表需要图层需要移动多少次,以循环的方式完成操作。
  • 当newIndex 值为0时表示图层需要移动到最顶部,所以直接使用 raiseToTop 方法直接移动到顶部。
  • 一开始我也尝试判断newIndex 值和图层总数的关系,判断是否直接使用 lowerToBottom 移动到最底部。然而我发现,cesium会在场景初始化时默认添加一个imageryLayer。所以判断newIndex 值和图层总数永远不会相等(天然少一个)。

以上即完成了图层移动层级的功能拓展,看下效果:
在这里插入图片描述


四、总结

本篇主要是利用 vue.draggable.next 组件库结合cesium图层调整顺序api方法,完成了图层管理已选二维图层顺序调整的功能模块。根据功能拓展的需求,将原有图层管理操作逻辑进行修改完善以适应新功能的接入。重点在于根据业务的需求逻辑,封装cesium提供的原始api方法,形成维度更高的项目级api方法。

再接再厉~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/883326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解InnoDB底层原理:从数据结构到逻辑架构

💡 无论你是刚刚踏入编程世界的新人,还是希望进一步提升自己的资深开发者,在这里都能找到适合你的内容。我们共同探讨技术难题,一起进步,携手度过互联网行业的每一个挑战。 📣 如果你觉得我的文章对你有帮助,请不要吝啬你的点赞👍分享💕和评论哦! 让我们一起打造…

ctfshow(259->261)--反序列化漏洞--原生类与更多魔术方法

Web259 进入界面&#xff0c;回显如下&#xff1a; highlight_file(__FILE__);$vip unserialize($_GET[vip]); //vip can get flag one key $vip->getFlag();题干里还提示了网站有一个flag.php界面&#xff0c;源代码如下&#xff1a; $xff explode(,, $_SERVER[HTTP_X…

常见的音视频格式介绍

目录 aac格式介绍&#xff08;ADTS&#xff09;h264格式分析FLV和MP4格式介绍 aac格式介绍&#xff08;ADTS&#xff09; aac的格式有两种&#xff1a;ADIF不常用&#xff0c;ADTS是主流&#xff0c;所以这里主要讲解ADTS。简单来说&#xff0c;ADTS可以在任意帧解码&#xff…

校园表白墙源码修复版

此校园表白墙源码基于thinkphp&#xff0c;因为时代久远有不少bug&#xff0c;经本人修复已去除大部分bug&#xff0c;添加了美化元素。 https://pan.quark.cn/s/1f9b3564c84b https://pan.baidu.com/s/1bb9vu9VV2jJoo9-GF6W3xw?pwd7293 https://caiyun.139.com/m/i?2hoTc…

多款云存储平台存在安全漏洞,影响超2200万用户

据苏黎世联邦理工学院研究人员Jonas Hofmann和Kien Tuong Turong的发现&#xff0c;端到端加密&#xff08;E2EE&#xff09;云存储平台存在一系列安全问题&#xff0c;可能会使用户数据暴露给恶意行为者。在通过密码学分析后&#xff0c;研究人员揭示了Sync、pCloud、Icedrive…

三维管线管网建模工具MagicPipe3D V3.5.3

经纬管网建模系统MagicPipe3D&#xff0c;本地离线参数化构建地下管网三维模型&#xff08;包括管道、接头、附属设施等&#xff09;&#xff0c;输出标准3DTiles、Obj模型等格式&#xff0c;支持Cesium、Unreal、Unity、Osg等引擎加载进行三维可视化、语义查询、专题分析&…

【Android】MVP架构

MVP架构简介 MVP&#xff08;Model-View-Presenter&#xff09;是一种常见的软件架构模式&#xff0c;尤其在Android应用开发中被广泛使用。它将应用程序分为三层&#xff1a;Model、View 和 Presenter&#xff0c;以实现职责分离&#xff0c;提高代码的可维护性和可测试性。 …

基于自适应VSG控制的光伏混合储能构网型逆变系统MATLAB仿真模型

模型简介 此模型源侧部分采用光伏发电系统与混合储能系统&#xff08;蓄电池超级电容&#xff09;&#xff0c;并网逆变器采用虚拟同步发电机&#xff08;VSG&#xff09;控制&#xff0c;为系统提供惯量阻尼支撑。同时对VSG控制部分进行了改进&#xff0c;采用构造函数法对虚…

论文阅读(二十九):Multi-scale Interactive Network for Salient Object Detection

文章目录 Abstract1.Introduction2.Scale VariationProposed Method3.1Network Overview3.2Aggregate Interaction Module3.3 Self-Interaction Module3.4Consistency-Enhanced Loss 4.Experiments4.1Implementation Details4.2 Comparison with State-of-the-arts4.3Ablation …

【力扣】[Java版] 刷题笔记-21. 合并两个有序链表

题目&#xff1a; 21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 解题思路 从题目和示例可以看出&#xff0c;应该是要循环遍历链表进行比较&#xff0c;然后组成新的链表。 第一种&#xff1a;递归…

存储过程(SQL)

1.存储过程 存储过程&#xff08;Stored Procedure&#xff09;是一组为了完成特定功能的SQL语句集&#xff0c;经编译后存储在数据库中&#xff0c;用户通过指定存储过程的名字并给定参数&#xff08;如果该存储过程带有参数&#xff09;来调用执行它。 2.MySQL存储过程创建…

PostgreSQL的前世今生

PostgreSQL的起源可以追溯到1977年的加州大学伯克利分校&#xff08;UC Berkeley&#xff09;的Ingres项目。该项目由著名的数据库科学家Michael Stonebraker领导&#xff0c;他是2015年图灵奖的获得者。以下是PostgreSQL起源的详细概述&#xff1a; 一、早期发展 Ingres项目…

LabVIEW换流变换器智能巡检系统

基于LabVIEW的换流变换器智能巡检系统通过自动化检测和数据分析&#xff0c;提高换流变换器的运行效率和可靠性&#xff0c;降低人工维护成本。 项目背景&#xff1a; 换流变压器作为电力系统的重要组成部分&#xff0c;其性能的可靠性直接影响到整个电网的稳定运行。然而&…

完美解决phpstudy安装后mysql无法启动

phpstudy数据库无法启动有以下几个原因。 一、自己在电脑上安装了MySQL数据库,MySQL的服务名为MySQL,这会与phpstudy的数据库的服务名发生冲突&#xff0c;从而造成phpstudy中的数据库无法启动&#xff0c;这时我们只需要将自己安装的MySQL的服务名改掉就行。 但是&#xff0…

软件测试的重要一环:「性能测试」怎么做?

性能测试是软件测试中的重要一环&#xff0c;今天给大家介绍性能测试及如何使用RunnerGo完成性能测试任务。 性能测试是什么&#xff1f; 一句话概括&#xff1a;不断地通过不同场景的系统表现去探究系统设计与资源消耗之间的平衡&#xff0c;为开发人员提供消除瓶颈所需的诊…

Ajax:表单 模板引擎

Ajax&#xff1a;表单 & 模板引擎 form 表单form 属性 Ajax操控表单事件监听阻止默认行为收集表单数据 模板引擎art-template{{}}语法原文输出条件输出循环输出过滤器 原理 form 表单 在HTML中&#xff0c;可以通过<form>创建一个表单&#xff0c;收集用户信息。而采…

基于docker 部署redis

1、拉取镜像 docker pull redis:latest如果拉取失败可以尝试下配置镜像源&#xff0c;具体参考如下&#xff0c;目前暂可以使用 Docker切换镜像源-CSDN博客 2、创建配置文件 mkdir /usr/local/redis/conf vim redis.conf bind 0.0.0.0#protected-mode no port 6379 tcp-b…

Fast Simulation of Mass-Spring Systems in Rust 论文阅读

参考资料&#xff1a; Fast Simulation of Mass-Spring Systems in Rust 论文阅读&#xff1a;Fast Simulation of Mass-Spring Systems 【论文精读】讲解刘天添2013年的fast simulation of mass spring system(Projective Dynamics最早的论文) Projective Dynamics笔记(一…

面试经典 150 题 第三周代码

【题目链接】 80. 删除有序数组中的重复项 II 【参考代码】 双指针 class Solution { public:int removeDuplicates(vector<int>& nums) {int size nums.size();if(size < 2){return size;}int slow 2, fast 2;while(fast < size){if(nums[slow-2] ! num…

【C++数学 负进制】1017. 负二进制转换|1697

本文涉及知识点 数学 LeetCode1017. 负二进制转换 给你一个整数 n &#xff0c;以二进制字符串的形式返回该整数的 负二进制&#xff08;base -2&#xff09;表示。 注意&#xff0c;除非字符串就是 “0”&#xff0c;否则返回的字符串中不能含有前导零。 示例 1&#xff1a…