新手向用Threejs写一个旋转的动态三角形注释超详细

38次阅读

共计 2340 个字符,预计需要花费 6 分钟才能阅读完成。

Three.JS 是基于 WebGL 的 Javascript 开源框架,一模一样的效果我也有用 webGL 做过,链接是这个 https://segmentfault.com/a/11…

html 部分还是很简单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>demoThree</title>
</head>
<body>
    <canvas id="demo-three"></canvas>
</body>
<script type="text/javascript" src="./three.js"></script>
<script type="text/javascript" src="./demo_three.js"></script>
</html>

下面是 js 部分,每行代码都有比较详细的注释解释

// 定义宽高
const width = 400;
const height = 400;

const canvas = document.getElementById('demo-three');

// WebGLRenderer 如果不传参数不会把 dom 元素和最终渲染出来的屏幕上的 html 上的 dom 元素相关联, 那种情况就需要把 domElement,append 到 body 上,才能有相关画布出现
let renderer = new THREE.WebGLRenderer({canvas});
// 绘制场景,在 scene 中维护在场景中渲染的物体
let scene = new THREE.Scene();
// 使用正交相机(没有透视效果,适合我们这次的平面三角形), 正交相机需要定义上下左右前后的坐标情况,从而规定正交相机所能截取到的相关的平面空间中,物体的情况(视角空间的截取)let camera = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, -1000, 1000)
// 黑色背景,透明度 1.0
renderer.setClearColor(new THREE.Color(0x000000), 1.0);
// renderer 大小
renderer.setSize(400, 400);

// 在 three.js 官网可查看,有很多预定义的 geometry,但是没有三角形,我们可以通过 shapeGeometry 来绘制
let triangleShape = new THREE.Shape();
// 将绘制起始点移动到(const0,100)这个位置
triangleShape.moveTo(0, 100);
// 开始划线
triangleShape.lineTo(-100, -100);
triangleShape.lineTo(100, -100);
triangleShape.lineTo(0, 100);
// 定义几何体
const geometry = new THREE.ShapeGeometry(triangleShape);
// 定义材质,三角形只是基本图形,不需要光照
const material = new THREE.MeshBasicMaterial({
    color: 0xff0000,
    // 默认是一面的 (只渲染法向量所对应那一面),定义为 DoubleSide,将正反面都渲染出来
    side: THREE.DoubleSide
});
// 第一个参数 geometry,是我们之前定义的几何体的坐标情况,就很像之前的 webGl 中顶点着色器传入的顶点序列,不涉及颜色信息,只是定义几何体形状
// 第二个参数 material, 很像 webGl 中片段着色器中的,给顶点序列上色
let mesh = new THREE.Mesh(geometry, material);
// 设置 mesh 在 scene 中的位置
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 1;
scene.add(mesh);
// 相机沿着 z 轴负方向望进去,所以把相机设置在了原点
// 设置位置直接通过 position,要比原生 webGl 去修改往顶点着色器传的数据要方便很多
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 0;
// camera 从(0, 0, 0)的位置望向(0,0,1)camera.lookAt(new THREE.Vector3(0, 0, 1));

let currentAngle = 0;
let lastTimestamp = Date.now();

function animate() {
    // 记下时间,拿到现在的时间戳,因为每次 requestAnimationFrame 间隔时间是不知道的
    const now = Date.now();
    // 减去老的时间戳
    const duration = now - lastTimestamp;
    lastTimestamp = now;
    // 想要 requestAnimationFrame 间隔时间内转 180 度
    currentAngle = currentAngle + duration / 1000 * Math.PI;
}

function render() {animate();
    // mesh 绕 y 轴旋转 currentAngle 角度
    mesh.rotation.set(0, currentAngle, 0);
    // 渲染
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

render();

效果:

正文完
 0