分享是传播活动,吸引用户最重要的一环。现有分享手段多是题目配合单张图片,利用点击的方式跳转到目标页面。在信息越来越丰富的今天,单个题目和图片对用户的吸引力是有限的。而在对推广要求更高的营销场景和裂变过程中,我们往往需要将页面内容一部分作为图片整体分享出去。直接利用手机原生的截屏功能会有几个问题:1)内容格式无法自定义。2)翻页情况无法处理。3)视窗区域不可控。本文通过讨论现有截屏的方案和闲鱼内部截屏方案,介绍如何利用web实现移动端高还原度富图文分享。
html2canvas是一种基于canvas,将DOM结构绘制在canvas上面产生图片的第三方库。通过如下的方式可以将对应的DOM结构绘制成图片保存出来。优势在于上手简单,使用方便。
原理如下图所示。核心逻辑是克隆对应节点DOM结构,利用parse解析成数据,构建canvas进行内容绘制,返回对应的canvas。
scale
放大后绘制,又会由于生成base64格式图片内容过长导致无法传输。该方案是利用svg可以包裹DOM结构的特性,将对应目标装载进去,之后将svg导出成base64格式的图片。使用方式如下。通过xmlns指定命名空间,防止多集合下元素和属性的冲突。后缀中的svg
和xhtml
分别表示解析方式。利用不同的解析方式,实现了svg内部嵌入html的方式。
之后只要通过encodeURIComponent(svg)
将对应的svg转换成base64就可以。优势是容易上手且不依赖第三方库。
从上面可以看到,现有的两种主流移动端截屏方案都有自己的不足。相比之下,利用canvas绘制的方法更适合SPA应用。那么我们需要解决的是html2canvas对应的几个问题:图片跨域,清晰度低,圆弧计算精度差,深层节点解析出错。
通过new Image()
的方式生成图片,在image.onload
阶段使用canvas绘制图片。此时会产生跨域限制,需要通过crossOrigin = 'Anonymous'
设置来解决这个问题。
在绘制中发现,如果采用宽度375px的canvas将图片导出,会出现图片模糊的情况。一种方案是提高原图片清晰度,但是加载速度会大大提高,用户体验不友好。另一种方式是放大canvas,利用drawImage
中的参数控制图片坐标和canvas中的绘制坐标。drawImage
中包含几个参数:控制图片的sx, sy, sWidth, sHeight和控制canvas绘制的x, y, width, height。参数具体含义如图中所示。
将方法中width和height乘上ratio,放大图片,控制绘制坐标,就能在canvas特定位置上绘制出想要的内容。考虑到小canvas在展示阶段清晰度足够,仅保存阶段需要放大三倍绘制的特性,采用第二种方法在几乎没有提高性能开销的前提下,提高清晰度。我们以实际绘制截图来看一下效果。下图左边是一倍结果,右图是三倍结果。
https://fleamarket.taobao.com/wow/z/act/solution5-1-95/fish-six-anniv-welcome?wh_biz=tm<br>https://fleamarket.taobao.com/wow/z/act/solution5-1-95/fish-six-anniv-welcome?wh_biz=tm (二维码自动识别)
圆弧精度低和深层DOM解析出错问题本质上还是由于DOM结构过于复杂,当采用通用方案处理时,难免无法覆盖。考虑到移动端内容有限,结构简单的特点。决定采用特定DOM节点针对性绘制的方案解决深层DOM解析出错的问题。好处如下:1)方法原子化,维护简单。2)绘制高度自定义化,自由组织界面结构。3)拓展性强。在同事胖仔的帮助下实现特定DOM节点绘制方案。方案构建过程中主要有如下几个难点:圆角矩形,文字自动换行。 圆角矩形:通过截断的方式绘制特定背景的圆角矩形。原理是通过createPattern
的方式在canvas上获取图片内容,再利用Path的方式,绘制对应的路线,利用canvas.arc
绘制圆弧部分,利用canvas.lineTo
绘制直线部分,截取想要的内容,实现圆角矩形。 1. 图片内容获取。 context.createPattern(imgUrl, "no-repeat")
1. 圆角矩形区域绘制
本文系作者在时代Java发表,未经许可,不得转载。
如有侵权,请联系nowjava@qq.com删除。