点击查看html编辑器说明文档

时空穿梭edit icon

|
|
Fork(复制)
|
|
作者:
用户fkxIv10
提交反馈
嵌入
设置
下载
HTML
格式化
支持Emmet,输入 p 后按 Tab键试试吧!
<head> ...
展开
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.1/gl-matrix-min.js"></script>
</body>
CSS
格式化
html {
  background: #000;
}

canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
JS
格式化
(function() {
  var LorenzAttractor;

  Math.DEG = 180 / Math.PI;

  Math.RAD = Math.PI / 180;

  Math.TAU = Math.PI * 2;

  Math.PHI = 0.5 + 0.5 * Math.sqrt(5);

  LorenzAttractor = function(σ, ρ, β) {
    return function(v, t) {
      var x, y, z;
      [x, y, z] = v;
      v[0] += t * (σ * (y - x));
      v[1] += t * (x * (ρ - z) - y);
      return v[2] += t * (x * y - β * z);
    };
  };

  this.addEventListener('load', function() {
    var canvas, context, lorenz, model, mvp, p, projection, render, u, v, view;
    lorenz = LorenzAttractor(10, 28, 8 / 3);
    canvas = document.createElement('canvas');
    context = canvas.getContext('2d');
    document.body.appendChild(canvas);
    model = mat4.create();
    view = mat4.create();
    projection = mat4.create();
    mvp = mat4.create();
    v = vec4.fromValues(1, 0, 0, 1);
    u = vec4.create();
    p = vec4.create();
    return (render = function() {
      var H, HH, HW, T, W, i, j, lastX, lastY, outside, x, y, z;
      requestAnimationFrame(render);
      T = 1e-3 * Date.now();
      W = canvas.clientWidth;
      H = canvas.clientHeight;
      if (W !== canvas.width || H !== canvas.height) {
        canvas.width = W;
        canvas.height = H;
        context.globalCompositeOperation = 'screen';
        context.strokeStyle = 'rgb(30,15,80)';
      }
      mat4.identity(model);
      mat4.rotateY(model, model, 0.05 * T);
      mat4.rotateX(model, model, 1.89 * Math.PI);
      mat4.rotateZ(model, model, 1.66 * Math.PI);
      mat4.translate(model, model, [0, 0, -27]);
      mat4.lookAt(view, [0, 3, 25], [0, -2, 0], [0, 1, 0]);
      mat4.perspective(projection, 45 * Math.RAD, W / H, 1e-3, 1e3);
      mat4.scale(projection, projection, [HW = W / 2, HH = H / 2, 1]);
      [model, view, projection].reduce(function(a, b) {
        return mat4.mul(mvp, b, a);
      });
      context.setTransform(1, 0, 0, -1, HW, HH);
      for (i = j = 0; j < 100000; i = ++j) {
        if (i === 1e2) {
          vec3.copy(u, v);
        }
        lorenz(v, 5e-3);
        vec4.transformMat4(p, v, mvp);
        vec3.scale(p, p, 1 / p[3]);
        [x, y, z] = p;
        if ((-1 < z && z < 1) && (-HH < y && y < HH) && (-HW < x && x < HW)) {
          if (outside) {
            outside = false;
            context.moveTo(lastX, lastY);
          }
          context.lineTo(x, y);
        } else {
          if (!outside) {
            outside = true;
            context.lineTo(x, y);
          }
          lastX = x;
          lastY = y;
        }
      }
      vec3.copy(v, u);
      context.setTransform(1, 0, 0, 1, 0, 0);
      context.clearRect(0, 0, W, H);
      context.stroke();
      return context.beginPath();
    })();
  });

}).call(window);
预览
控制台