three Shape 与 ShapePath 使用小结

184 阅读2分钟

在 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>