前端批量生成图片的几种方案

最近我们有个项目,需要批量生成大量图片。简单点说就是,用户提供很多组的文本组或者图片组,每组里都有很多文本或者图片,然后每组里任取一个元素出来设置样式,最后对所有这些组进行叉乘,把所有叉乘出来的结果都生成为一张图片。

举个例子,如下图,有2个文字组,2个图片组,然后每组选中一个在预览区进行预览。

然后对每个组进行叉乘,得到大量的新组合,本例需要生成的新组合数量即为:2*2*3*2 = 24,下图为其中几个新组合的例子。有点类似于公交线路,接口可能返回的线路为第一段[1路, 18路],第二段[321路,88路],那展示的就是1路->321路,1路->88路,18路->321路,18路->88路。

最后将这些组合都作为图片进行保存,也就是合成一张张图片。

所以这里就涉及到了前端批量生成图片的问题,在方案调研和实际开发中得出了如下四种方案。

方案一:展示时用dom,接口提交时用算法将dom同步为canvas然后转为为base64传给后端

这个对于前端来说是最简单的一种方式,展示时只需要通过css就可以,然后使用一些开源的包将dom转为canvas,这里推荐下html2canvas,不过这个包不是很完美,很多css3的属性无法支持,需要在不支持的时候去完善html2canvas的源码。

但这种方案有个非常严重的缺陷,就是叉乘结果太多时,需要生成大量图片,会占用大量内存,导致浏览器卡死。

方案二:展示时用canvas,接口提交时直接将canvas转为base64传给后端

这种方案优点就是最后生成图片时不需要额外多做一部,直接调用方法就可以了,同时在预览时性能要远大于dom。

缺点就是位置什么的需要计算为画布的坐标,好在有很多开源的类库可以使用,这里推荐下phaser.js,把每个元素作为精灵就可以了,但还是有很多的css样式可能需要做一些额外的工作去实现。同时和第一种方案一样,也会造成浏览器卡死。总结起来就是前端生成大量图片(短时间内上千张)造成浏览器卡死是不可避免的。

方案三:展示时用dom,提交时取出每个dom的样式、标签名、属性等拼成数组传给后端,然后后端通过这些数据拼成HTML,再在后台起一个浏览器引擎渲染HTML,然后进行截图,获得图片

这种方案前端也很简单,只需要去除每个元素的样式、标签名、属性就可以了,然后一起发给后端,因为只是数据,所以即使再多也不会太多不会卡。

然后就是后端的处理了,后端通过一系列操作进行dom拼接,渲染成一个HTML,然后使用浏览器引擎渲染截图,这里我们使用的phantomjs。下面给出一种简单的实现方案:下面的程序console出图片的base64,然后另一个进程捕获到,再生成实际的图片。

这种方案还有一个好处就是,前端点击保存后无需等待,直接通过交互的方式,使用户感觉更舒服。然后在后端可以做成任务型的,全部图片生成后,推送给前端消息,前端通知用户,并做其他修改。

方案四:展示时用dom,提交时只提交生成这些dom的数据,后端通过使用和前端一样的算法把dom在后端浏览器引擎渲染出来,再截图获得图片。

这种方式和方案三的区别就是传给后端的数据,因为方案三传的是style,数据量还是很大的,如果只传有哪些文字组、图片组,一个每个组的样式,数据量就会大减。

但这就要求后端也需要实现这个叉乘方案,这里考虑使用前后端同构的方式。

最开始我们使用的第二种方案,最近改成了第三种,性能获得了很大提升,目前生成千张图片的时间在20秒以内,随着后期优化还会更快。目前也在考虑实践一下第四种方案。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171215G0RM5R00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券