Three.js——二维平面、二维圆、自定义二维图形、立方体、球体、圆柱体、圆环、扭结、多面体、文字

个人简介

👀个人主页: 前端杂货铺
开源项目: rich-vue3 (基于 Vue3 + TS + Pinia + Element Plus + Spring全家桶 + MySQL)
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍖开源 rich-vue3 🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

内容参考链接
WebGL专栏WebGL 入门
Three.js(一)创建场景、渲染三维对象、添加灯光、添加阴影、添加雾化
Three.js(二)scene场景、几何体位置旋转缩放、正射投影相机、透视投影相机
Three.js(三)聚光灯、环境光、点光源、平行光、半球光
Three.js(四)基础材质、深度材质、法向材质、面材质、朗伯材质、Phong材质、着色器材质、直线和虚线、联合材质

文章目录

    • 前言
    • 一、二维平面
    • 二、二维圆
    • 三、自定义二维图形
    • 四、立方体
    • 五、球体
    • 六、圆柱体
    • 七、圆环
    • 八、扭结
    • 九、多面体
    • 十、文字
    • GUI 控制文件
    • 总结

前言

大家好,这里是前端杂货铺。

上篇文章我们学习了 基础材质、深度材质、法向材质、面材质、朗伯材质、Phong材质、着色器材质、直线和虚线、联合材质。接下来,我们继续我们 three.js 的学习!

在学习的过程中,如若需要深入了解或扩展某些知识,可以自行查阅 => three.js官方文档。


一、二维平面

PlaneBufferGeometry 一个用于生成平面几何体的类。相较于于 PlaneGeometry 更加轻量化。

new THREE.PlaneBufferGeometry(width : Float, height : Float, widthSegments : Integer, heightSegments : Integer)
参数名称描述
width平面沿着 X 轴的宽度。默认值是 1
height平面沿着 Y 轴的高度。默认值是 1
widthSegments(可选)平面的宽度分段数,默认值是 1
heightSegments(可选)平面的高度分段数,默认值是 1
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body><script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 添加平面 平面沿着 X 轴的宽度 | 平面沿着 Y 轴的高度 | 平面的宽度分段数 | 平面的高度分段数const geometry = new THREE.PlaneBufferGeometry(10, 10, 2, 2);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();</script>
</body></html>

二维平面


二、二维圆

CircleGeometry 是欧式几何的一个简单形状,它由围绕着一个中心点的三角分段的数量所构造,由给定的半径来延展。 同时它也可以用于创建规则多边形,其分段数量取决于该规则多边形的边数。

new MeshDepthMaterial(parameters: Object);
参数名称描述
radius圆形的半径,默认值为1
segments分段(三角面)的数量,最小值为3,默认值为 32
thetaStart第一个分段的起始角度,默认为0
thetaLength圆形扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 添加二维圆 半径 | 指定创建圆需要的面的数量(最少3个) | 开始画的角度,0-Math.PI * 2 | 角度,定义圆要画多大const geometry = new THREE.CircleGeometry(4, 10, 0, Math.PI * 2);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

二维圆


三、自定义二维图形

自定义二维图形需要使用到 Shape 对象 和 ShapeGeometry 对象。

Shpae 使用路径以及可选的孔洞来定义一个二维形状平面。 它可以和 ExtrudeGeometry、ShapeGeometry 一起使用,获取点,或者获取三角面。

new THREE.Shape( points : Array );
参数名称描述
points一个 Vector2 数组

ShapeGeometry 形状缓冲几何体,用于从一个或多个路径形状中创建一个单面多边形几何体。

new THREE.ShapeGeometry(shapes : Array, curveSegments : Integer)
参数名称描述
shapes一个单独的shape,或者一个包含形状的Array
curveSegments每一个形状的分段数,默认值为12
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);const shape = new THREE.Shape();// 将绘制点移动到某处shape.moveTo(0, 0);// 从起始位置开始绘制,绘制到xy处停止shape.lineTo(0, 3);shape.lineTo(2, 3);shape.lineTo(5, 0);shape.lineTo(0, 0);// 绘制圆// shape.arc(1, 1, Math.PI * 2, Math.PI * 2, 100);const geometry = new THREE.ShapeGeometry(shape);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

