【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.rhkb.cn/news/456989.html

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

相关文章

Linux-Centos操作系统备份及还原(整机镜像制作与还原)--再生龙

适用场景 Linux系统设备需要备份整机数据&#xff0c;或者需要还原到多台设备上。适用再生龙工具进行整机备用和还原。 镜像制作 下载再生龙镜像&#xff1a;clonezilla-live-2.6.4-10-amd64.iso&#xff0c;制作启动盘-设置U盘启动 启动后界面如下选择第四项other modes of…

使用Python来下一场深夜雪

效果图&#xff1a;&#xff08;真实情况是动态的&#xff09; 完整代码&#xff1a; import turtle import random# 初始化画布 turtle.bgcolor("#001f3f") # 偏深蓝色的背景 turtle.title("下雪的画面") turtle.speed(0) turtle.hideturtle() turtle.t…

steam新品节!GameViewr远程随时随地手机平板玩主机游戏教程

Steam平台在10月14日迎来了新品节&#xff0c;你可以尝试即将推出的游戏的免费试用版&#xff0c;将他们加入愿望单&#xff0c;像是《迷失之径》《贪婪大地》《疯狂手机大亨》等等。不知道大家是否已经选择好自己心怡的游戏呢&#xff1f;要是你想随时随地体验steam新品节的游…

WebStorm EsLint报红色波浪线

如图左侧。 这个错误是由于 ESLint 和 Prettier 的配置不一致导致的。它建议你移除多余的空格。以下是一些解决方法&#xff1a; 安装 Prettier 插件&#xff1a; 确保你在 WebStorm 中安装了 Prettier 插件&#xff0c;并确保它配置正确。 调整 ESLint 配置&#xff1a; 检查…

10340 文本编辑器(vim)

经验值&#xff1a;1600 时间限制&#xff1a;1000毫秒 内存限制&#xff1a;512MB 经开区2023年信息学竞赛试题 不许抄袭&#xff0c;一旦发现&#xff0c;直接清空经验&#xff01; 题目描述 Description 李明正在学习使用文本编辑器软件 Vim。与 Word、VSCode 等常用的…

qt QNetworkProxy详解

一、概述 QNetworkProxy通过设置代理类型、主机、端口和认证信息&#xff0c;可以使应用程序的所有网络请求通过代理服务器进行。它支持为Qt网络类&#xff08;如QAbstractSocket、QTcpSocket、QUdpSocket、QTcpServer、QNetworkAccessManager等&#xff09;配置网络层代理支持…

arthas使用 笔记

下载启动 curl -O https://arthas.aliyun.com/arthas-boot.jarjava -jar arthas-boot.jar基本命令使用 JVM相关命令 Dashboard - 仪表盘 用途&#xff1a;查看当前Java应用的实时性能面板&#xff0c;包括CPU、线程、内存使用情况等。场景&#xff1a;快速概览系统整体健康…

【JAVA】第三张_Eclipse下载、安装、汉化

简介 Eclipse是一种流行的集成开发环境&#xff08;IDE&#xff09;&#xff0c;可用于开发各种编程语言&#xff0c;包括Java、C、Python等。它最初由IBM公司开发&#xff0c;后来被Eclipse Foundation接手并成为一个开源项目。 Eclipse提供了一个功能强大的开发平台&#x…

JavaWeb——Maven(5/8):依赖管理-依赖配置(Maven 项目中的依赖配置、访问仓库网站、配置依赖的注意事项)

目录 依赖配置 Maven 项目中的依赖配置 访问仓库网站 配置依赖的注意事项 接下来&#xff0c;我们了解 Maven 当中的第三方依赖管理。 Maven 第三方依赖管理的重要性 依赖管理是 Maven 这款工具最核心的功能。在依赖管理这部分&#xff0c;我们主要讲解四个方面&#xff…

uniapp一键打包

1.先安装python环境&#xff0c; 2.复制这几个文件到uniapp项目里面 3.修改自己证书路径&#xff0c;配置文件路径什么的 4.在文件夹页面双击buildController.py或者cmd直接输入buildController.py 5.python报错&#xff0c;哪个依赖缺少安装哪个依赖 6.执行不动的话&…

