Vue2 为例
#安装
npm install threejs
完整代码:已封装成组件,只需要通过组件传参数url即可渲染点云图(基础版)
<template>
<div ref="threeDemo" style="height: 100%; width: 100%">
<div id="PcdThree" style="height: 100%; width: 100%"></div>
</div>
</template>
<script>
// 引入Three.js
import * as THREE from "three";
// 引入PCD加载器
import { PCDLoader } from "three/examples/jsm/loaders/PCDLoader.js"; // 注意是examples/jsm
// 引入模型控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 放大缩小旋转等控制操作
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 创建一个时钟对象Clock
var clock = new THREE.Clock();
// 设置渲染频率为30FBS,也就是每秒调用渲染器render方法大约30次
var FPS = 30;
var renderT = 1 / FPS; //单位秒 间隔多长时间渲染渲染一次
// 声明一个变量表示render()函数被多次调用累积时间
// 如果执行一次renderer.render,timeS重新置0
var timeS = 0;
var scene; //
var mesh; //网格模型对象
export default {
components: {},
name: "PcdThree",
props: ['url'],
data() {
return {
animationId: null, //
isShowLoading: false,
elem: null,
camera: null, //相机对象
renderer: null, //渲染器对象
loader: null,
controls: null,
addURL: "/pcd/CloudPoint_20231017140135.pcd",// 点云图地址
modelStatus: false,
};
},
beforeDestroy() {
this.destroyModel();
window.removeEventListener("resize", this.resMode);
},
created() {},
mounted() {
// 初始化模型
this.initModel(this.addURL, "PcdThree");
window.addEventListener("resize", ()=>this.resMode(this.addURL));
},
watch: {
url: {
handler: async function (newValue, oldValue) {
if(newValue){
this.addURL = newValue;
if(this.modelStatus){
this.resMode(newValue);
}
}
},
immediate: true
},
},
methods: {
async resMode(value) {
if(this.controls != null){
this.controls.removeEventListener("change", this.animate);
}
await this.scene.traverse(function (v) {
if (v.type === "Mesh") {
v.geometry.dispose();
v.material.dispose();
}
});
while (this.scene.children.length > 0) {
this.scene.remove(this.scene.children[0]);
}
// 重置渲染器输出画布canvas尺寸
this.renderer.setSize(this.elem.clientWidth, this.elem.clientHeight);
// 全屏情况下:设置观察范围长宽比aspect为窗口宽高比
this.camera.aspect = this.elem.clientWidth / this.elem.clientHeight;
// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
this.camera.updateProjectionMatrix();
this.initModelAddress(value);
},
initModel(pcdPath, domName) {
// console.log("开始初始化模型文件");
this.modelStatus = true;//组件加载完毕
this.elem = document.getElementById(domName); // 相机CanvasRenderer
this.camera = new THREE.PerspectiveCamera(
20, // 视野
this.elem.clientWidth / this.elem.clientHeight, // 纵横比
0.5, // 近平面
1000 // 远平面
); // 渲染器
// 设置相机位置
this.renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
this.camera.lookAt({
x: 0,
y: 0,
z: 0,
});
this.renderer.setClearColor(new THREE.Color(0x303030)); // 背景色
this.renderer.setSize(this.elem.clientWidth, this.elem.clientHeight);
this.elem.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene(); // 场景
this.loader = new PCDLoader(); //PCD加载器
// // 创建坐标轴辅助器
// var axesHelper = new THREE.AxesHelper( 10 );
// // 添加到场景中
// this.scene.add( axesHelper );
// 初始化模型
// this.initModelAddress(pcdPath);
},
initModelAddress(address) {
console.log("加载PCD文件", this.scene.position);
const THIS = this; //第一层 捕捉报错
try {
//加载PCD文件
THIS.loader.load(
address,
function (points) {
// console.log("加载成功", points);
// 模型点位大小
points.material.size = 0.02;
points.material.color = new THREE.Color(0x00ffff); // 模型颜色
THIS.scene.add(points);
// 构造盒子
var middle = new THREE.Vector3();
points.geometry.computeBoundingBox();
points.geometry.translate(0, 0, 0);
points.geometry.boundingBox.getCenter(middle);
// THIS.camera.position.set(Math.PI / ,0,0)
points.applyMatrix4(
new THREE.Matrix4().makeTranslation(
-middle.x / 1,
-middle.y / 1,
-middle.z / 1
)
); // 比例
var largestDimension = Math.max(
points.geometry.boundingBox.max.x,
points.geometry.boundingBox.max.y,
points.geometry.boundingBox.max.z
);
THIS.camera.position.x = largestDimension * 1;
THIS.camera.position.y = largestDimension * 1;
THIS.camera.position.z = largestDimension * 1;
THIS.animate();
// 调用 OrbitControls 插件实现交互式操作
THIS.controls = new OrbitControls(
THIS.camera,
THIS.renderer.domElement
);
// 把对象放到坐标原点
points.geometry.center();
// 绕轴旋转
points.geometry.rotateX(Math.PI / 2);
points.geometry.rotateY(Math.PI / -4);
// points.geometry.rotateZ(Math.PI / 90);
// 再把对象放回原来的地方
points.geometry.translate(middle.x, middle.y, middle.z);
//调用方式,设置x、y、z轴的旋转
THIS.controls.addEventListener("change", THIS.animate); // 监听鼠标、键盘事件 放大缩小等 // THIS.isShowLoading = false;
},
function (xhr) {
// console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
}, //第二层 捕捉报错
function (error) {
// THIS.isShowLoading = false;
THIS.$Message.error("模型地址不对,请稍候再试!");
}
);
} catch (error) {
// THIS.isShowLoading = false;
THIS.$Message.error("模型地址不对,请稍候再试!");
}
},
// 监听鼠标、键盘事件 放大缩小等
animate() {
this.animationId = requestAnimationFrame(this.animate); //.getDelta()方法获得两帧的时间间隔
var T = clock.getDelta();
timeS = timeS + T; // requestAnimationFrame默认调用render函数60次,通过时间判断,降低renderer.render执行频率
if (timeS > renderT) {
// 控制台查看渲染器渲染方法的调用周期,也就是间隔时间是多少
// console.log(`调用.render时间间隔`, timeS * 1000 + "毫秒");
this.renderer.render(this.scene, this.camera); //执行渲染操作 //renderer.render每执行一次,timeS置0
timeS = 0;
}
}, // 销毁模型
destroyModel() {
console.log("销毁模型");
clearTimeout();
try {
this.scene.traverse(function (v) {
if (v.type === "Mesh") {
v.geometry.dispose();
v.material.dispose();
}
});
while (this.scene.children.length > 0) {
this.scene.remove(this.scene.children[0]);
}
this.scene.clear();
this.renderer.dispose();
this.renderer.clear();
this.renderer.forceContextLoss();
this.renderer.content = null;
this.controls.removeEventListener("change", this.animate);
cancelAnimationFrame(this.animationId); // 去除animationFrame
const gl = this.renderer.domElement.getContext("webgl");
gl && gl.getExtension("WEBGL_lose_context").loseContext();
console.log("销毁成功");
} catch (e) {
console.log("销毁失败");
}
},
},
};
</script>
文章介绍了如何在Vue2应用中使用Three.js库来渲染点云图,包括安装、组件化、PCD文件加载、模型控制器的使用以及动画和销毁模型的方法。
1万+

被折叠的 条评论
为什么被折叠?