自定义二维图形


四、立方体

BoxGeometry 是四边形的原始几何类,它通常使用构造函数所提供的 “width”、“height”、“depth” 参数来创建立方体或者不规则四边形。

new THREE.BoxGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
参数名称描述
widthX 轴上面的宽度,默认值为 1
heightY 轴上面的高度,默认值为 1
depthZ 轴上面的深度,默认值为 1
widthSegments(可选)宽度的分段数,默认值是 1
heightSegments(可选)高度的分段数,默认值是 1
depthSegments(可选)深度的分段数,默认值是 1
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 宽度 x轴方向 | 高度 y轴方向 | 深度 z轴方向 | x轴方向将面分成多少份 | y... | z...const geometry = new THREE.BoxGeometry(3, 3, 3, 1, 1, 1);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

立方体


五、球体

SphereGeometry 是 一个用于生成球体的类

new THREE.SphereGeometry(radius : Float, widthSegments : Integer, heightSegments : Integer, phiStart : Float, phiLength : Float, thetaStart : Float, thetaLength : Float)
参数名称描述
radius球体半径,默认为 1
widthSegments水平分段数(沿着经线分段),最小值为 3,默认值为 32
heightSegments垂直分段数(沿着纬线分段),最小值为 2,默认值为 16
phiStart指定水平(经线)起始角度,默认值为 0
phiLength指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2
thetaStart指定垂直(纬线)起始角度,默认值为0
thetaLength指定垂直(纬线)扫描角度大小,默认值为 Math.PI
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 半径 | x轴方向将面分成多少份 | y轴方向将面分成多少份 | 从x轴什么位置开始回值 | 绘制多少 | 从y轴什么位置开始回值 | 绘制多少const geometry = new THREE.SphereGeometry(2, 20, 20, Math.PI * 2, Math.PI * 2, Math.PI * 2, Math.PI * 2);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

球体


六、圆柱体

CylinderGeometry 是 一个用于生成圆柱几何体的类

new THREE.CylinderGeometry(radiusTop : Float, radiusBottom : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float);
参数名称描述
radiusTop圆柱的顶部半径,默认值是 1
radiusBottom圆柱的底部半径,默认值是 1
height圆柱的高度,默认值是 1
radialSegments圆柱侧面周围的分段数,默认为 32
heightSegments圆柱侧面沿着其高度的分段数,默认值为 1
openEnded一个 Boolean 值,指明该圆锥的底面是开放的还是封顶的。默认值为 false,即其底面默认是封顶的
thetaStart第一个分段的起始角度,默认为 0
thetaLength圆柱底面圆扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆柱
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 半径 | x轴方向将面分成多少份 | y轴方向将面分成多少份 | 从x轴什么位置开始回值 | 绘制多少 | 从y轴什么位置开始回值 | 绘制多少const geometry = new THREE.CylinderGeometry(2, 2, 2, 20, 4, false);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

圆柱体


七、圆环

TorusGeometry 是 一个用于生成圆环几何体的类

new THREE.TorusGeometry(radius : Float, tube : Float, radialSegments : Integer, tubularSegments : Integer, arc : Float);
参数名称描述
radius环面的半径,从环面的中心到管道横截面的中心。默认值是 1
tube管道的半径,默认值为 0.4
radialSegments管道横截面的分段数,默认值为 12
tubularSegments管道的分段数,默认值为 48
arc圆环的圆心角(单位是弧度),默认值为 Math.PI * 2
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 半径 | 管子的半径 | 沿圆环长度分为多少段 | 宽度分成多少段 | 是否形成一个完整的闭环 |const geometry = new THREE.TorusGeometry(2, 1, 10, 10, Math.PI * 2);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

圆环


八、扭结

TorusKnotGeometry 用于创建一个圆环扭结,其特殊形状由一对互质的整数,p和q所定义。如果p和q不互质,创建出来的几何体将是一个环面链接。

