Можно ли замедлить данную анимацию на canvas

Можно ли замедлить данную анимацию на canvas Codepen прилагаю https://codepen.io/jekashiyan/pen/wvqoavK

<canvas class="canvas"></canvas>

body {
  margin: 0;
  background-color: #000;
}
.canvas {
  width: 100%;
  height: 100vh;
}

.content {
  color: #fff
}

// Init Context
const c = document.querySelector(".canvas").getContext('2d');
const canvas = c.canvas;
const vertices = [];
// Effect Properties
const vertexCount = 7000; // 7000
const vertexSize = 3;
const oceanWidth = 100; // 204
const oceanHeight = -70;
const gridSize = 5; // 32
const waveSize = 18;
const perspective = 350;

// Common variables
const depth = (vertexCount / oceanWidth * gridSize);
let frame = 0;
const {sin, cos} = Math;

// Render loop
const loop = () => {
  frame++;
  if (c.canvas.width !== c.canvas.offsetWidth || c.canvas.height !== c.canvas.offsetHeight) {
    c.canvas.width = canvas.width = c.canvas.offsetWidth;
    c.canvas.height = canvas.height = c.canvas.offsetHeight;
  }


  c.clearRect(0,0, canvas.width,canvas.height);
  c.fillStyle = "rgba(0,0,0,0)";
  c.fillRect(0,0, canvas.width,canvas.height);

  c.save();
  c.translate(canvas.width / 2, canvas.height / 4);

  c.beginPath();

  vertices.forEach((vertex, i) => {
    let x = vertex[0] - frame % (gridSize * 2);
    const z = vertex[2] - frame * 2 % gridSize + (i % 2 === 0 ? gridSize / 2 : 0);
    const wave = (cos(frame / 45 + x / 50) - sin(frame / 20 + z / 50) + sin(frame / 30 + z*x / 10000));
    let y = vertex[1] + wave * waveSize;
    const a = Math.max(0, 1 - (Math.sqrt(x ** 2 + z ** 2)) / depth);

    y -= oceanHeight;

    x /= z / perspective;
    y /= z / perspective;


    if (a < 0.01) return;
    if (z < 0) return;


    c.globalAlpha = a;
    c.fillStyle = `#34344A`;
    c.fillRect(x - a * vertexSize / 2, y - a * vertexSize / 2, a * vertexSize, a * vertexSize);
    c.globalAlpha = 1;
  });
  c.restore();

  // Post-processing
  c.drawImage(canvas, 0, 0);

  c.globalCompositeOperation = 'screen';
  c.drawImage(canvas, 0, 0);
  c.globalCompositeOperation = 'source-over';

  requestAnimationFrame(loop);
};

// Generating dots
for (let i = 0; i < vertexCount; i++) {
  const x = i % oceanWidth;
  const y = 0;
  const z = i / oceanWidth >> 0;
  const offset = oceanWidth / 2;
  vertices.push([(-offset + x) * gridSize, y * gridSize, z * gridSize]);
}

loop();

Ответы (1 шт):

Автор решения: hlearn

Скорость меняется значением fps

// Init Context
const c = document.querySelector(".canvas").getContext('2d');
const canvas = c.canvas;
const vertices = [];
// Effect Properties
const vertexCount = 7000; // 7000
const vertexSize = 3;
const oceanWidth = 100; // 204
const oceanHeight = -70;
const gridSize = 5; // 32
const waveSize = 18;
const perspective = 350;

// Common variables
const depth = (vertexCount / oceanWidth * gridSize);
let frame = 0;
const {
  sin,
  cos
} = Math;

const fps = 25;
let time = 0;

// Render loop
const loop = (timestamp) => {
  if (time) {
    const delta = Math.round((timestamp - time) * fps / 1000);
    if (!delta) return requestAnimationFrame(loop);
    frame += delta;
  }
  time = timestamp;
  if (c.canvas.width !== c.canvas.offsetWidth || c.canvas.height !== c.canvas.offsetHeight) {
    c.canvas.width = canvas.width = c.canvas.offsetWidth;
    c.canvas.height = canvas.height = c.canvas.offsetHeight;
  }


  c.clearRect(0, 0, canvas.width, canvas.height);
  c.fillStyle = "rgba(0,0,0,0)";
  c.fillRect(0, 0, canvas.width, canvas.height);

  c.save();
  c.translate(canvas.width / 2, canvas.height / 4);

  c.beginPath();

  vertices.forEach((vertex, i) => {
    let x = vertex[0] - frame % (gridSize * 2);
    const z = vertex[2] - frame * 2 % gridSize + (i % 2 === 0 ? gridSize / 2 : 0);
    const wave = (cos(frame / 45 + x / 50) - sin(frame / 20 + z / 50) + sin(frame / 30 + z * x / 10000));
    let y = vertex[1] + wave * waveSize;
    const a = Math.max(0, 1 - (Math.sqrt(x ** 2 + z ** 2)) / depth);

    y -= oceanHeight;

    x /= z / perspective;
    y /= z / perspective;


    if (a < 0.01) return;
    if (z < 0) return;


    c.globalAlpha = a;
    c.fillStyle = `#34344A`;
    c.fillRect(x - a * vertexSize / 2, y - a * vertexSize / 2, a * vertexSize, a * vertexSize);
    c.globalAlpha = 1;
  });
  c.restore();

  // Post-processing
  c.drawImage(canvas, 0, 0);

  c.globalCompositeOperation = 'screen';
  c.drawImage(canvas, 0, 0);
  c.globalCompositeOperation = 'source-over';

  requestAnimationFrame(loop);
};

// Generating dots
for (let i = 0; i < vertexCount; i++) {
  const x = i % oceanWidth;
  const y = 0;
  const z = i / oceanWidth >> 0;
  const offset = oceanWidth / 2;
  vertices.push([(-offset + x) * gridSize, y * gridSize, z * gridSize]);
}

loop();
<canvas class="canvas"></canvas>

→ Ссылка