CesiumJS整合ThreeJS插件封装

2024-06-21 09:04

本文主要是介绍CesiumJS整合ThreeJS插件封装,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近做项目有一个三维需求使用CesiumJS比较难以实现,发现THREEJS中效果比较合适,于是准备将THREEJS整合到CesiumJS中

为实现效果所需我们找到官方Integrating Cesium with Three.js博客,于是根据该博客提供的思路去实现整合

文章目录

    • 一、创建ThreeJS类
    • 二、插件threeJs 优化
      • 1、创建ThressScene工具
        • 1.1、同步camera
        • 1.2、同步场景中的物体
        • 1.3、同步render
      • 2、插件使用
        • 2.1 引入插件初始化map
        • 2.1 初始化Meshes
        • 2.2 初始化threeScene
        • 2.3 效果预览

一、创建ThreeJS类

为了开发时更好的扩展性把他写到了一个ThreeJS 类里面,功能直接调用即可

function ThreeJs(viewer, cesiumGlobal, defaultStatic, threeConf) {if (viewer && threeConf) {const { threeGlobal, containerId, threeContainerId } = threeConf;Cesium = cesiumGlobal;THREE = threeGlobal;this._viewer = viewer;this._containerId = containerId;this._threeContainerId = threeContainerId;this._initContainer();this._initThree();}
}
//部分省略......

项目中使用

import { ThreeJs } from 'cesium_dev_kit'// 初始化mapinitMap (){const ThreeJsObj = new ThreeJs({cesiumGlobal: Cesium,threeGlobal: THREE,containerId: 'cesiumContainer',threeContainerId: 'threeContainer',
//部分省略......})this.c_viewer = ThreeJsObj.viewer;this.threeJs = ThreeJsObj.threeJs;this.initThree(this.threeJs);},// 初始化ThreeJsinitThree (ThreeJs) {const threeDObject = this.create3DOject(ThreeJs, this.c_viewer);ThreeJs.addThreeObjects(threeDObject)this.c_viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)//解除视角锁定},// 创建三维模型create3DOject (threeObj, viewer) {let three = threeObj._three;let _3Dobjects = [], _3DOB;let entity = {name: 'Polygon',polygon: {hierarchy: Cesium.Cartesian3.fromDegreesArray([minWGS84[0], minWGS84[1],maxWGS84[0], minWGS84[1],maxWGS84[0], maxWGS84[1],minWGS84[0], maxWGS84[1]]),material: Cesium.Color.RED.withAlpha(0.1)}}let Polypon = viewer.entities.add(entity);let doubleSideMaterial = new THREE.MeshNormalMaterial({side: THREE.DoubleSide});
//部分省略......return _3Dobjects;}   

根据官网的思量整合后最终实现效果如下
实现效果
效果是实现了,但是这个封装耦合性相当高,多个功能都需要使用这个插件时特别蹩脚,于是开始了下一次造…

二、插件threeJs 优化

理解官方案例的思路整合关键主要有三个方面,第一个是同步Camera,第二个是同步Scene中的物体位置,第三个是需要同步CesiumJS和THREEJS 的render重绘程序

1、创建ThressScene工具

为了扩展与管理我们抽离一个Scene 的工具js

class Scene extends THREE.Scene {}

在这个js 里面去实现插件操作的优化

1.1、同步camera

