Three.js Line2渐变色线条序列帧动画
·
效果
代码
1. 生成轨迹线
// 轨迹曲线线
const curve = new THREE.CatmullRomCurve3(
[
new THREE.Vector3(-20, 30, 4),
new THREE.Vector3(20, 30, 4),
new THREE.Vector3(20, 0, 4),
new THREE.Vector3(-20, 0, 4),
new THREE.Vector3(-20, -30, 4),
new THREE.Vector3(20, -30, 4),
new THREE.Vector3(20, -30, -4),
new THREE.Vector3(-20, -30, -4),
new THREE.Vector3(-20, 0, -4),
new THREE.Vector3(20, 0, -4),
new THREE.Vector3(20, 30, -4),
new THREE.Vector3(-20, 30, -4),
new THREE.Vector3(-20, 30, 4),
],
false,
"catmullrom",
0.05
);
// 轨迹线
const points = curve.getPoints(100).reduce((arr, item) => {
return arr.concat(item.x, item.y, item.z);
}, []);
const geometry = new LineGeometry();
geometry.setPositions(points);
const material = new LineMaterial({
color: 0x2e91c2,
linewidth: 4,
});
material.resolution.set(window.innerWidth, window.innerHeight);
const line = new Line2(geometry, material);
line.computeLineDistances();
scene.add(line);
2. 渐变色线段生成方法
function createMovingLine(
curve,
index = 0,
color = ["#00ffff", "#224242"],
pointNum = 400,
verticNum = 30
) {
const lightGeometry = new LineGeometry();
const pointsV3 = curve.getPoints(pointNum);
lightGeometry.setPositions(
pointsV3.slice(index, index + verticNum).reduce((arr, item) => {
return arr.concat(item.x, item.y, item.z);
}, [])
);
const lightMaterial = new LineMaterial({
transparent: true,
side: THREE.DoubleSide,
linewidth: 12,
depthTest: false, // 慎用
vertexColors: THREE.VertexColors,
});
// 渐变色处理
const colors = gradientColors(color[1], color[0], verticNum);
const colorArr = colors.reduce((arr, item) => {
const Tcolor = new THREE.Color(item);
return arr.concat(Tcolor.r, Tcolor.g, Tcolor.b);
}, []);
lightGeometry.setColors(colorArr);
lightMaterial.resolution.set(window.innerWidth, window.innerHeight);
const lightLine = new Line2(lightGeometry, lightMaterial);
lightLine.computeLineDistances();
return {
index,
verticNum,
mesh: lightLine,
linePointsV3: pointsV3,
};
}
// 颜色插值
function gradientColors(start, end, steps, gamma) {
const parseColor = function (hexStr) {
return hexStr.length === 4
? hexStr
.substr(1)
.split("")
.map(function (s) {
return 0x11 * parseInt(s, 16);
})
: [
hexStr.substr(1, 2),
hexStr.substr(3, 2),
hexStr.substr(5, 2),
].map(function (s) {
return parseInt(s, 16);
});
};
const pad = function (s) {
return s.length === 1 ? `0${s}` : s;
};
let j;
let ms;
let me;
const output = [];
const so = [];
// eslint-disable-next-line
gamma = gamma || 1;
const normalize = function (channel) {
// eslint-disable-next-line
return Math.pow(channel / 255, gamma);
};
// eslint-disable-next-line
start = parseColor(start).map(normalize);
// eslint-disable-next-line
end = parseColor(end).map(normalize);
for (let i = 0; i < steps; i++) {
ms = i / (steps - 1);
me = 1 - ms;
for (j = 0; j < 3; j++) {
// eslint-disable-next-line
so[j] = pad(
Math.round(
Math.pow(start[j] * me + end[j] * ms, 1 / gamma) * 255
).toString(16)
);
}
output.push(`#${so.join("")}`);
}
return output;
}
3.添加渐变色线段
new Array(4).fill(0).forEach((it, i) => {
const movingLine = createMovingLine(curve, i * 100);
anmations.push(movingLine);
scene.add(movingLine.mesh);
});
4.帧渲染动画处理
anmations.forEach((item) => {
item.index + 1 > item.linePointsV3.length - item.verticNum
? (item.index = 0)
: (item.index += 3);
item.mesh.geometry.setPositions(
item.linePointsV3
.slice(item.index, item.index + item.verticNum)
.reduce((arr, item) => {
return arr.concat(item.x, item.y, item.z);
}, [])
);
});
搭配UnrealBloomPass实现发光效果
更多推荐
已为社区贡献10条内容
所有评论(0)