export DOM Node to GIF with gif-encoder and dom-to-image libs

为君一笑 提交于 2019-12-11 17:16:26

问题


I am desperately trying to get a non-animated gif export from a DOM Node, on client-side, but without any success yet.

I use for that the lib dom-to-image which, thanks to it's method toPixelData, return some pixels. Then I want these pixels to give me a gif. I use for this the lib gif-encoder which sounds great. I thought about using a Promise for that because the last step is to put this gif in a ZIP file created by JSZip.

Here is the code below. Consider that I already have the DOM Node as an input, with predefined height and width. Everything is going pretty well, until the step where I need to convert my GifEncoder instance to a blob, in order to download it.

import domtoimage from 'dom-to-image';
import GifEncoder from 'gif-encoder';
const fs = require('localstorage-fs');
const toBlob = require('stream-to-blob');
import JSZip from 'jszip';

const pixelsToGIF = (pixels, width, height) =>
  new Promise((resolve, reject) => {
    const gif = new GifEncoder(width, height);
    const gifFile = fs.createWriteStream('image.gif');
    gif.pipe(gifFile);
    gif.writeHeader();
    gif.addFrame(pixels);
    gif.finish();
    gif.on('data', function() {
      console.log(this); //GIFEncoder, a constructor function which extends readable-stream@~1.1.9 (cf doc.)
      toBlob(this, function (err, blob) {
        console.error(err) // No error
        console.log(blob) // Blob of size 0
        resolve(blob)
      })
    })
    gif.on('error', reject)
  })

const zip = new JSZip();
domtoimage
.toPixelData(DOMNode, { width, height })
.then(pixels => pixelsToGIF(pixels, 'image.gif', width, height))
.then(gif => { 
  console.log(gif); // Blob of size 0
  zip.file('image.gif', gif)
})
.catch(e => console.log('couldn\'t export to GIF', e));

I also tried to use gif.on('end', function () {} ) instead of gif.on('data'), but except for the property readable which is true for the event data, and false for the event end, the result is the same: Blob of size 0. Where is the mistake ?


回答1:


So the creator of gif-encoder lib found the solution, and here it is below. If I may quote him :

Our library outputs the GIF as data, not as an DOM element or similar. To aggregate this content, you can collect the stream into a buffer or pass it along to its target

So the proper code for this is finally :

import domtoimage from 'dom-to-image';
import concat from 'concat-stream';
import GifEncoder from 'gif-encoder';
import JSZip from 'jszip';

const pixelsToGIF = (pixels, width, height) =>
  new Promise((resolve, reject) => {
    const gif = new GifEncoder(width, height);
    gif.pipe(concat(resolve));
    gif.writeHeader();
    gif.addFrame(pixels);
    gif.finish();
    gif.on('error', reject);
  })

const zip = new JSZip();
domtoimage
.toPixelData(DOMNode, { width, height })
.then(pixels => pixelsToGIF(pixels, 'image.gif', width, height))
.then(gif => zip.file('image.gif', gif))
.catch(e => console.log('couldn\'t export to GIF', e));


来源:https://stackoverflow.com/questions/52877121/export-dom-node-to-gif-with-gif-encoder-and-dom-to-image-libs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!