需求背景
前段时间接到PM需求,要做一个微信端的问答+奖励金类活动,大概需求如下:
- 首先参与活动需要用户微信授权登录,用户每天默认的答题次数有限,要增加答题机会可分享给好友,好友参与答题了就会给用户增加1-2次机会。
- 首页:活动首页展示了用户目前的总奖励金额及剩余的答题次数,可通过首页进入答题页、好友排行榜、游戏规则等。
- 排行榜:页面展示参与了答题的好友列表,列出了好友的答题成绩及排行。
- 答题页:有若干题目,全部答完后提交答案,跳转至结果页。
- 结果页:展示用户当次答题分数及奖励金,有几个按钮,再次答题、分享、去论坛看答案,下载app提现,其中论坛和下载都是外链。
- 分享页:一张图片,展示了用户头像和昵称,以及本次答题的分数、奖励金、二维码和一些其他文案,用户通过长按图片将图片分享给好友或朋友圈,好友通过图片中的二维码参与活动。
相关技术
- 架构:vue+vue-router+vuex+axios全家桶
- 画二维码:qrcode.vue
- 画图: html2canvas
- 其他工具
需求和技术全部列出来了,一目了然,简单明了
具体的实现细节就不描述了,上面的需求背景中也忽略了一些其他(app内打开,与app的一些交互,微信右上角分享、注册提现等等),不是重点。
下面介绍一下开发过程中踩到的坑:
- 使用html2canvas画出的待分享图片(以下统一称分享图),模糊失真。
- 分享图不完整,或画图失败、或缺失头像、或整体黑色
- 微信ios端长按分享图,只弹出的「保存图像」和「取消」,并没有我们需要的「发送给朋友」和「识别二维码」
解决方案:
-
html2canvas画的图片失真有两个因素:
- 高分屏下canvas元素尺寸设置,这个就不多说了,很常见的问题,直接上码
function html2Image(dom) { return new Promise(function(resolve,reject) { function getPixelRatio(context) { let backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; return (window.devicePixelRatio || 1) / backingStore; }; let shareContent = dom; //需要绘图的DOM对象 let width = shareContent.offsetWidth; //dom 宽度 let height = shareContent.offsetHeight; //dom 高度 let canvas = document.createElement("canvas"); //创建一个canvas节点 let context = canvas.getContext('2d'); let scale = getPixelRatio(context);
// 这个地方是处理模糊问题的关键 canvas.width = width * scale; canvas.height = height * scale; context.scale(scale,scale); // 关闭抗锯齿 context.mozImageSmoothingEnabled = false; context.webkitImageSmoothingEnabled = false; context.msImageSmoothingEnabled = false; context.imageSmoothingEnabled = false; let opts = { scale: scale,// 添加的scale 参数 canvas: canvas,//自定义 canvas logging: false,//日志开关,便于查看html2canvas的内部执行流程 width: width,//dom 原始宽度 height: height,backgroundColor: null,// 设置null,透明背景 useCORS: true // 【重要】开启跨域配置 }; // html2canvas html2canvas(shareContent,opts).then((canvas) => { // 这里用到了canvas2image组件 var img = convertToImage(canvas,canvas.width,canvas.height,'image/jpeg'); resolve(img); })
})
}- 绘制的目标dom中有背景图片
图片最好作为img元素放进目标dom中,不要作为样式background,不然绘出的图片肯定要模糊
-
图片绘制不完整,是由于图片尚未加载完成,或者dom元素没有load结束就开始绘图
- 解决方法是遍历目标元素中的所有img标签,等待所有图片均加载完后再行绘图
-
微信ios下长按菜单没有「发送给朋友」和「识别二维码」
- 这算是微信的一个坑(以下所说的微信统一指ios下,安卓没有这个问题),因为项目中用到了vue-router,且router.mode='history',使用history作路由跳转的时候,微信的坑比较多,其中分享的时候报“invalid signature”签名错误是比较常见的,这个问题的处理方法一般是,每个页面在请求签名的时候统一使用首次进入时候的url,具体做法可自行Google/百度。按理说页面通过
wx.config({...})
注册成功后,相关功能都应该可以正常使用的,但是长按菜单还是有问题,不明所以,已经在GitHub上给weixin-js-sdk提(issue)[]了,目前尚未解答。下面介绍一下解决方案。 - 进入分享图页面的时候,不使用router跳转
具体做法是将点击跳转的行为,主要是vm.$router.push()
和
改为或者
location.href='xxx'
,这样做就是完全避开router,相当于重新打开一个页面,但是这样做有个很明显的缺点,分享页相当于新页面,那么存储在vuex store
中的状态就取不到了,如果需要带参数到分享页,可以带在href跳转的链接上,或者暂存在localStorage里 -
将history模式改为hash
因为微信做url认证的时候是忽略#
以后的部分的,所以hash模式刚好可以完美的解决这个问题new Router({ mode: 'hash',//这里默认值就是hash,可以省掉 //... })
- 这算是微信的一个坑(以下所说的微信统一指ios下,安卓没有这个问题),因为项目中用到了vue-router,且router.mode='history',使用history作路由跳转的时候,微信的坑比较多,其中分享的时候报“invalid signature”签名错误是比较常见的,这个问题的处理方法一般是,每个页面在请求签名的时候统一使用首次进入时候的url,具体做法可自行Google/百度。按理说页面通过
总结
个人微信项目经验不多,仅做记录,也希望对他人能有所帮助。相信这些问题或多或少也有人遇到过,应该也有更有效更优雅的解决方案。如有问题,请多多指教~
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。