剪刀動畫

一個簡單的 WebGL 示例,我們使用剪刀和清除操作來 fun 地製作動畫。

使用剪刀進行動畫

在此示例中,我們使用 scissor()clear() 來製作正方形動畫。我們再次使用計時器建立動畫迴圈。請注意,這一次是正方形的位置(剪刀區域)在每一幀中更新(我們將幀率設定為大約每 17 毫秒一幀,即大約 60 幀/秒 – 每秒幀數)。

相比之下,正方形的顏色(使用 clearColor 設定)僅在新正方形建立時更新。這是 WebGL 作為狀態機的絕佳演示。對於每個正方形,我們一次設定其顏色,然後每幀僅更新其位置。WebGL 的清除顏色狀態將保持在設定的值,直到我們建立一個新正方形時再次更改它。

js
const canvas = document.querySelector("canvas");

// Variables to hold the WebGL context, and the color and
// position of animated squares.
const gl = getRenderingContext();
let color = getRandomColor();
// Unlike the browser window, vertical position in WebGL is
// measured from bottom to top. In here we set the initial
// position of the square to be at the top left corner of the
// drawing buffer.
let position = [0, gl.drawingBufferHeight];

gl.enable(gl.SCISSOR_TEST);
gl.clearColor(color[0], color[1], color[2], 1.0);

const button = document.querySelector("button");
let timer;

function getRenderingContext() {
  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;
  const gl = canvas.getContext("webgl");
  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  return gl;
}

function startAnimation(evt) {
  button.removeEventListener(evt.type, startAnimation);
  button.addEventListener("click", stopAnimation);
  document.querySelector("strong").textContent = "stop";
  timer = setInterval(drawAnimation, 17);
  drawAnimation();
}

function stopAnimation(evt) {
  button.removeEventListener(evt.type, stopAnimation);
  button.addEventListener("click", startAnimation);
  document.querySelector("strong").textContent = "start";
  clearInterval(timer);
}

stopAnimation({ type: "click" });

// Variables to hold the size and velocity of the square.
const size = [60, 60];
let velocity = 3.0;
function drawAnimation() {
  gl.scissor(position[0], position[1], size[0], size[1]);
  gl.clear(gl.COLOR_BUFFER_BIT);
  // Every frame the vertical position of the square is
  // decreased, to create the illusion of movement.
  position[1] -= velocity;
  // When the square hits the bottom of the drawing buffer,
  // we override it with new square of different color and
  // velocity.
  if (position[1] < 0) {
    // Horizontal position chosen randomly, and vertical
    // position at the top of the drawing buffer.
    position = [
      Math.random() * (gl.drawingBufferWidth - size[0]),
      gl.drawingBufferHeight,
    ];
    // Random velocity between 1.0 and 7.0
    velocity = 1.0 + 6.0 * Math.random();
    color = getRandomColor();
    gl.clearColor(color[0], color[1], color[2], 1.0);
  }
}

function getRandomColor() {
  return [Math.random(), Math.random(), Math.random()];
}

此示例的原始碼也可在 GitHub 上找到。