使用场景:
需实现一个微信分享的H5活动页,用户进行一个测试,提交答案后生成动态结果页,长按保存下载分享图片。
功能需求:
- 图片内容动态生成
- 图片带有用户头像及昵称
- 显示图片与实际下载图片不一致,实际下载的图片附有分享二维码
实现思路:
- 通过微信鉴权获取用户的头像和昵称
- 根据用户提交的答案生成结果
- 将实际需要转图片的dom节点通过设置层叠的方式使其不可见
- 使用html2canvas将隐藏的dom节点转canvas,再将canvas转图片
- 长按保存下载图片
具体实现:
第一步:微信鉴权获取用户的头像和昵称
通过微信鉴权获取用户头像和昵称,参见微信网络授权-获取用户信息。
第二步:根据用户提交的答案生成结果
根据用户提交的答案生成结果,由于当前展示的页面和实际需要保存的图片不一致,所以需要通过设置position和z-index,将实际需要转为图片的dom节点“隐藏”于页面下。
第三步:html转图片
import html2canvas from 'html2canvas';
...
// html转图片
function convert2img() {
let $share = document.querySelector('#share');
html2canvas($share, {
allowTaint: true,
taintTest: false,
scale: 2,
width: $share.offsetWidth,
height: $share.offsetHeight
}).then(function (canvas) {
// img为base64格式的图片
let img = canvas.toDataURL('image/jpeg', 1.0);
...
});
}
对于图片的优化处理可参见下方链接。
第四步:长按保存下载图片
微信自带长按保存图片的功能,所以需要实现的是,当用户长按“长按保存”时,如何让微信保存第三步中生成的分享图片。
实现关键:当用户长按不可见的图片,也能启用长按保存功能。
所以只需要将分享图片隐藏,并且设置它为最高层级即可。当用户长按保存时,实际长按的是被隐藏了的分享图片。
综合方案,实际的层叠关系如下:
补充: 微信头像跨域问题
canvas对于图片资源具有同源限制,存在非同源图片时,后续采用的html2canvas方法会报错。当前的解决方案为服务端代理转发,node实现方式如下:
//app.js
var proxy = require('http-proxy-middleware');
...
var app = express();
...
var wx_options = {
target: 'http://thirdwx.qlogo.cn', // 目标服务器
changeOrigin: true, // 默认false,是否需要改变原始主机头为目标URL
pathRewrite: {
'^/wx_head/mmopen' : '/mmopen' // 重写URL请求
},
onProxyReq: (proxyReq, req, res) => {
proxyReq.setHeader('Referer', 'http://thirdwx.qlogo.cn')
}
};
...
app.use('/wx_head', proxy(wx_options)); // 当请求到wx_head下时,转发请求
...
module.exports = app;
当页面调用图片时,更改微信头像前缀为:
// 原微信头像URL为"http://thirdwx.qlogo.cn/mmopen/..."
img.src = "http://www.xxx.com/wx_head/mmopen/..."