SOURCE

console 命令行工具 X clear

                    
>
console
function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}const {
  innerWidth,
  TweenMax,
  Power0,
  Zdog: { Illustration, TAU, Shape } } =
window;
const randomInRange = (max, min) =>
Math.floor(Math.random() * (max - min + 1)) + min;
const Scene = new Illustration({
  element: 'canvas',
  resize: 'fullscreen',
  dragRotate: true,
  rotate: {
    x: TAU * -0.075,
    y: TAU * 0.1 } });


const AXIS_LENGTH = Math.max(300, innerWidth * 0.25);
const PIPE_LIFESPAN = 2000;
const PIPE_SPEED = 0.002;
const PIPE_STROKE = 5;
const PIPE_COLORS = [
'#e4e9ed',
'#f27935',
'#fef160',
'#7befb2',
'#6bb9f0',
'#be90d4',
'#f64747'];

let CURRENT_PIPE = undefined;
class Pipe {

  constructor(opts) {_defineProperty(this, "IS_ALIVE", true);_defineProperty(this, "ACTIVE_AXIS", undefined);_defineProperty(this, "LENGTH", 0);_defineProperty(this, "SHAPE", undefined);_defineProperty(this, "start",


    () => {
      this.ACTIVE_AXIS = ['x', 'y', 'z'].filter(v => v !== this.ACTIVE_AXIS)[
      this.ACTIVE_AXIS ?
      Math.floor(Math.random() * 2) :
      Math.floor(Math.random() * 3)];

      this.SHAPE.path = [
      ...this.SHAPE.path,
      { ...this.SHAPE.path[this.SHAPE.path.length - 1] }];

      const currentPos = this.SHAPE.path[this.SHAPE.path.length - 1][
      this.ACTIVE_AXIS];

      const newPos = randomInRange(-AXIS_LENGTH / 2, AXIS_LENGTH / 2);
      const distance = Math.abs(newPos - currentPos);
      this.LENGTH += distance;
      const duration = distance * PIPE_SPEED;
      TweenMax.to(this.SHAPE.path[this.SHAPE.path.length - 1], duration, {
        [this.ACTIVE_AXIS]: newPos,
        ease: Power0.easeNone,
        onComplete: () => {
          new Shape({
            addTo: Scene,
            stroke: PIPE_STROKE * 2,
            color: this.SHAPE.color,
            translate: this.SHAPE.path[this.SHAPE.path.length - 1] });

          if (this.LENGTH > PIPE_LIFESPAN) {
            this.IS_ALIVE = false;
          } else {
            this.start();
          }
        } });

    });this.SHAPE = new Shape({ addTo: Scene, stroke: PIPE_STROKE, closed: false, ...opts });new Shape({ addTo: Scene, stroke: PIPE_STROKE * 2, translate: opts.path[0], color: opts.color });this.start();}}

const start = () => {
  Scene.updateRenderGraph();
  Scene.rotate.y += 0.003;
  requestAnimationFrame(start);
  if (!CURRENT_PIPE || !CURRENT_PIPE.IS_ALIVE) {
    const PIPE_OPTIONS = {
      color: PIPE_COLORS[Math.floor(Math.random() * PIPE_COLORS.length)],
      path: [
      {
        x: randomInRange(-AXIS_LENGTH / 2, AXIS_LENGTH / 2),
        y: randomInRange(-AXIS_LENGTH / 2, AXIS_LENGTH / 2),
        z: randomInRange(-AXIS_LENGTH / 2, AXIS_LENGTH / 2) }] };



    CURRENT_PIPE = new Pipe(PIPE_OPTIONS);
  }
  if (CURRENT_PIPE && CURRENT_PIPE.IS_ALIVE) {
    CURRENT_PIPE.SHAPE.updatePathCommands();
  }
};

start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
<script src="https://unpkg.com/zdog@1.1.0/dist/zdog.dist.js"></script>
<canvas></canvas>
* {
  box-sizing: border-box;
}
body {
  background: #111;
  min-height: 100vh;
}
canvas {
  touch-action: none;
  height: 100vh;
  width: 100vw;
}