【问题记录】使用Fabric.js反序列化遇到的问题

【问题记录】使用Fabric.js反序列化遇到的问题,第1张

场景

使用fabric.js将canvas上的元素通过canvas.toJSON()转换为JSON后,要到另外一个页面上还原成原来的canvas。
需求是能够在canvas上绘制gif动图,fabric.js和原生canvas是不支持的,参考了fabricGif的做法实现了在canvas上绘制动图,实现的原理包括对fabric.Image的_render()方法的重写,要在另外一个页面的canvas上也实现绘制动图,我把fabricGif的做法同样运用到该页面中。在新页面中,我遍历JSON的objects,将里面类型为gif的对象拎出来(我使用另外一个对象记录canvas上所有元素的类型),对gif类型的对象采用fabricGif的方法进行绘制,然后将该对象在objects中剔除,最后使用canvas.loadFormJSON()绘制其他元素。

async function init () {
	const canvasObjs = JSON.parse(canvasJSON) // canvasJSON 是原来的canvas序列化后的结果
	const objects = Object.assign({}, canvasObjs.objects)
   for (let i = 0; i < objects.length; i++) {
       if (elementMap[i].type === "gif") {
           await createGif(objects[i]); // 单独绘制gif元素
           objects[i].isGif = 1
       } 
    }
	const finalObjs = objects.filter(item => item.isGif !== 1)

	canvas.loadFormJSON(JSON.stringify(finalObjs)) // 绘制非gif元素
 }

 init();

然后问题就出现了:
当页面中只有一个动图时,它可以正常运行,但是当加上一个静态图片时,这个动图只显示第一帧之后就消失了。

问题排查

我通过在那个重写的_render()方法中打log发现,在canvas上只有gif这一种图片类型元素时,_render()中的log可以随着fabric.util.requestAnimFrame的每次render正常打印,而在有其他静态图片类型元素时,这个log只会打印一次,而fabric.util.requestAnimFrame还是正常render。所以我怀疑在页面上有其他图片类型元素时,我重写的_render()会被再次重写,但是我没有证据,也不知道为什么会被重写,我甚至去看了fabric的部分相关源码,没看出什么端倪,可能是我比较菜、。。
然后我回到原来的那个canvas上,图片和gif是可以和谐共存的,原来的canvas上的静态图片,是通过fabric.Image.fromUrl()创建的,而另一个页面的canvas的静态图片,我是通过canvas.loadFromJSON()自动绘制的,意识到此处不同,我尝试在另外一个页面的canvas也采用相同的方法创建图片,然后问题就这样解决了。

问题解决
function createImg (obj) {
	const { left, top, scaleX, scaleY, src } = img
    return new Promise((resolve) => {
            fabric.Image.fromURL(src, img => {
	            img.set({
	                top,
	                left,
	                scaleX,
	                scaleY,
	                originX: 'center',
	                originY: 'center'
	            })
	            canvas.add(img)
	            resolve()
        })
    })
}

async function init () {
	const canvasObjs = JSON.parse(canvasJSON) // canvasJSON 是原来的canvas序列化后的结果
	const objects = Object.assign({}, canvasObjs.objects)
   for (let i = 0; i < objects.length; i++) {
       if (elementMap[i].type === "gif") {
           await createGif(objects[i]); // 单独绘制gif元素
           objects[i].isGif = 1
       } else if (elementMap[i].type === "img") {
       		await createImg(objects[i]);
       		objects[i].isImg = 1
    }
	const finalObjs = objects.filter(item => item.isGif !== 1 && item.isImg !== 1)

	canvas.loadFormJSON(JSON.stringify(finalObjs)) // 绘制非gif元素
 }

 init();

问题解决得有点稀里糊涂,我甚至还不清楚到底是什么原因导致我自定义的_render()方法没有正常执行,如果有懂行的大佬,希望不吝赐教,感激不尽!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/2992068.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)

保存