使⽤html2canvas在前端⽣成图⽚
前⾔
流量之于互联⽹公司,就如同⽔之于万物⼀样重要,那么当今国内的移动互联⽹流量主要集中在哪⾥呢?答案是显⽽易见的,那就是我们每天都在使⽤的。
2018年年初,的⽉活⽤户数已经突破了10亿,成为了国内⾸个⽉活超过10亿的产品。“3Q⼤战”之后的腾讯逐渐由封闭⾛向了开放,⽽作为腾讯在移动互联⽹时代最重要最成功的战略级产品,也在切实实践着腾讯的开放战略。在这样的⼤背景下,如何利⽤好内的流量,引导⽤户去做分享和传播,就成为摆在我们⾯前的重要课题。但是⽅⾯基于⾃⾝利益以及⽤户体验等因素的考虑,对于在内做分享和传播的内容及形式都有着很严格的规定和诸多的限制,稍不注意违反了这些规则就有可能受到惩罚,严重的甚⾄被封杀。
但是风险和收益永远是成正⽐的,有的时候为了传播的效果更好,我们就不得不“合理地”采取⼀些措施。就⽬前来说,能够在内做分享和传播的形式⽆外乎以下五种:⽂字、图⽚、H5链接、⼩程序以及短视频。从技术的⾓度来讲,⽂字、H5链接和⼩程序这三种形式管控起来⽐较容易,⽽图⽚和短视频相对⽽⾔更容易绕过的监察。虽然短视频现在很⽕爆,但是我司⽤的不多(虽然我觉得应该充分利⽤起来),所以接下来我们重点说⼀下图⽚。
业务背景
在我们的业务中经常需要引导⽤户分享图⽚到。⽬前来讲我们⽣成图⽚的⽅式主要有两种,⼀种是在APP内通过⾃主研发的Autumn系统来⽣成图⽚,另外⼀种是通过PHP后端⽣成图⽚,上传到CDN后将图⽚链接返回给前端。这两种⽅法都有它的局限性,第⼀种⽅法的局限性在于它只能在APP内使⽤,⽆法在环境或⼿机浏览器中使⽤,第⼆种⽅法的问题在于它需要后端同学来完成分享海报图的布局开发,并且需要占⽤CDN资源(需要花钱),如果⽣成的图⽚只是临时使⽤的话,这种⽅法的弊端就很明显了。所以,我们的思路是到⼀种可以直接在前端⽣成的,并且在APP、以及H5等各个环境都能使⽤的海报图⽣成⽅法。
技术选型
要在前端⽣成图⽚,⾃然会想到利⽤Canvas技术来做,但是如何利⽤Canvas在团队内有两种思路:第⼀种是完全⾃⼰封装Canvas API来作图,第⼆种是直接使⽤开源库,⽐如流⾏的html2canvas库。我个⼈主张⽤第⼆种⽅法,⼀⽅⾯是它能直接将DOM转成Canvas,⽤我们再熟悉不过的⽅式来作图简直不要太⽅便,如果是我们⾃⼰封装的话,很多基础性的⼯作,⽐如界⾯布局、各种元素的绘制等等都要做⼀遍,开发和维护的风险和成本都太⾼。另⼀⽅⾯是html2canvas库是开源已久的项⽬,应该是⽐较成熟稳定的。不过团队内仍然有⽼司机发出过预警,提及他们以前尝试过使⽤html2canvas库来
做项⽬,但是在绘制⼀些⽐较复杂的页⾯时遇到了诸多的问题,所以后来他们决定放弃这种⽅案,转⽽采取了完全⾃主开发的⽅式,也就是前⾯的第⼀种⽅法。但是⼀⽅⾯我们需要⽣成的海报图并不复杂,另⼀⽅⾯直接使⽤DOM来作图对我的诱惑⼒极⼤,所以思量之后我决定采⽤html2canvas的作图⽅案。
google官方下载app
html2canvas的基本介绍
根据html2canvas官⽅⽂档的介绍,html2canvas库的⼯作原理并不是真正的“截图”,⽽是读取⽹页上的⽬标DOM节点的信息来绘制canvas,所以它并不⽀持所有的css属性(详情参考这⾥),⽽且期望使⽤的图⽚跟当前域名同源,不过官⽅也提供了⼀些⽅法来解决跨域图⽚的加载问题。
其使⽤⽅法很简单,引⼊html2canvas库以后,拿到⽬标dom调⽤⼀下html2canvas⽅法就能⽣成canvas对象了,由于我们的⽬标是⽣成图⽚,所以还需要再调⽤DataURL()⽅法⽣成<img>标签的可⽤数据:
html2canvas(targetDom).then(canvas => { // append canvas to page });
接下来,我来列举⼀下在这个过程中我遇到的⼀些问题,以及它们的解决办法。
问题⼀:⽣成的图⽚很模糊
当我按照官⽹的介绍写好了代码准备查看效果时,我发现⽣成的图⽚很模糊,具体可以看下图的对⽐,右边是海报图DOM,左边是html2canvas 库⽣成的Canvas,下⾯如⽆特殊说明,都是左Canvas右DOM。
问题⼀:图⽚模糊
可以看到,红圈标出来的图⽚部分都很模糊。遇到这个问题后,我⾃然⽽然地去Google解决办法,你还别说,分分钟就搜出来⼀堆的结果(毕竟成熟的开源软件嘛 ),然后我天真地以为很快就能解决这个问题了。
Google⼤法好!
我随便点开了⼏个链接,看了⼀下⾥⾯的解决办法,⼤致的思路都是将canvas放⼤n倍再作图。奇怪的是我尝试过之后发现这个很多⼈都说有效的⽅法在我这⾥却完全没什么⽤,即便我放⼤200倍绘制出来的图⽚还是⼀样的模糊,所以我只能遗憾地宣告这种⽅法对我⽆效了。
于是我在想这是不是html2canvas库⾃⾝的Bug,就换了⼀个类似的库dom-to-image做了⼀下尝试,结果出乎我的意料……这货不仅仅是图⽚模糊,它是整个canvas都很模糊啊!⽽且它的还原度极差,吓得我差点把⼿机都扔掉了 。截图在这⾥,⼤家⾃⾏感受⼀下……
Are you serious?
到这⾥我就有点灰⼼了,因为从这个情况来看,很有可能是某些底层的逻辑存在问题,也就是说这个问题有可能是⽆法解决的……不过好在天⽆绝⼈之路,转折点出现在有⼀次我们⼏个⼈⼀起讨论这个问题的时候,有位同学突然发现⽣成的海报图并不是所有的图⽚都很模糊,有⼀张⼩图还是很清晰的!这个发现让我喜出望外,测试了⼀下⼦后我发现,只有作为background-image的背景图会模糊,⽽<img>图⽚标签是没有这个问题只要使⽤<img>来实现background-image的效果,问题就迎刃⽽解了。
的。那么解决的办法就很简单了,只要使⽤<img>来实现background-image的效果
问题⼆:删除线(text-decoration:line-through)线条偏下
这是个⼩问题,只是⽂本划线有些偏下⽽已,如图所⽰:
⽂本中横线偏下
解决办法也很简单,将⽂本元素设置成relative相对定位,然后应⽤伪元素模拟⼀下就好了,less代码如下:
&:after { .text-decoration-line-through();}
.text-decoration-line-through(@color: #fff) { position: absolute; width: 100%; height: 1px; top: 50%; left: 0;
content: ''; background-color: @color;}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。