最近项目需要添加小程序海报分享的功能,也就是可以生成商品图片和跳转商品详情页的小程序码(也叫菊花码),然后用户点击保存图片后,添加到手机相册,用户可以直接把已保存的图片发出来,其他人可以通过长按小程序码直接跳转到商品详情页。看起来比较普通的一个需求,上手做起来之后才会发现有各种各样的坑,下面就来看看遇到了那些坑吧。
一开始肯定是直接文档走起,小程序获取小程序码,刚开始还以为这个小程序码都是在前端生成的,文档一打开,直接看到接口getWXACodeUnlimit下面写着“本接口应在后端服务器调用”,因为生成小程序码需要通过接口传递参数access_token,然后获得access_token之前需要调用另外的接口getAccessToken得到access_token,这里又需要传appid和secret,这些私密字段只能在后台进行传递,那么小程序码就是后台直接返回的了。话不多说,直接上代码,(ps:我们项目是基于mpvue开发的小程序),以下是.vue文件里的template部分代码:
<template>
<div class="share_new clearfix" :class="point_default==0?'mt30':''" v-if="!this.appisH5()">
<div class="lineBox"></div>
<span class="iconfont icon-fenxiang" @click="getSharePop"></span>
<p class="iconText">分享</p>
</div>
<!-- 从分享扫码进入详情页出现返回首页悬浮按钮 -->
<img :src="staticImgUrl+'/static/images/img/btn_shop.png'" class="backHome" @click.stop="back_home_page" alt="" v-if="ifWxScan"/>
<!-- 商品详情分享弹框 -->
<div class="goodSharePop" v-if="goodSharePopShow==true">
<div class="goodSharePopMask" @click="closeSpecPop"></div>
<ul class="goodSharePopContent" :class="goodSharePopShow?'sildUp':'sildDown'">
<li class="content-item"><button class="shareBtn" open-type="share" @click="closeSpecPop">立即分享</button></li>
<li class="content-item" @click="getShareCode">生成海报 保存分享</li>
<li class="content-item cancelShare" @click="closeSpecPop">取消</li>
</ul>
</div>
<!-- 生成海报弹出框 -->
<div class="shareCodePop" v-if="shareCodeShow==true">
<div class="shareCodeMask" @click="closeSpecPop"></div>
<div class="shareCodeContent" style="width:300px;height:450px;"
v-bind:style="{left:shareCodeContent_style.left,
top:shareCodeContent_style.top}">
<!-- 保存海报的画布 -->
<canvas canvas-id='shareCanvas' style="width:300px;height:410px;background:#fff;" @click="closeSpecPop"></canvas>
<!-- 去授权按钮 -->
<button class="saveImg gradient" style="width:300px;height:40px;line-height:40px;" @click="openSetting" v-if="openSettingShow">保存图片</button>
<!-- 保存图片按钮 -->
<button class="saveImg gradient" style="width:300px;height:40px;line-height:40px;" @click="saveImageToPhotosAlbum" v-if="saveBtnShow">保存图片</button>
</div>
</div>
<loadbox ref="loadbox"></loadbox>
<layer ref="layer"></layer>
</template>
第一步,获取小程序码代码如下:
//生成海报弹框
getShareCode(){
//分享弹出框隐藏
this.goodSharePopShow = false;
//请求生成小程序码的接口
let self = this;
let layer = this.$refs.layer;
layer.open({
});
this.service.httpRequest({
methods: "post",
url: '/XXX-XXX/WXACodeUnlimit/api/getWXACodeUnlimit',
data: {
page:'pages/goodDetail/main',
scene:self.goodsId
}
}).then(function (data) {
if(data.success){
layer.close();
//海报弹框显示
self.shareCodeShow = true;
self.shareCodeUrl = data.img;
//获得分享海报画布
self.getShareCanvas();
}
}).catch(function (data) {
self.$refs.loadbox.show_reset({
reStart: function () {
self.init();
}
});
});
},
url部分的路径是我们后台通过调用小程序文档调用生成小程序码的路径,this.service.httpRequest也是项目封装好的异步请求,这部分代码的写法需要根据自己实际项目的请求来写。
坑1、返回的小程序码不能是base64格式,后台调用微信接口返回的值是,如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。一开始返回的是base64格式,在微信开发者工具上是可以显示小程序码的,但是在真机上不行,后来通过百度发现手机上小程序不支持base64格式,那么就只能后台把接口的返回格式换一下咯,通过沟通后,后台会返回小程序码的网络路径。后台修改接口后的代码如下:
//生成海报弹框
getShareCode(){
//分享弹出框隐藏
this.goodSharePopShow = false;
//请求生成小程序码的接口
let self = this;
let layer = this.$refs.layer;
layer.open({
});
this.service.httpRequest({
methods: "post",
url: '/yggjshop-front/WXACodeUnlimit/api/getWXACodeUnlimitUrl',
data: {
page:'pages/goodDetail/main',
scene:self.goodsId
}
}).then(function (data) {
if(data.success){
layer.close();
//海报弹框显示
self.shareCodeShow = true;
self.shareCodeUrl = self.imgUrl + data.imgurl;
//获得分享海报画布
self.getShareCanvas();
}
}).catch(function (data) {
self.$refs.loadbox.show_reset({
reStart: function () {
self.init();
}
});
});
},
可以看到接口名字也从getWXACodeUnlimit改成了getWXACodeUnlimitUrl,然后返回的值也从之前的base64改成了网络路径,这样第一部生成小程序码算是由后台的配合搞定了。
第二步,小程序码生成了之后,自然是需要在页面展示的,图文展示并保存图片,就会想到此处应该需要canvas来解决,因为并不是一张单纯的图片,还有相应的商品名称、价格等信息。小程序刚好也有使用canvas的api,那么就需要绘制画布了,画布绘制代码如下: