MeshLine:基础
首先,创建一个新项目并安装Three.js。正如标题所述,我们不会使用LineBasicMaterial。我们将使用一个第三方模块,名为MeshLine。
在终端中安装它:npm install meshline
接下来,我们将把它导入到我们的项目中。
import { MeshLineGeometry, MeshLineMaterial } from 'meshline';
正如你所看到的,我们现在有了新的材质和几何体,用于线条。
像往常一样,将某物添加到场景中,我们需要创建一个几何体和一个材质,然后将它们组合成一个网格。
那么,让我们从几何体开始,创建一个MeshLineGeometry的新实例。
const geometry = new MeshLineGeometry();
接下来,我们创建一个数组。
const geometryPoints = [
new THREE.Vector3(-2, 3, 0),
new THREE.Vector3(3, 3, -2),
new THREE.Vector3(0, -2, 0),
new THREE.Vector3(-2, 0, 2),
new THREE.Vector3(-2, 6, 5),
new THREE.Vector3(5, 2, -3),
];
现在,我们将使用setPoints()方法将这些坐标分配给几何体。
geometry.setPoints(geometryPoints);
对于材质,我们将创建一个MeshLineMaterial类的新实例,并将颜色、宽度和分辨率作为属性传递。
const lineMaterial = new MeshLineMaterial({
color: new THREE.Color(0xff0000),
lineWidth: 1,
resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
});
完成这些后,我们只需创建一个新的网格,将其添加到场景中,一切就绪!
const mesh = new THREE.Mesh(geometry, lineMaterial);
scene.add(mesh);
心形的动画
MeshLineMaterial带有一组属性。但在本文中,我将重点介绍其中的三个属性,这些属性将帮助我们实现最佳的动画效果。
首先,让我们创建一个循环,生成一个心形。
const geometry = new MeshLineGeometry();
// const geometryPoints = [
// new THREE.Vector3(-2, 3, 0),
// new THREE.Vector3(3, 3, -2),
// new THREE.Vector3(0, -2, 0),
// new THREE.Vector3(-2, 0, 2),
// new THREE.Vector3(-2, 6, 5),
// new THREE.Vector3(5, 2, -3),
// ];
const geometryPoints = [];
for (let t = 0; t <= Math.PI * 2; t += 0.01) {
const x = 16 * Math.pow(Math.sin(t), 3);
const y =
13 * Math.cos(t) -
5 * Math.cos(2 * t) -
2 * Math.cos(3 * t) -
Math.cos(4 * t);
geometryPoints.push(new THREE.Vector3(x, y, 0));
}
geometry.setPoints(geometryPoints);
接下来,让我们更新相机的位置。
// camera.position.set(6, 8, 14);
camera.position.set(0, 0, 50);
我们需要的第一个属性是dashArray,顾名思义,它将连续的线条转换为虚线。
const lineMaterial = new MeshLineMaterial({
color: new THREE.Color(0xff0000), // 线条颜色(此处为红色)
lineWidth: 1,
resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
dashArray: 0.2,
});
为了让这个效果运动起来,我们将更新虚线偏移量。
为了让动画看起来像是用一条线绘制的,增加dashArray的值。
const lineMaterial = new MeshLineMaterial({
color: new THREE.Color(0xff0000), // 线条颜色(此处为红色)
lineWidth: 1,
resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
// dashArray: 0.2,
dashArray: 2,
});
第一个问题是虚线部分并没有完全不可见。放大后,你会注意到它。线条看起来像是被切断的,因为虚线部分重叠的区域出现在前面。
那么,为了让虚线部分真正不可见,我们将transparent属性设置为true。
lineMaterial.transparent = true;
正如你所看到的,通过使虚线部分真正不可见,解决了两个问题中的一个。然而,可见部分仍然看起来像是被切断的,因为虚线在它前面。
为了防止这种遮挡问题,我们将depthTest属性设置为false。
lineMaterial.depthTest = false;
我们可以改变曲线的宽度。例如,它可以逐渐变细。
为此,我们将一个函数作为setPoints()方法的第二个参数设置。
// geometry.setPoints(geometryPoints);
geometry.setPoints(geometryPoints, (p) => 1 - p);
我们可以做相反的事情,也就是说让曲线从细开始。
// geometry.setPoints(geometryPoints);
// geometry.setPoints(geometryPoints, (p) => 1 - p);
geometry.setPoints(geometryPoints, (p) => 1 - (1 - p));
最后,我们只需对场景进行一些后期处理,一切就绪!