new THREE.TorusKnotGeometry(radius : Float, tube : Float, tubularSegments : Integer, radialSegments : Integer, p : Integer, q : Integer);
参数名称描述
radius圆环的半径,默认值为 1
tube管道的半径,默认值为 0.4
tubularSegments管道的分段数量,默认值为 64
radialSegments横截面分段数量,默认值为 8
p这个值决定了几何体将绕着其旋转对称轴旋转多少次,默认值是 2
q这个值决定了几何体将绕着其内部圆环旋转多少次,默认值是 3
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 半径 | 管子的半径 | 沿圆环长度分为多少段 | 宽度分成多少段 | 定义结的形状 | 定义结的形状 | 拉伸纽结 |const geometry = new THREE.TorusKnotGeometry(2, 1, 20, 6, 1, 3, 1);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

扭结


九、多面体

PolyhedronGeometry 多面体在三维空间中具有一些平面的立体图形。这个类将一个顶点数组投射到一个球面上,之后将它们细分为所需的细节级别。

new THREE.PolyhedronGeometry(vertices : Array, indices : Array, radius : Float, detail : Integer);
参数名称描述
vertices一个顶点Array(数组):[1,1,1, -1,-1,-1, … ]
indices一个构成面的索引Array(数组), [0,1,2, 2,3,0, … ]
radius最终形状的半径
detail将对这个几何体细分多少个级别。细节越多,形状就越平滑
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 构成多面体的顶点 | 创建出的面 | 指定多面的大小 | 处理多面体细节 |const geometry = new THREE.PolyhedronGeometry(vertices, indices, 4, 0);// 正四面体// const geometry = new THREE.TetrahedronGeometry(4, 0);// 正八面体// const geometry = new THREE.OctahedronGeometry(4, 0);// 正二十面体// const geometry = new THREE.IcosahedronGeometry(4, 0);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

多面体


十、文字

TextGeometry 是一个用于将文本生成为单一的几何体的类。 它是由一串给定的文本,以及由加载的font(字体)和该几何体 ExtrudeGeometry 父类中的设置所组成的参数来构造的。

// text 将要显示的文本
new THREE.TextGeometry(text : String, parameters : Object);
参数名称描述
fontTHREE.Font 的实例
size字体大小,默认值为100
depth挤出文本的厚度。默认值为 50
curveSegments(表示文本的)曲线上点的数量。默认值为 12
bevelEnabled是否开启斜角,默认为 false
bevelThickness文本上斜角的深度,默认值为 20
bevelSize斜角与原始文本轮廓之间的延伸距离。默认值为 8
bevelSegments斜角的分段数。默认值为 3
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><script src="../lib/three/dat.gui.js"></script><script src="../controls/index.js"></script><script src="../assets/font/font.js"></script>
</head><body>
<script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 文字const geometry = new THREE.TextGeometry("THREE", textOptions);const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});const mesh = {pointer: new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic])};// 添加到场景scene.add(mesh.pointer);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);initControls(geometry, camera, mesh, scene);const animation = () => {mesh.pointer.rotation.x += 0.01;mesh.pointer.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();
</script>
</body></html>

文字


GUI 控制文件

老规矩,我们把本篇文章需要使用的 ./controls/index.js 补充完毕

