在Vue项目中使用three.js在前端页面展示PLY文件或STL文件
- 其他
- 2025-08-28 18:15:02

前言:这是一个3d打印局域网管理系统的需求
一、安装three.jsthree.js官网: threejs.org/docs/#manual/en/introduction/Installation
我用的是yarn,官网用的是npm
二、使用three.js 1.在script部分导入three.js import * as THREE from 'three'; 2.基础使用=》创建场景:场景是three.js中用于存储所有3D对象的容器。它相当于一个虚拟的3D空间,所有对象(如几何体、灯光等)都会被添加到场景中。
const scene = new THREE.Scene();//创建场景=》创建相机:相机用于定义用户观察场景的视角。这里使用的是PerspectiveCamera,它模拟了真实世界的透视效果。
//创建相机 const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);它的参数分别是:
->FOV(Field of View):视野角度,单位是度。这里设置为75,表示相机能看到的范围。
->宽高比(Aspect Ratio):通常是容器的宽度除以高度。这里使用window.innerWidth / window.innerHeight,确保在场景不同屏幕尺寸下不会变形。
->近裁剪面(Near Clipping Plane):距离相机最近的渲染范围,小于这个值的物体不会被渲染。这里设置为0.1。
->远裁剪面(Far Clipping Plane):距离相机最远的渲染范围,大于这个值的物体不会被渲染。这里设置为1000。
=》创建渲染器:渲染器的作用是将场景渲染到屏幕上。这里使用的是WebGLRenderer,它利用WebGL技术在浏览器中渲染3D图形。setSize方法设置了渲染器的尺寸,通常与浏览器窗口的大小一致。最后,将渲染器的domElement(一个<canvas>元素)添加到HTML文档中。
//创建渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth,window.innerHeight); document.body.appendChild(renderer.domElement);=》创建立方体:
//创建立方体 const geometry = new THREE.BoxGeometry(1,1,1); const material = new THREE.MeshBasicMaterial({color:0x00ff00}); const cube = new THREE.Mesh(geometry,material); scene.add(cube);->几何体(Geometry):定义了对象的形状。这里使用BoxGeometry创建了一个边长为1的立方体。
->材质(Material):定义了对象的外观。这里使用MeshBasicMaterial,并设置颜色为绿色(0x00ff00)。
->网格(Mesh):将几何体和材质组合在一起,形成一个可渲染的对象。最后,将立方体添加到场景中。
=》调整相机位置:默认情况下,相机和立方体都在场景的原点(0, 0, 0)。为了避免它们重叠,将相机沿Z轴向后移动5个单位。
//调整相机位置 camera.position.z = 5;=》动画循环:
//动画循环 function animate(){ cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene,camera); } renderer.setAnimationLoop(animate);->动画逻辑:在animate函数中,每帧更新立方体的旋转角度(rotation.x和rotation.y),使其围绕X轴和Y轴旋转。
->渲染场景:调用renderer.render(scene, camera)将场景渲染到屏幕上。
->循环调用:renderer.setAnimationLoop(animate)会自动调用animate函数,并在浏览器刷新时重新渲染场景,通常每秒60次。
3.综合使用这里创建一个文件名为Three.vue的vue文件
<template> <div ref="threeJsContainer" class="three-js-container"></div> </template> <script> import * as THREE from 'three'; export default { name: 'ThreeJsComponent', mounted() { this.initThreeJs(); }, methods: { initThreeJs() { // 创建场景 const scene = new THREE.Scene(); // 创建相机 const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.z = 5; // 创建渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); // 将渲染器的 canvas 添加到 Vue 组件的 div 中 this.$refs.threeJsContainer.appendChild(renderer.domElement); // 创建立方体 const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const cube = new THREE.Mesh(geometry, material); scene.add(cube); // 动画循环 const animate = () => { cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); }; renderer.setAnimationLoop(animate); } } }; </script> <style scoped> .three-js-container { width: 100vw; height: 100vh; } </style>在App组件中导入并使用这个组件,不出意外就可看到一个旋转的绿色正方体
4.展示ply文件我下载了blender软件,导出了一个ply文件,这个ply文件放在项目的public文件夹
先导入所需的文件
import * as THREE from 'three'; import { PLYLoader } from 'three/examples/jsm/loaders/PLYLoader.js'; <template> <h1>我是PLY</h1> <div ref="threeContainer" class="three-container"></div> <h1>你呢</h1> </template> <script> import * as THREE from 'three'; import { PLYLoader } from 'three/examples/jsm/loaders/PLYLoader.js'; export default { name: 'PLY', mounted() { this.initThree(); }, methods: { initThree() { console.log("ply"); // 创建场景 const scene = new THREE.Scene(); // 创建相机 const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(0, 0, 10); // 调整相机位置 camera.lookAt(scene.position); // 让相机朝向场景中心 // 添加光源 const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); scene.add(directionalLight); // 创建渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); // 将渲染器的 canvas 添加到 Vue 组件的 div 中 this.$refs.threeContainer.appendChild(renderer.domElement); // 加载 .ply 文件 let mesh; // 声明一个变量用于存储加载的网格 const loader = new PLYLoader(); loader.load('/2.ply', function (geometry) { // 计算顶点法线 geometry puteVertexNormals(); const material = new THREE.MeshStandardMaterial({ color: 0xffffff }); mesh = new THREE.Mesh(geometry, material); // 将加载的网格存储到变量中 scene.add(mesh); }); // 动画循环 const animate = () => { if (mesh) { // 每帧让物体绕 x 轴和 y 轴旋转 mesh.rotation.x += 0.01; mesh.rotation.y += 0.01; } renderer.render(scene, camera); }; renderer.setAnimationLoop(animate); } } }; </script> <style scoped> .three-container { width: 100%; height: 100%; } </style> 5.展示stl文件文件是一个同学发给我的,一个城堡
其实这个是和ply同理的,只是导入的文件不同
import * as THREE from 'three'; import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'; <template> <h1>我是STL</h1> <div ref="threeContainer" class="three-container"></div> <h1>你呢</h1> </template> <script> import * as THREE from 'three'; import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'; export default { name: 'STL', mounted() { this.initThree(); }, methods: { initThree() { console.log("stl"); // 创建场景 const scene = new THREE.Scene(); // 创建相机 const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(0, 0, 10); // 调整相机位置 camera.lookAt(scene.position); // 让相机朝向场景中心 // 添加光源 const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); scene.add(directionalLight); // 创建渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); // 将渲染器的 canvas 添加到 Vue 组件的 div 中 this.$refs.threeContainer.appendChild(renderer.domElement); // 加载 .stl 文件 let mesh; // 用于存储加载的模型 const loader = new STLLoader(); // 使用 STLLoader 加载 STL 文件 loader.load('/chengbao.stl', function (geometry) { // STL 文件通常不需要计算顶点法线,因为它们是三角形网格 // 居中几何体(确保模型的几何中心在原点) geometry.center(); // 创建渐变材质 const uniforms = { iTime: { value: 0 }, iResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) } }; const material = new THREE.ShaderMaterial({ uniforms: uniforms, vertexShader: ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, fragmentShader: ` precision highp float; uniform float iTime; uniform vec2 iResolution; varying vec2 vUv; // 渐变颜色定义 const vec3 colors[5] = vec3[]( vec3(0., 0., 0.6), vec3(0., 1., 1.), vec3(0.0, 1.0, 0.), vec3(1.0, 1.0, 0.), vec3(1.0, 0.0, 0.) ); const float points[5] = float[]( 0.0, 0.15, 0.5, 0.65, 1.0 ); vec3 gradian(vec3 c1, vec3 c2, float a) { return mix(c1, c2, a); } vec3 heat4(float weight) { if (weight <= points[0]) return colors[0]; if (weight >= points[4]) return colors[4]; for (int i = 1; i < 5; i++) { if (weight < points[i]) { float a = (weight - points[i - 1]) / (points[i] - points[i - 1]); return gradian(colors[i - 1], colors[i], a); } } return vec3(0.0); } void main() { float weight = (vUv.x + vUv.y + iTime) / 10.0; // 根据时间动态调整权重 vec3 color = heat4(weight); float alpha = sin(iTime) * 0.5 + 0.5; // 透明度在 0 到 1 之间变化 gl_FragColor = vec4(color, alpha); } `, transparent: true // 启用透明度 }); mesh = new THREE.Mesh(geometry, material); // 创建网格 mesh.position.set(0, 0, 0); // 确保模型在场景中心 mesh.scale.set(0.1, 0.1, 0.1); // 调整模型大小(根据需要) scene.add(mesh); // 将模型添加到场景中 }); // 鼠标滑动控制渐变速度和模型旋转 let lastTime = performance.now(); let lastMouseX = 0; let lastMouseY = 0; renderer.domElement.addEventListener('mousemove', (event) => { const now = performance.now(); const deltaTime = (now - lastTime) / 1000; // 时间差(秒) const mouseX = event.clientX; const mouseY = event.clientY; const deltaX = mouseX - lastMouseX; const deltaY = mouseY - lastMouseY; const speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // 鼠标滑动速度 const speedFactor = speed * deltaTime; // 速度因子 if (mesh) { mesh.material.uniforms.iTime.value += speedFactor; // 根据鼠标滑动速度调整时间 mesh.rotation.y += deltaX * 0.001; // 水平旋转 mesh.rotation.x -= deltaY * 0.001; // 垂直旋转 } lastTime = now; lastMouseX = mouseX; lastMouseY = mouseY; }); // 动画循环 const animate = () => { renderer.render(scene, camera); // 渲染场景 }; renderer.setAnimationLoop(animate); // 设置动画循环 } } }; </script> <style scoped> .three-container { width: 100%; height: 100%; } </style>我这个做了更花哨的效果,可以渐变
在Vue项目中使用three.js在前端页面展示PLY文件或STL文件由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“在Vue项目中使用three.js在前端页面展示PLY文件或STL文件”