airbnb/lottie-web

How to init Lottie with offscreen canvas?

ilchenkoea opened this issue · 1 comments

Hi!

We are trying to use Lottie for rendering on offscreen canvas (via Emscripten, not Chromium).
Currently we cannot understand possibility of this...
Now I'm trying to debug this code:

var offscreenCanvas = new OffscreenCanvas(2000, 2000);
var offscreenCtx = offscreenCanvas.getContext('2d');

// Create a bitmap renderer for the off-screen canvas
var bitmapRenderer = {
  canvas: offscreenCanvas,
  context: offscreenCtx,
  clearRect: function(x, y, w, h) {
    this.context.clearRect(x, y, w, h);
  },
  drawImage: function(image, dx, dy, dw, dh) {
    this.context.drawImage(image, dx, dy, dw, dh);
  },
};

function setupLottieAnimation() {
// Load and render the Lottie animation
  var animation = lottie.loadAnimation({
      container: bitmapRenderer, // Use the off-screen canvas renderer
      offscreen: true,
      loop: false,
      autoplay: false,
      path: 'https://assets4.lottiefiles.com/packages/lf20_zyquagfl.json'// Replace with the path to your Lottie JSON file
  });

  console.log('not ready');
  return new Promise((resolve) => {
      animation.addEventListener('data_ready', function () {
          console.log('Animation data is ready');
          console.log(animation.totalFrames); // Log total frames
          console.log(animation.getDuration(false)); // Log total duration (ms
          resolve(); // Resolve the promise when animation is ready
      });
  });
}

It doesn't work, because bitmapRenderer doesn't have appendChild method, exception is thrown from this lottie code:

this.animationItem.wrapper.appendChild(this.svgElement);

And same situation if I'll try to pass offscreenCanvas object instead of bitmapRenderer.
Could you say, does lottie support offscreen canvas for this moment?
Thank you!

It works now, here is example:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Lottie Animation</title>
</head>

<body>
    <canvas id="mainCanvas"></canvas>
    <div id="lottie-container"></div>

    <!-- Load the Lottie library from a CDN -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
    <script>
        // Function to initialize and draw the Lottie animation on the off-screen canvas

        function drawLottieOnOffscreenCanvas() {
          var mainCanvas = document.getElementById('mainCanvas');
          mainCanvas.width  = 1000;
          mainCanvas.height = 1000;
          var mainCtx = mainCanvas.getContext('2d');


          // Create an off-screen canvas
          var offscreenCanvas = new OffscreenCanvas(1000, 1000);
          var offscreenCtx = offscreenCanvas.getContext('2d');

          function setupLottieAnimation() {
          // Load and render the Lottie animation
            animation = lottie.loadAnimation({
                renderer: "canvas",
                loop: false,
                autoplay: false,
                rendererSettings: {
                    context: offscreenCtx,
                    scaleMode: 'noScale',
                    clearCanvas: true
                },
                path: 'https://assets4.lottiefiles.com/packages/lf20_zyquagfl.json'// Replace with the path to your Lottie JSON file
            });

            return new Promise((resolve) => {
                animation.addEventListener('data_ready', function () {
                    console.log('Animation data is ready');
                    console.log(animation.totalFrames); // Log total frames
                    console.log(animation.getDuration(false)); // Log total duration (ms
                    resolve(); // Resolve the promise when animation is ready
                });
            });
          }



          async function manipulate(context) {
            if (context.action == "init") {
                console.log('Initializing and drawing animation');
                await setupLottieAnimation(); // Wait until the setup is complete
            } else if (context.action == "seek") {
                console.log('Seeking time:', context.time);
                animation.goToAndStop(context.time * 1000);
            }
        }

        let context0 = {action:"init"};
        manipulate(context0).then(
            function(value) {
                let context1 = {action:"seek", time:0.7};
                manipulate(context1);
            },
            function(error) {
                console.log('Error:', error);
            }
        );

        function transferToMainCanvas() {
            mainCtx.clearRect(0, 0, mainCanvas.width, mainCanvas.height);
            mainCtx.drawImage(offscreenCanvas, 0, 0);
            requestAnimationFrame(transferToMainCanvas);
        }

         transferToMainCanvas();
        }

        // Call the function to start the process
        drawLottieOnOffscreenCanvas();
      </script>
</body>

</html>