在 three 中形状的定义方法,以及形状的属性与API,以及基本使用示例。形状路径能够定义更多的形状。
Shape 是什么有什么用
- 这是一个形状API
- 能够创建出任意几形状
- 通过 ShapeGeometry 创建平面形状
- 通过 ExtrudeGeometry 创建3D形状
Shape 属性及API列表
- uuid 惟一ID不能修改
- holes 形状的孔洞数组
- extractPoints 获取形状的点位
- getPointsHoles 获取孔洞点位
重点了解下 holes
- 在 holes属性中可以压入Path组
- 当 Path 组在形状里面时这些点位就是形状的孔洞
// 创建孔洞
const hole = new THREE.Path();
hole.moveTo(3, 3);
hole.lineTo(7, 3);
hole.lineTo(7, 7);
hole.lineTo(3, 7);
hole.lineTo(3, 3); // 关闭路径形成孔洞
// 当这些点位在形状里面时就是孔洞
ShapePath 是 Shape 的内部实现
ShapePath的属性
- subPaths 子路径列表
- currentPath 当前路径
ShapePath的方法
- moveTo 移动 currentPath 位置
- lineTo 直接连接新点位
- quadraticCurveTo 通过二次曲线连接新点位
- bezierCurveTo 通过贝塞尔曲线连接新点位
- splineThru 通过points 组生成新点位表
- toShapes 更改实体形状和孔洞的生成方式
使用示例
<template>
<div id="parkingLot" ref="parkingLot">
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import * as THREE from 'three';
// 导入 OrbitControls
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const parkingLot = ref();
onMounted(() => {
const DOMEl = parkingLot.value;
// 获取 DOMEl 的宽度和高度,以设置渲染器的大小。
const width = DOMEl.clientWidth;
const height = DOMEl.clientHeight;
const renderer = new THREE.WebGLRenderer();
renderer.setSize( width, height );
DOMEl.appendChild( renderer.domElement );
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 2000 );
camera.position.set( 0, 300, 800 );
camera.lookAt( 0, 0, 0 );
// 创建一个新的 Shape 对象
const shape = new THREE.Shape();
// 定义形状的路径
shape.moveTo(0, 0);
shape.lineTo(10, 0);
shape.lineTo(10, 10);
shape.lineTo(0, 10);
shape.lineTo(0, 0); // 关闭路径形成矩形
const extrudeSettings = {
steps: 2,
depth: 10,
bevelEnabled: true,
bevelThickness: 1,
bevelSize: 1,
bevelOffset: 0,
bevelSegments: 1
};
const extrudeGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
// 创建材质
const material = new THREE.MeshLambertMaterial({ color: 0xffffff });
const extrudeMesh = new THREE.Mesh(extrudeGeometry, material);
scene.add(extrudeMesh);
// 创建 OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 创建光源
const light = new THREE.DirectionalLight(0x0000ff, 10);
light.position.set(10, 10, 10);
light.castShadow = true;
scene.add(light);
// 渲染函数
function animate() {
requestAnimationFrame(animate);
controls.update(); // 仅在启用阻尼时需要调用
renderer.render(scene, camera);
}
animate();
});
</script>
<style lang="scss" scoped="scoped">
#parkingLot {
width: 940px;
height: 940px;
border: 1px solid #ccc;
margin: 30px auto;
}
</style>