【问题标题】:How to save canvas animation as gif or webm?如何将画布动画保存为 gif 或 webm?
【发布时间】:2018-11-13 20:29:51
【问题描述】:

我已经编写了这个函数来捕获 GIF 的每一帧,但是输出非常滞后并且在数据增加时崩溃。有什么建议吗?

代码:

    function createGifFromPng(list, framerate, fileName, gifScale) {
            gifshot.createGIF({
                'images': list,
                'gifWidth': wWidth * gifScale,
                'gifHeight': wHeight * gifScale,
                'interval': 1 / framerate,
            }, function(obj) {
                if (!obj.error) {
                    var image = obj.image;
                    var a = document.createElement('a');
                    document.body.append(a);
                    a.download = fileName;
                    a.href = image;
                    a.click();
                    a.remove();
                }
            });
        }
/////////////////////////////////////////////////////////////////////////

function getGifFromCanvas(renderer, sprite, fileName, gifScale, framesCount, framerate) {
            var listImgs = [];
            var saving = false;
            var interval = setInterval(function() {
                renderer.extract.canvas(sprite).toBlob(function(b) {
                    if (listImgs.length >= framesCount) {
                        clearInterval(interval);
                        if (!saving) {
                        createGifFromPng(listImgs, framerate, fileName,gifScale);
                            saving = true;
                        }
                    }
                    else {
                        listImgs.push(URL.createObjectURL(b));
                    }
                }, 'image/gif');
            }, 1000 / framerate);
        }

【问题讨论】:

    标签: javascript html canvas three.js gif


    【解决方案1】:

    在现代浏览器中,您可以结合使用 MediaRecorder APIHTMLCanvasElement.captureStream 方法。

    MediaRecorder API 将能够在视频或音频媒体文件中即时对 MediaStream 进行编码,从而比抓取静止图像时所需的内存少得多。

    const ctx = canvas.getContext('2d');
    var x = 0;
    anim();
    startRecording();
    
    function startRecording() {
      const chunks = []; // here we will store our recorded media chunks (Blobs)
      const stream = canvas.captureStream(); // grab our canvas MediaStream
      const rec = new MediaRecorder(stream); // init the recorder
      // every time the recorder has new data, we will store it in our array
      rec.ondataavailable = e => chunks.push(e.data);
      // only when the recorder stops, we construct a complete Blob from all the chunks
      rec.onstop = e => exportVid(new Blob(chunks, {type: 'video/webm'}));
      
      rec.start();
      setTimeout(()=>rec.stop(), 3000); // stop recording in 3s
    }
    
    function exportVid(blob) {
      const vid = document.createElement('video');
      vid.src = URL.createObjectURL(blob);
      vid.controls = true;
      document.body.appendChild(vid);
      const a = document.createElement('a');
      a.download = 'myvid.webm';
      a.href = vid.src;
      a.textContent = 'download the video';
      document.body.appendChild(a);
    }
    
    function anim(){
      x = (x + 1) % canvas.width;
      ctx.fillStyle = 'white';
      ctx.fillRect(0,0,canvas.width,canvas.height);
      ctx.fillStyle = 'black';
      ctx.fillRect(x - 20, 0, 40, 40);
      requestAnimationFrame(anim);
    }
    <canvas id="canvas"></canvas>

    【讨论】:

    • 我认为部分原因是性能会随着 Blob 数量的增加而下降,因此在您可以执行此代码之前存储它们可能不可行。
    • @TheJim01 我可能应该解释一下 MediaRecorder 对视频进行动态编码,因此它不会保存静止图像,而我们存储的 chunks 确实是 final 媒体文件,即已经编码为 webm,或者说不同,不是静止图像。您只将最终视频的数据保留在内存中。
    • 嗨,我正在尝试使用此代码,但出现如下错误:canvas.captureStream 不是函数
    • @UmeshPatadiya 来自哪个浏览器?微软的仍然不支持这种方法。
    • 我在 Windows 上使用 chrome。我的项目是 Angular 6。
    【解决方案2】:

    您也可以使用https://github.com/spite/ccapture.js/ 捕捉到 gif 或视频。

    【讨论】:

      猜你喜欢
      • 2021-06-24
      • 1970-01-01
      • 2019-12-03
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 2014-02-14
      • 1970-01-01
      • 2021-04-25
      相关资源
      最近更新 更多