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实现发光效果

在这里插入图片描述

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值