es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Nodo – ¿Por qué mi gif es tan lento al usar GifEncoder?

Quiero renderizar un Gif con GifEncoder (versión antigua) de Benjaminadk/gif-encoder-2, pero desafortunadamente la salida de gif es mucho más lenta o, por así decirlo, se retrasa. Este es mi código:

importar GIFEncoder desde “gif-encoder-2”;
importar fs desde “fs”;

import pkg de “canvas”;
const { createCanvas } = pkg;

deja marco = 0;
const tamaño = 200;
const fr = 60; // FPS inicial
const codificador = nuevo GIFEncoder (tamaño, tamaño);

codificador
.createReadStream()
.pipe(fs.createWriteStream(“my.gif”));

codificador.start();
codificador.setRepeat(0); // 0 para repetir, -1 para no repetir
codificador.setDelay(0); // retardo de fotograma en ms
codificador.setQuality(10); // calidad de imagen. 10 es el valor predeterminado

var lienzo = createCanvas(tamaño, tamaño),
cw = canvas.width,
ch = canvas.height,
cx = nulo,
fps = 60,
bX = 30,
bY = 30,
mM = 10,
mY = 20,
intervalo = nulo;

function gameLoop() {
cx.clearRect(0, 0, cw, cw);

cx.beginPath();
cx.fillStyle = “rojo”;
cx.arc(bX, bY, 20, 0, Math.PI * 360);
cx.fill();
si (bX >= cw || bX <= 0) {
mM * = -1;
}
si (bY >= ch || bY <= 0) {
mY * = -1;
}

bX += mM;
bY += mY;

codificador.addFrame(cx);

console.log(frame);

si (marco> 60) {
clearInterval(intervalo);
codificador.finish();
}

++marco;
}

if (typeof canvas.getContext! == indefinido) {
cx = canvas.getContext(“2d”);

intervalo = setInterval(gameLoop, 1000 / fps);
}

Este es el resultado

gif output

Tomé el ejemplo de este Fiddle, donde se puede ver lo suave que debería verse la pelota.

how it should look like

Lo que he intentado sin éxito,

  • No crear una transmisión al usar GifEncoder
  • Recopilar cx en una matriz y usar GifEncoder después, pero parece que ctx es un objeto de referencia y no pude encontrar una forma de copiarlo
  • Jugar con P5 con la esperanza de que tengan un cálculo interno cuando deltaTime es demasiado alto entre los fotogramas

¿Alguien puede ayudarme aquí o darme un consejo sobre qué hacer?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Parece que el retraso en la salida se debe a un retraso en el cálculo de fotogramas. Una forma de mejorar esto es utilizar requestAnimationFrame en lugar de setInterval para ejecutar la función gameLoop. requestAnimationFrame está optimizado para animaciones y ejecutará la función a la velocidad de fotogramas óptima basada en la velocidad de refresco del navegador.

    Aquí hay un fragmento de código actualizado que usa requestAnimationFrame:

    import GIFEncoder from "gif-encoder-2";
    import fs from "fs";
    
    import pkg from "canvas";
    const { createCanvas } = pkg;
    
    let frame = 0;
    const size = 200;
    const fr = 60; //comenzando FPS
    const encoder = new GIFEncoder(size, size);
    
    encoder.createReadStream().pipe(fs.createWriteStream("mi.gif"));
    
    encoder.start();
    encoder.setRepeat(0); // 0 para repetir, -1 para no repetir
    encoder.setDelay(0); // retraso de fotogramas en ms
    encoder.setQuality(10); // calidad de imagen. 10 es el valor por defecto.
    
    var canvas = createCanvas(size, size),
      cw = canvas.width,
      ch = canvas.height,
      cx = null,
      fps = 60,
      bX = 30,
      bY = 30,
      mX = 10,
      mY = 20;
    
    function gameLoop() {
      cx.clearRect(0, 0, cw, cw);
    
      cx.beginPath();
      cx.fillStyle = "red";
      cx.arc(bX, bY, 20, 0, Math.PI * 360);
      cx.fill();
      if (bX >= cw || bX <= 0) {
        mX *= -1;
      }
      if (bY >= ch || bY <= 0) {
        mY *= -1;
      }
    
      bX += mX;
      bY += mY;
    
      encoder.addFrame(cx);
    
      console.log(frame);
    
      if (frame > 60) {
        encoder.finish();
        return;
      }
    
      ++frame;
    
      requestAnimationFrame(gameLoop);
    }
    
    if (typeof canvas.getContext !== undefined) {
      cx = canvas.getContext("2d");
    
      requestAnimationFrame(gameLoop);
    }
    

    Esto debería resultar en una salida de gif más fluida.

Comments are closed.