html2canvas
当我们想生成一个海报的时候, 最简单的方法是使用 html2canvas(https://html2canvas.hertzen.com/)
使用这个库有两个需要注意的地方, 一个是跨域 (useCORS), 一个清晰度 (scale). 这两个都在它的配置闻到里有说明, 就不细说了.
filter blur
今天要讨论的问题是这个库目前还没有实现的功能.* filter
就是如果我们的 dom 里使用了 filter, 比如我们想实现高斯模糊 https://www.zhangxinxu.com/wordpress/2013/11/CSS-svg-image-blur/
在 CSS 里这样写:
- .blur {
- -webkit-filter: blur(10px); /* Chrome, Opera */
- -moz-filter: blur(10px);
- -ms-filter: blur(10px);
- filter: blur(10px);
- }
html2canvas 目前没有实现这个功能, 那就只能我们自己实现了. 上面的链接里介绍了一个库 http://www.quasimondo.com/StackBlurForCanvas/StackBlur.js
使用这个库, 配合自己在 canvas 上绘制海报内容, 就能生成带高斯模糊的图片.
具体需求
但是具体的需求有一个特别的地方, 就是第一张图是用户看到的界面, 但是用户长按保存的时候, 实际下载的图片是第二张图的样子.
第一张图
第二张图
很显然我们需要有两个图层, 一个背景模糊图层, 和用户下载的图片图层, 但是两个图层交界的地方看起来要无缝, 就是一张图的感觉. 这里的实现方式是把背景图片放到下载图层里, 然后位置往上移动一定距离, 使得和背景图层重合. 这里具体实现的时候有一个细节, 就是我在两个 canvas 里对同一图片分别使用 StackBlur.JS 绘制出高斯后, 两个图层没法完全重合, 多少看起来中间有一条逢, 最后的解决方案是先从背景 canvas 里导出高斯后的图片数据, 然后使用 putImageData 把图片数据绘制到下载图层里, 这样两个图层重复才是无缝的. 这里猜想是因为两个 canvas 有一些细微差别导致的.
最后因为我们没有使用 html2canvas 这个库, 所以自己绘制的 canvas 需要导出成图片数据, 使用的 toDataURL
函数, 这个函数有两个参数, 第二个参数设置为 1 才能保证导出的质量最高.
当设置为 1 生成的图片还是模糊的时候, 我们可以放大 canvas 的尺寸, 来绘制高清图片, 具体可以看这篇文章 https://juejin.im/post/5bddac7d6fb9a049ee7fe452.
用户长按保存图片的小细节. 因为用了两个图层, 当用户长按到背景图层的时候, 可能下载的是背景图层, 这种情况如何使用用户长按任何位置都是下载的海报图层呢, 我使用的方案是动态计算除去海报图层高度以后, 上下到屏幕还有多少, 有多少就设置多少 padding, 这样用户长按屏幕任意位置都会下载海报图层.
目前还有一个问题没有解决, 就是在微信里长按的时候, 因为图片上有二维码, 所以是出现识别二维码的选项, 对用户有一定干扰.
来源: http://www.jianshu.com/p/81507540c827