const basicType = {// 颜色。默认为一个白色(0xffffff)的 Color 对象。color: {method: 'addColor',getValue: item => item.color.getStyle(),setValue: (item, value) => item.color.setStyle(value),},// skyColor: {method: 'addColor',getValue: item => item.skyColor.getStyle(),setValue: (item, value) => item.skyColor.setStyle(value),},// 光照强度。默认值为 1intensity: {method: 'add',extends: [0, 2],getValue: item => item.intensity,setValue: (item, value) => item.intensity = +value,},// 光源照射的最大距离。默认值为 0(无限远)distance: {method: 'add',extends: [0, 1],getValue: item => item.distance,setValue: (item, value) => item.distance = +value,},// 光线照射范围的角度。默认值为 Math.PI/3angle: {method: 'add',extends: [0, Math.PI / 2],getValue: item => item.angle,setValue: (item, value) => item.angle = +value,},// 决定了光线强度递减的速度。exponent: {method: 'add',extends: [0, 20],getValue: item => item.exponent,setValue: (item, value) => item.exponent = +value,},// 亮度opacity: {extends: [0, 1],getValue: item => item.opacity,setValue: (item, value) => item.opacity = +value},// 透明度transparent: {getValue: item => item.transparent,setValue: (item, value) => item.transparent = value},// 线框wireframe: {getValue: item => item.wireframe,setValue: (item, value) => item.wireframe = value},// 显隐visible: {getValue: item => item.visible,setValue: (item, value) => item.visible = value},cameraNear: {extends: [0, 50],getValue: (item, camera) => camera.near,setValue: (item, value, camera) => camera.near = value},cameraFar: {extends: [50, 200],getValue: (item, camera) => camera.far,setValue: (item, value, camera) => camera.far = value},side: {extends: [['font', 'back', 'double']],getValue: (item, camera) => 'font',setValue: (item, value) => {switch (value) {case 'font':item.side = THREE.FrontSide;break;case 'back':item.side = THREE.BackSide;break;case 'double':item.side = THREE.DoubleSide;break;}}},// 材料的环境颜色ambient: {method: 'addColor',getValue: (item) => item.ambient.getHex(),setValue: (item, value) => item.ambient = new THREE.Color(value),},// 物体材料本身发出的颜色emissive: {method: 'addColor',getValue: (item) => item.emissive.getHex(),setValue: (item, value) => item.emissive = new THREE.Color(value),},// 设置高亮部分的颜色specular: {method: 'addColor',getValue: (item) => item.specular.getHex(),setValue: (item, value) => item.specular = new THREE.Color(value),},// 设置高亮部分的亮度shininess: {extends: [0, 100],getValue: (item) => item.shininess,setValue: (item, value) => item.shininess = value,},red: {extends: [0, 1],getValue: (item) => item.uniforms.r.value,setValue: (item, value) => item.uniforms.r.value = value,},alpha: {extends: [0, 1],getValue: (item) => item.uniforms.a.value,setValue: (item, value) => item.uniforms.a.value = value,},dashSize: {extends: [0, 5],getValue: (item) => item.dashSize,setValue: (item, value) => item.dashSize = +value,},width: getMeshValue([0, 20], 'width'),height: getMeshValue([0, 20], 'height'),widthSegments: getMeshValue([0, 20], 'widthSegments'),heightSegments: getMeshValue([0, 20], 'heightSegments'),radius: getMeshValue([1, 20], 'radius'),segments: getMeshValue([3, 80], 'segments'),thetaStart: getMeshValue([0, Math.PI * 2], 'thetaStart'),thetaLength: getMeshValue([0, Math.PI * 2], 'thetaLength'),depth: getMeshValue([0, 20], 'depth'),depthSegments: getMeshValue([0, 20], 'depthSegments'),phiStart: getMeshValue([0, Math.PI * 2], 'phiStart'),radiusTop: getMeshValue([-20, 20], 'radiusTop'),radiusBottom: getMeshValue([-20, 20], 'radiusBottom'),radialSegments: getMeshValue([1, 60], 'radialSegments'),openEnded: getMeshValue([], 'openEnded'),tube: getMeshValue([1, 6], 'tube'),tubularSegments: getMeshValue([0, Math.PI * 2], 'tubularSegments'),arc: getMeshValue([1, 20], 'arc'),p: getMeshValue([1, 10], 'p'),q: getMeshValue([1, 10], 'q'),detail: getMeshValue([0, 5], 'detail'),heightScale: getMeshValue([0, 5], 'heightScale'),size: getMeshValue([0, 10], 'size'),bevelThickness: getMeshValue([1, 30], 'bevelThickness'),bevelEnabled: getMeshValue([], 'bevelEnabled'),bevelSegments: getMeshValue([1, 30], 'bevelSegments'),curveSegments: getMeshValue([1, 30], 'curveSegments'),steps: getMeshValue([0, 10], 'steps'),
}const vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1];
const indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1];function createMaterial(geometry) {const lambert = new THREE.MeshLambertMaterial({color: 0xff0000});const basic = new THREE.MeshBasicMaterial({wireframe: true});return new THREE.SceneUtils.createMultiMaterialObject(geometry, [lambert, basic]);
}// 字体配置
const textOptions = {size: 1,height: 1,weight: 'normal',font: 'helvetiker',bevelThickness: 1,bevelEnabled: false,bevelSegments: 1,curveSegments: 1,steps: 1
}const roundValue = {width: 1,height: 1,depth: 1,widthSegments: 1,heightSegments: 1,depthSegments: 1, // 不能为 undefinedradialSegments: 1,tubularSegments: 1,detail: 1,size: 1,bevelSegments: 1,curveSegments: 1,steps: 1
}const isPolyhedron = item => item.type === 'PolyhedronGeometry';const isFont = item => item.type === 'TextGeometry';function removeAndAdd(item, value, camera, mesh, scene, controls) {const {x,y,z} = mesh.pointer.rotation;scene.remove(mesh.pointer);const arg = [];for (const key in controls) {if (roundValue[key]) {// ~~位运算符,转为数字controls[key] = ~~controls[key];}arg.push(controls[key]);}// 多面体if (isPolyhedron(item)) {arg.unshift(vertices, indices);}if (isFont(item)) {mesh.pointer = createMaterial(new THREE[item.type]('THREE', Object.assign(textOptions, controls)));} else {mesh.pointer = createMaterial(new THREE[item.type](...arg));}mesh.pointer.rotation.set(x, y, z);scene.add(mesh.pointer);
}function getMeshValue(extend, name) {return {extends: extend,getValue: (item, camera, mesh) => isFont(item) && textOptions[name] !== undefined ? textOptions[name] : mesh.children[0].geometry.parameters[name],setValue: (...arg) => removeAndAdd(...arg)}
}const itemType = {SpotLight: ['color', 'intensity', 'distance', 'angle', 'exponent'], // 聚光灯AmbientLight: ['color'], // 环境光PointLight: ['color', 'intensity', 'distance'], // 点光源DirectionalLight: ['color', 'intensity'], // 平行光HemisphereLight: ['groundColor', 'intensity'], // 半球光MeshBasicMaterial: ['color', 'opacity', 'transparent', 'wireframe', 'visible'], // 基础网格材质MeshDepthMaterial: ['wireframe', 'cameraNear', 'cameraFar'], // 深度网格材质MeshNormalMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side'],MeshLambertMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side', 'ambient', 'emissive', 'color'], // 朗伯材质MeshPhongMaterial: ['opacity', 'transparent', 'wireframe', 'visible', 'side', 'ambient', 'emissive', 'color', 'specular', 'shininess'], // Phong材质ShaderMaterial: ['red', 'alpha'], // 着色器材质LineBasicMaterial: ['color'], // 直线LineDashedMaterial: ['dashSize', 'gapSize'], // 虚线PlaneBufferGeometry: ['width', 'height', 'widthSegments', 'heightSegments'], // 二维屏幕CircleGeometry: ['radius', 'segments', 'thetaStart', 'thetaLength'], // 二维圆BoxGeometry: ['width', 'height', 'depth', 'widthSegments', 'heightSegments', 'depthSegments'], // 立方体SphereGeometry:  ['radius', 'widthSegments', 'heightSegments', 'phiStart', 'phiLength', 'thetaStart', 'thetaLength'], // 球体CylinderGeometry: ['radiusTop', 'radiusBottom', 'height', 'radialSegments', 'heightSegments', 'openEnded'], // 圆柱体TorusGeometry: ['radius', 'tube', 'radialSegments', 'tubularSegments', 'arc'], // 圆环TorusKnotGeometry: ['radius', 'tube', 'radialSegments', 'tubularSegments', 'p', 'q', 'heightScale'], // 纽结PolyhedronGeometry: ['radius', 'detail'], // 多面缓冲几何体TetrahedronGeometry: ['radius', 'detail'], // 四面缓冲几何体OctahedronGeometry: ['radius', 'detail'], // 八面缓冲几何体IcosahedronGeometry: ['radius', 'detail'], // 二十面缓冲几何体TextGeometry: ['size', 'bevelThickness', 'bevelEnabled', 'bevelSegments', 'curveSegments', 'steps'],
}function initControls(item, camera, mesh, scene) {console.log('item', item)const typeList = itemType[item.type];const controls = {};if (!typeList || !typeList.length) {return;}const gui = new dat.GUI();for (let i = 0; i < typeList.length; i++) {const child = basicType[typeList[i]];if (child) {controls[typeList[i]] = child.getValue(item, camera, mesh.pointer);const childExtends = child.extends || [];gui[child.method || 'add'](controls, typeList[i], ...childExtends).onChange((value) => {child.setValue(item, value, camera, mesh, scene, controls);})}}
}

总结

本篇文章我们讲解了几种常见几何体的基本使用,包括二维平面、二维圆、自定义二维图形、立方体、球体、圆柱体、圆环、扭结、多面体、文字。

更多内容扩展请大家自行查阅 => three.js官方文档,真心推荐读一读!!

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. Three.js 官方文档
  2. WebGL+Three.js 入门与实战【作者:慕课网_yancy】

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/15979.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ-默认读、写方式介绍

1、RabbitMQ简介 rabbitmq是一个开源的消息中间件&#xff0c;主要有以下用途&#xff0c;分别是&#xff1a; 应用解耦&#xff1a;通过使用RabbitMQ&#xff0c;不同的应用程序之间可以通过消息进行通信&#xff0c;从而降低应用程序之间的直接依赖性&#xff0c;提高系统的…

功率电感的设计步骤

文章目录 1&#xff1a;高导磁气隙&#xff08;铁氧体&#xff09;1.1设计原理1.2 设计步骤 2 铁粉芯2.1&#xff1a;设计原理2.2&#xff1a;设计步骤 TI电感设计 学习视频原链接 截图 1 截图1 截图1 截图 2 截图2 截图2 1&#xff1a;高导磁气隙&#xff08;铁氧体&#…

基于机器学习判断面部微表情发现哪些人更容易诊有帕金森病

1. 概述 帕金森病&#xff08;Parkinson’s disease&#xff0c;PD&#xff09;是一种慢性、进展性的神经退行性疾病&#xff0c;主要影响运动系统。该病症以大脑中黑质致密部多巴胺能神经元的逐渐丧失为特征&#xff0c;导致多巴胺&#xff08;一种重要的神经递质&#xff09…

【Qt】深入探索Qt窗口与对话框:从创建到管理:QDockWidget(浮动窗口)、QDialog(对话框)

文章目录 前言&#xff1a;1. 浮动窗口2. 对话框介绍2.1. 示例&#xff1a;主窗口中&#xff0c;通过点击按钮&#xff0c;弹出一个新的对话框。2.2. 创建自定义对话框2.2.1. 纯代码的方式2.2.2. 图形化界面的方式 3. 模态对话框 和 非模态对话框4. Qt 内置对话框4.1. 消息对话…

Hybrid Block Storage for Efficient Cloud Volume Service——论文泛读

TOS 2023 Paper 论文阅读笔记整理 问题 传统桌面和服务器应用程序向云的迁移给底层云存储带来了高性能、高可靠性和低成本的挑战。由于这些传统应用程序的I/O模式和一致性要求&#xff0c;与采用特定编程模型和范式&#xff08;如MapReduce[22]和RDD[52]&#xff09;的云原生…

香橙派AIpro(OrangePi AIPro)开发板初测评

开发板简介 最近&#xff0c;我拿到手一款Orange Pi AI Pro 开发板&#xff0c;它是香橙派联合华为精心打造的高性能AI 开发板&#xff0c;最早发布于2023年12月&#xff0c;其搭载了昇腾AI 处理器&#xff0c;可提供8TOPS INT8 的计算能力&#xff0c;内存提供了8GB 和16GB两…

基于jeecgboot-vue3的Flowable新建流程定义(一)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、vue3版本因为流程分类是动态的&#xff0c;不再固定了&#xff0c;所以新建的时候需要选择建立哪种流程类型的流程 代码如下&#xff1a; <!-- 选择模型的流程类型对话框 -->&…

数据结构(六)图

2024年5月26日一稿(王道P220) 6.1 图的基本概念 6.1.1 图的定义 6.2 图的存储及基本操作 6.2.1邻接矩阵法 6.2.2 邻接表

python web自动化(分布式测试Grid)

Grid介绍 Selenium Grid 是 Selenium 提供的⼀个⼯具&#xff0c;⽤于⽀持在多台计算机上并⾏运⾏测试。 它允许将测试分发到不同的机器和浏览器组合上&#xff0c;同时收集结果。 1.并⾏执⾏测试⽤例&#xff1a;在不同的机器上并⾏执⾏测试⽤例&#xff0c;从⽽加速整个测试过…

Vulhub——adminer

文章目录 一、CVE-2021-21311&#xff08;SSRF&#xff09;二、CVE-2021-43008&#xff08;远程文件读取&#xff09; 一、CVE-2021-21311&#xff08;SSRF&#xff09; Adminer是一个PHP编写的开源数据库管理工具&#xff0c;支持MySQL、MariaDB、PostgreSQL、SQLite、MS SQL…

基于SpringBoot+Vue的人事管理系统

引言 目前,人事管理的系统大都是CS架构的大型系统,很少有面向机关,事业单位内部的基于BS架构的微型人事系统,因此.开发一个基于BS架构的人事信息管理系统是非常必要的.但是基于BS架构的人事系统对于安全是一个大的考验点.在人事信息系统中,功能需简单清晰,可操作性强,其次安全…

第六节:带你全面理解vue3 浅层响应式API: shallowRef, shallowReactive, shallowReadonly

前言 前面两章,给大家讲解了vue3中ref, reactive,readonly创建响应式数据的API, 以及常用的计算属性computed, 侦听器watch,watchEffect的使用 其中reactive, ref, readonly创建的响应式数据都是深层响应. 而本章主要给大家讲解以上三个API 对应的创建浅层响应式数据的 API,…

【STM32单片机】----实现LED灯闪烁实战

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

【机器学习-23】关联规则(Apriori)算法:介绍、应用与实现

在现代数据分析中&#xff0c;经常需要从大规模数据集中挖掘有用的信息。关联规则挖掘是一种强大的技术&#xff0c;可以揭示数据中的隐藏关系和规律。本文将介绍如何使用Python进行关联规则挖掘&#xff0c;以帮助您发现数据中的有趣模式。 一、引言 1. 简要介绍关联规则学习…

动态路由实验—OSPF

动态路由协议实验-------OSPF 链路状态路由选择协议又被称为最短路径优先协议&#xff0c;它基SPF&#xff08;shortest path first &#xff09;算法 实验要求&#xff1a;各个PC之间能够互通 1.四台PC配置如下 PC1 PC2 PC3 PC4 2.配置各个交换机的口子的IP R1 <HUAWE…

spiderfoot一键扫描IP信息(KALI工具系列九)

目录 1、KALI LINUX简介 2、spiderfoot工具简介 3、在KALI中使用spiderfoot 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、命令示例 4.1 web访问 4.2 扫描并进行DNS解析 4.3 全面扫描 5、总结 1、KALI LINUX简介 Kali Linux 是一个功能强大、多才多…

基于docxtpl的模板生成Word

docxtpl是一个用于生成Microsoft Word文档的模板引擎库。它结合了docx模块和Jinja2模板引擎&#xff0c;使用户能够使用Microsoft Word模板文件并在其中填充动态数据。这个库提供了一种方便的方式来生成个性化的Word文档&#xff0c;并支持条件语句、循环语句和变量等控制结构&…

如何在 Elasticsearch 中选择精确 kNN 搜索和近似 kNN 搜索

作者&#xff1a;来自 Elastic Carlos Delgado kNN 是什么&#xff1f; 语义搜索&#xff08;semantic search&#xff09;是相关性排名的强大工具。 它使你不仅可以使用关键字&#xff0c;还可以考虑文档和查询的实际含义。 语义搜索基于向量搜索&#xff08;vector search&…

大数据工具之HIVE-参数调优,调度乱码(二)

一、调度乱码 在利用HUE工具,搭建WORKFLOW流程的过程中,如果直接执行hivesql数据正常,不会出现乱码现象,如果利用WORKFLOW搭建的流程,进行数据的拉取,会出现数据中文乱码现象,这些乱码主要是由于select 中的硬编码中文导致出现的现象 具体现象如下: select case when …

TG5032CGN TCXO 超高稳定10pin端子型适用于汽车动力转向控制器

TG5032CGN TCXO / VC-TCXO是一款应用广泛的晶振&#xff0c;具有超高稳定性&#xff0c;CMOS输出和使用晶体基振的削波正弦波输出形式。且有低相位噪声优势&#xff0c;是温补晶体振荡器(TCXO)和压控晶体振荡器(VCXO)结合的产物&#xff0c;具有TCXO和VCXO的共同优点&#xff0…