创建一个updateCameraMatrix来同步项目位置,核心代码如下

  updateCameraMatrix() {//同步相机this.camera.fov = Cesium.Math.toDegrees(this.cesiumViewer.camera.frustum.fovy) // ThreeJS FOV is verticalthis.camera.updateProjectionMatrix()this.camera.matrixAutoUpdate = falseconst cvm = this.cesiumViewer.camera.viewMatrixconst civm = this.cesiumViewer.camera.inverseViewMatrixthis.camera.lookAt(this.cameraCenter)
//部分省略......const width = this.cesiumViewer.scene.canvas.clientWidthconst height = this.cesiumViewer.scene.canvas.clientHeightthis.camera.aspect = width / heightthis.camera.updateProjectionMatrix()this.renderer.setSize(width, height)return this}
1.2、同步场景中的物体

创建一个updateGroupMatrixWorld来进行物体位置同步,核心代码如下

	 // 重写add 方法add(object) {if (arguments.length > 1) {for (let i = 0; i < arguments.length; i++) {this.childrenGroup.add(arguments[i])}return this}//部分省略......return this}updateGroupMatrixWorld() {// 得到面向模型的前向方向const center = this.cartesian3ToVector(Cesium.Cartesian3.fromDegrees(this.lngLat[0], this.lngLat[1], 0))// 使用从左下到左上的方向作为上向量const topLeft = this.cartesian3ToVector(Cesium.Cartesian3.fromDegrees(this.lngLat[0], this.lngLat[1], 2))const latDir = new THREE.Vector3().subVectors(center, topLeft).normalize()// 配置实体的位置和方向// this.syncGroup.position.copy(center)this.syncGroup.lookAt(latDir)this.syncGroup.up.copy(latDir)this.syncGroup.updateMatrix()this.cameraOffset.copy(center)this.sphere.position.set(0 - center.x, 0 - center.y, 0 - center.z)this.syncGroup.up.set(0, 0, -1)this.up.set(0, 0, -1)return this}
1.3、同步render
    renderCesium() {this.cesiumViewer.render()return this}renderThree() {this.renderer.render(this, this.camera)return this}loop(callback) {const _loop = function () {let time = requestAnimationFrame(_loop)callback && callback(time)}_loop()}

2、插件使用

插件改完了心里还是有点鸡冻,马上在项目中引入开始测试

2.1 引入插件初始化map
import { initCesium } from 'cesium_dev_kit'// 初始化mapinitMap (){const { viewer, threeJs, base, graphics, material } = new initCesium({cesiumGlobal: Cesium,threeGlobal: THREE,containerId: 'cesiumContainer',threeContainerId: 'threeContainer',//部分省略......})this.c_viewer = viewer;this.threeJs = threeJs;this.base = base;this.graphics = graphics;this.material = materialthis.initThree(this.threeJs);// this.getClickPosition()this.createAEllipsoid();this.createAFanShape();},
2.1 初始化Meshes

这里我们就使用官方的extrude案例

    initMeshes (scene) {// 环形 extrudeconst closedSpline = new THREE.CatmullRomCurve3([new THREE.Vector3(-60, 30, 60), // 左下new THREE.Vector3(-60, 100, 60), // 左中new THREE.Vector3(-60, 220, 60), // 左上new THREE.Vector3(60, 80, -60), // 右中new THREE.Vector3(60, 30, -60), // 右下]);// 2、extrude settingsclosedSpline.curveType = "catmullrom";closedSpline.closed = true;const extrudeSettings = {steps: 100,bevelEnabled: false,extrudePath: closedSpline,};// 3、construct shapeconst r = 20; // 截面半径const pts1 = [];const count = 3; // 截面的棱边数量for (let index = 0; index < count; index++) {// index/count 几分之几,2π为周长const a = (index / count) * Math.PI * 2;pts1.push(new THREE.Vector2(r * Math.cos(a), r * Math.sin(a)));}const shape1 = new THREE.Shape(pts1);// create geometryconst geometry1 = new THREE.ExtrudeGeometry(shape1, extrudeSettings);// create materialconst material1 = new THREE.MeshLambertMaterial({color: 0xb00000,});// assembly meshesconst mesh1 = new THREE.Mesh(geometry1, material1);// add mesh to scenescene.add(mesh1);//部分省略......},
2.2 初始化threeScene
    initThree (ThreeJs) {const { scene, camera } = ThreeJs.initThree({ center, axesHelper: true, threeHabit: false });this.initLight(scene, camera)this.initMeshes(scene);this.flyto(scene);ThreeJs.loop(function () {scene.update();})},
2.3 效果预览

光线投射
光线投射 图形挤压图形挤压烟花效果
烟花效果

奔跑的士兵
奔跑的士兵

嗯嗯测试了几个功能看了基本上问题不大了,ok先告一段落后期继续优化…

感谢您的阅读,最后附上插件下载与源码地址

  • 插件下载安装
npm install cesium_dev_kit
  • 案例源码地址
    https://github.com/dengxiaoning/cesium_dev_kit

这篇关于CesiumJS整合ThreeJS插件封装的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1080784

相关文章

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

SpringBoot整合DeepSeek实现AI对话功能

《SpringBoot整合DeepSeek实现AI对话功能》本文介绍了如何在SpringBoot项目中整合DeepSeekAPI和本地私有化部署DeepSeekR1模型,通过SpringAI框架简化了... 目录Spring AI版本依赖整合DeepSeek API key整合本地化部署的DeepSeek

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

Ollama整合open-webui的步骤及访问

《Ollama整合open-webui的步骤及访问》:本文主要介绍如何通过源码方式安装OpenWebUI,并详细说明了安装步骤、环境要求以及第一次使用时的账号注册和模型选择过程,需要的朋友可以参考... 目录安装环境要求步骤访问选择PjrIUE模型开始对话总结 安装官方安装地址:https://docs.

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题小结

《SpringBoot整合ShedLock处理定时任务重复执行的问题小结》ShedLock是解决分布式系统中定时任务重复执行问题的Java库,通过在数据库中加锁,确保只有一个节点在指定时间执行... 目录前言什么是 ShedLock?ShedLock 的工作原理:定时任务重复执行China编程的问题使用 Shed

SpringBoot 整合 Grizzly的过程

《SpringBoot整合Grizzly的过程》Grizzly是一个高性能的、异步的、非阻塞的HTTP服务器框架,它可以与SpringBoot一起提供比传统的Tomcat或Jet... 目录为什么选择 Grizzly?Spring Boot + Grizzly 整合的优势添加依赖自定义 Grizzly 作为

springboot整合gateway的详细过程

《springboot整合gateway的详细过程》本文介绍了如何配置和使用SpringCloudGateway构建一个API网关,通过实例代码介绍了springboot整合gateway的过程,需要... 目录1. 添加依赖2. 配置网关路由3. 启用Eureka客户端(可选)4. 创建主应用类5. 自定

springboot整合 xxl-job及使用步骤

《springboot整合xxl-job及使用步骤》XXL-JOB是一个分布式任务调度平台,用于解决分布式系统中的任务调度和管理问题,文章详细介绍了XXL-JOB的架构,包括调度中心、执行器和Web... 目录一、xxl-job是什么二、使用步骤1. 下载并运行管理端代码2. 访问管理页面,确认是否启动成功

SpringBoot整合kaptcha验证码过程(复制粘贴即可用)

《SpringBoot整合kaptcha验证码过程(复制粘贴即可用)》本文介绍了如何在SpringBoot项目中整合Kaptcha验证码实现,通过配置和编写相应的Controller、工具类以及前端页... 目录SpringBoot整合kaptcha验证码程序目录参考有两种方式在springboot中使用k