语音提示器-WT3000A离在线TTS方案-打破语种限制/AI对话多功能支持

前言&#xff1a; TTS&#xff08;Text To Speech &#xff09;技术作为智能语音领域的重要组成部分&#xff0c;能够将文本信息转化为逼真的语音输出&#xff0c;为各类硬件设备提供便捷的语音提示服务。本方案正是基于唯创知音的离在线TTS&#xff08;离线本地音乐播放与在线…

STM32--基于STM32F103C8T6的OV7670摄像头显示

本文介绍基于STM32F103C8T6实现的OV7670摄像头显示设计&#xff08;完整资源及代码见文末链接&#xff09; 一、简介 本文实现的功能&#xff1a;基于STM32F103C8T6实现的OV7670摄像头模组实时在2.2寸TFT彩屏上显示出来 所需硬件&#xff1a; STM32F103C8T6最小系统板、OV76…

HivisionIDPhoto Docker部署以及Springboot接口对接(AI证件照制作)

项目简介 项目以及官方文档地址 HivisionIDPhoto 旨在开发一种实用、系统性的证件照智能制作算法。 它利用一套完善的AI模型工作流程&#xff0c;实现对多种用户拍照场景的识别、抠图与证件照生成。 HivisionIDPhoto 可以做到&#xff1a; 轻量级抠图&#xff08;纯离线&a…

Mysql主主互备配置

在现有运行的mysql环境下&#xff0c;修改相关配置项&#xff0c;完成主主互备模式的部署。 下面的配置说明中设置的mysql互备对应服务器IP为&#xff1a; 192.168.1.6 192.168.1.7 先检查UUID 在mysql的数据目录下&#xff0c;检查主备mysql的uuid&#xff08;如下的server-…

Unity实现DBSCAN

参考连接 直接上代码&#xff0c;把脚本挂载到场景中的物体上&#xff0c;运行应该就就能看到效果。 using System.Collections; using System.Collections.Generic; using UnityEngine;public class TestDBSCAN : MonoBehaviour {private List<GameObject> goList new…

【ARM】ARM架构参考手册_Part B 内存和系统架构(5)

目录 5.1关于缓存和写缓冲区 5.2 Cache 组织 5.2.1 集联性&#xff08;Set-associativity&#xff09; 5.2.2 缓存大小 5.3 缓存类型 5.3.1 统一缓存或分离缓存 5.3.2 写通过&#xff08;Write-through&#xff09;或写回&#xff08;Write-back&#xff09;缓存 5.3.3…

BFS解决FloodFill算法(4)_被围绕的区域

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 BFS解决FloodFill算法(4)_被围绕的区域 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c…

【R + Python】iNaturalist 网站图片下载 inat api

文章目录 一、iNaturalist 简介二、R语言API&#xff1a;rinat三、示例3.1 获取观测数据3.2 绘制可视化图像函数用法 3.4 在区域网格中搜索3.5 下载图片3.51 提取图片 url3.52 下载图片: R语言3.53 下载图片: python 四、获取详细rinat包的文档 一、iNaturalist 简介 &#x1…

8.three.js相机详解

8.three.js相机详解 1、 认识相机 在Threejs中相机的表示是THREE.Camera&#xff0c;它是相机的抽象基类&#xff0c;其子类有两种相机&#xff0c;分别是正投影相机THREE.OrthographicCamera和透视投影相机THREE.PerspectiveCamera&#xff1a; 正投影和透视投影的区别是&am…

深度学习技术演进:从 CNN、RNN 到 Transformer 的发展与原理解析

深度学习的技术演进经历了从卷积神经网络&#xff08;CNN&#xff09;到循环神经网络&#xff08;RNN&#xff09;再到 Transformer 的重要发展。这三个架构分别擅长处理图像、序列数据和多种任务的特征&#xff0c;标志着深度学习在不同领域取得的进步。 1. 卷积神经网络&…