微信小程序内嵌H5页面生成分享图片并下载的坑
1.需求
最近传化产品大佬又在搞事情,
在微信小程序内嵌H5的页面上实现分享搜索结果的功能,将车辆定位的搜索结果页生成图片并附带上二维码分享出去。我一听,这好说,不就是分享图片保存图片的功能么。
整理一下需求:
点击分享定位按钮,弹出层,将当前搜索结果页面截图
点击保存按钮,将图片保存到本地
2.方案
根据需求,定了我的基本方案
html -> canvas -> image -> a[download]
- html2canvas.js:可将 htmldom 转为 canvas 元素。传送门
- canvasAPI:toDataUrl() 可将 canvas 转为 base64 格式
- 创建 a[download] 标签触发 click 事件实现下载
3.采坑表演
首先我们用到了html2canvas.js
根据官网介绍是通过js将DOM节点遍历一遍,然后基于DOM元素和样式来绘制canvas。有些样式可能无法理解,所以最后出来的结果有可能不大一样。
1 |
|
基本流程大概是:
- 递归遍历每个节点。
- 考虑节点的层级问题。
- 从底层开始画到canvas上。(跟浏览器本身的渲染很像)
原先存在图片模糊的问题,在官方1.0版本上已经修复。
先获取设备像素比,并根据比例创建尺寸更大的 canvas。如二倍屏就是二倍
1 |
|
3.1生成的截图里面,地图显示不出来
排查后发现是地图的图片跨域了,因为我们地图用的是百度地图,所以肯定跨域了。
canvas是可以绘制跨域的图片,但是此时的canvas是受到污染的,污染状态下的canvas是无法通过toDataUrl()来生成图片的。
解决方案:
方案 | 尝试 | 结局 | 分析原因
—|—|—|—|—
方案一 | 一般出现跨域, 只需要在图片设置这个属性: crossorigin=”anonymous”允许跨域即可 | 惨败 | 你设置crossOrigin=”anonymous”是表明你想跨域获取这张图片,好用在canvas.toDataURL()上,但是服务端不一定同意啊,服务端添加了access…这个字段并且value是*或者你网站的域名才行,否则就认为你无权用,结果就是无法显示
方案二 | 通过传入html2canvas的配置项中增加{ useCORS: true, useTainted: false } | 惨败 | 看了下html2canvas源码,也是通过设置crossOrigin=”anonymous”来实现图片跨域,失败原因同上
方案三 | 前端写一个node中间层来进行服务器转发 | 暂未尝试 | 考虑百度地图的图片是实时变化加载的,获取具体跨域图片的url地址难度较大
最终方案 | 不用百度地图作为背景,改为用一张静态图片 | 勉强交付
3.2保存图片
1 |
|
然而微信点击之后,没反应…
然后就去翻微信的jssdk
- 下载图片接口downloadImage,仅支持由uploadImage接口上传的图片
- uploadImage接口,仅支持由chooseImage接口选择相册里的图片
- chooseImage接口,是从本地相册选择图片
- 那么问题来了,图片都在相册了还需要我们干啥?
4.交付
最终的妥协方案:
- 用户搜索车辆定位,查询出结果
- 点击分享按钮,页面出现一个弹出框,弹出框背景为一张本地静态地图的图片,弹出框上加上二维码以及搜索结果
- 通过html2canvas,将当前弹框部分生成一张base64图片
- 微信中用户可长按页面上的图片调起 actionSheet 识别或保存图片
5.总结
因为第一次尝试在微信小程序内嵌H5的项目里做分享功能,所以需求阶段也不知道这个方案可不可行。一旦涉及到微信,就有可能出现一些之前考虑不到的问题和限制,所以,不管是产品经理还是程序员都要尽可能地多多了解。知道在微信中,能干什么,不能干什么,降低开发和反复沟通的成本。
希望以上内容能够对大家以后的开发有所帮助。