Three.js 绘制面_内置点教程

📅 2026/7/16 16:12:48
Three.js 绘制面_内置点教程
绘制面_内置点 ·Draw Face· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么OrbitControls 相机轨道交互Raycaster 鼠标拾取与交互requestAnimationFrame渲染循环与resize自适应效果说明本案例演示绘制面_内置点效果支持鼠标拾取、绘制或拖拽交互核心用到 OrbitControls、Raycaster。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念Scene / Camera / WebGLRenderer构成最小渲染闭环大场景可开logarithmicDepthBuffer缓解 Z-fighting。OrbitControls提供轨道旋转/缩放开启enableDamping后需在 animate 中controls.update()。Raycaster将屏幕坐标转为射线与场景求交得到世界坐标常用于绘制/拾取。实现步骤搭建灯光与环境如有requestAnimationFrame 循环 update render代码要点import * as THREE from threeimport { OrbitControls } from three/examples/jsm/controls/OrbitControls.jsconst box document.getElementById(box)const scene new THREE.Scene()const camera new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000)camera.position.set(0, 3, 3)const renderer new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true })renderer.setSize(box.clientWidth, box.clientHeight)box.appendChild(renderer.domElement)const controls new OrbitControls(camera, renderer.domElement)controls.enableDamping trueconst directionalLight new THREE.DirectionalLight(0xffffff, 1)directionalLight.position.set(0, 20, 0)scene.add(directionalLight, new THREE.AmbientLight(0xffffff, 1))/增加一个面/ const plane new THREE.PlaneGeometry(5, 5)const material new THREE.MeshStandardMaterial({ color: 0xffffff })const planeMesh new THREE.Mesh(plane, material)planeMesh.rotation.x - Math.PI / 2scene.add(planeMesh)animate()function animate() {requestAnimationFrame(animate)controls.update()renderer.render(scene, camera)}window.onresize () {renderer.setSize(box.clientWidth, box.clientHeight)camera.aspect box.clientWidth / box.clientHeightcamera.updateProjectionMatrix()}// 事件 const raycaster new THREE.Raycaster()const getPoint event {const mouse new THREE.Vector2((event.offsetX / event.target.clientWidth) * 2 - 1,-(event.offsetY / event.target.clientHeight) * 2 1)raycaster.setFromCamera(mouse, camera)const intersects raycaster.intersectObjects(scene.children)if (intersects.length 0) return intersects[0].point}const setPointBox point {const box new THREE.BoxGeometry(0.04, 0.04, 0.04)const material new THREE.MeshStandardMaterial({ color: 0xff0000 })const boxMesh new THREE.Mesh(box, material)boxMesh.position.copy(point)scene.add(boxMesh)}/开始绘制/ const pointList []; let drawMesh null; let stop falsebox.addEventListener(contextmenu, () {stop true// const { indexGroup, faceGroup, uvGroup } multShapeGroup(pointList)// if (drawMesh) updateMultShapePlaneGeometry(drawMesh.geometry, faceGroup, indexGroup, uvGroup)})// 移动 box.addEventListener(mousemove, (event) {if (stop) returnconst point getPoint(event) if (!point || !drawMesh || pointList.length 2) return// update_shape(pointList)})box.addEventListener(click, (event) {const point getPoint(event)if (!point || stop) returnsetPointBox(point)point.y 0.001pointList.push(point) if (pointList.length 4) returnif (!drawMesh) { draw_shape_v2(pointList) }else{ update_shape(pointList) } })// 此方法也可使用 const draw_shape (pointList){ let v2_p [] pointList.map(item{ v2_p.push(new THREE.Vector2(item.x,item.z)) }) const shape new THREE.Shape(v2_p) const geometry new THREE.ShapeGeometry(shape); const positions geometry.getAttribute(position) for (let i 0; i positions.count; i) { let y positions.array[i*31] positions.array[i31] positions.array[i32] 0.01 positions.array[i*32] y } geometry.attributes.position.needsUpdate true const material new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide }); drawMesh new THREE.Mesh(geometry, material); scene.add(drawMesh); }const draw_shape_v2 (pointList){ let v2_p [] const shape new THREE.Shape() shape.autoClose true pointList.map(item{ v2_p.push(new THREE.Vector2(item.x,item.z)) }) shape.moveTo(v2_p[0].x,v2_p[0].y) v2_p.map((item,index){ if (index0) { shape.lineTo(item.x,item.y) } }) const geometry new THREE.ShapeGeometry(shape); const positions geometry.getAttribute(position) console.log(positions); for (let i 0; i positions.count; i) { let y positions.array[i*31] positions.array[i31] positions.array[i32] 0.01 positions.array[i*32] y } geometry.attributes.position.needsUpdate true const material new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide }); drawMesh new THREE.Mesh(geometry, material); scene.add(drawMesh); }const update_shape (pointList){ drawMesh.geometry.dispose() drawMesh.material null scene.remove(drawMesh) draw_shape_v2(pointList) }完整源码GitHub小结本文提供绘制面_内置点完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库