前言:这阵子接手小程序的开发,也算是遇到一些问题,学习过程中也做一些自己的总结。主要的一个需求就是在用户进行转发的时候转发图片都不一样,而且其中数据是要随着更改的。第一思路用到的就是canvas,查了一些相关资料,参照思路,最后也是实现了产品所要的功能。其他也不多说,在下面直接上一些实现思路和代码吧。PS:因为我用的Taro框架,是react写法,标签就不换了,看官们能看懂的,就是原生小程序标签变大小写
(这里是实现分享转发的时候每次生成不一样的分享图片)
HTML部分(CSS就不放上来了)
<View className=‘index‘> // 我是自定义生成的那张分享图哦,会随着数据变化而变化~ <View className=‘save-view‘> <Canvas className=‘poster‘ canvasId=‘poster‘ style=‘width:250px;height:200px;‘></Canvas> </View> <CoverView>我是这个页面要展示的内容 <Button className=‘share-btn‘ open-type="share">我是分享按钮</Button> </CoverView> </View>
这里要注意:1.因为是分享转发带的图片,按官方比例5:4。建议canvas的大小也是这个比例,例如500*400rpx;
2.在首页主要展示的内容用cover-view原生组件包起来,为的就是在进入页面覆盖掉canvas让用户看不到;
3.这里建议最外层的cover-view采用fixed方式,因为有些手机识别z-index其实不是很好;
JS部分
state: IState = { recordList: null, // 列表数据 imgUrl: ‘‘, // 生成分享图链接 }; // data变量区 // 获得canvas图片信息 ImageInfo(path: any) { return new Promise((resolve, reject) => { Taro.getImageInfo( { src: path, success: function (res) { resolve(res) }, fail: function (res) { reject(res) } } ) }) } // 绘画Canvas-分享图 drawTitle(datas: any, title: string) { new Promise((resolve, reject) => { let rpx = 0 Taro.getSystemInfo({ success: function (res) { rpx = res.windowWidth / 375 } }) // 这里计算rpx是为了适配更多的手机,毕竟dpr值都不一样。可以要也可以不要 this.ImageInfo(‘https://static.jingzhuan.cn/WeChat/longtou/share-img-bg.png‘).then(res => { // 这里注意,因为canvas画图片是需要图片信息的,即临时路径类,最好是先把背景图放在网络上再通过小程序API生成获取路径 // 获取画布 const cvsCtx = Taro.createCanvasContext(‘poster‘, this) cvsCtx.drawImage(res.path, 0, 0, 250 * rpx, 200 * rpx) // 绘制背景底图 cvsCtx.setFontSize(16) cvsCtx.setFillStyle(‘#FFFFFF‘) cvsCtx.fillText(title, (250 - cvsCtx.measureText(title).width) * rpx / 2, 26 * rpx, 120 * rpx) // 计算标题文字所占宽度好做绝对居中计算 for (let b = 0; b < 3; b++) { cvsCtx.setFontSize(14) // 设置字体大小 cvsCtx.setFillStyle(‘#941D11‘) // 设置字体颜色 cvsCtx.fillText(datas[b].name, 95 * rpx, (88 + b * 38) * rpx, 70 * rpx) cvsCtx.setFontSize(14) if (datas[b].rise_percent > 0) { // 判断数据是否需要改变字体颜色 cvsCtx.setFillStyle(‘#FB4949‘) } else { cvsCtx.setFillStyle(‘#00CC66‘) } cvsCtx.fillText(`${datas[b].rise_percent}%`, 180 * rpx, (88 + b * 38) * rpx, 70 * rpx) // 绘制文字所在位置 } cvsCtx.draw(true) }) resolve() }).then(() => { this.generateUrl() // 当页面的canvas画成功后就调取生成临时路径 }) } // 截取canvas生成临时路径 async generateUrl() { const that = this setTimeout(() => { Taro.canvasToTempFilePath({ x: 0, y: 0, width: 500, // 截取的宽度 height: 400, // 截取的高度 destWidth: 500, // 生成的图片宽度 destHeight: 400, // 生成的图片高度 canvasId: ‘poster‘, // 生成对象的canvasid success: function (res) { that.goQiniu(res.tempFilePath) // 生成图片成功后调取上传到网络上 }, fail: function (res) { console.log(‘绘制临时路径失败‘) } }) }, 1000) // 设置1秒定时是防止canvas画一半,一般1秒是差不多的 } // 上传临时图片到七牛获取网络链接(这里是七牛SDK的上传方法,其他服务器都有对应的,根据情况而改变哦~) async goQiniu(imgUrl: any) { const that = this const res = await getQiniu({ key: ‘sig‘ }) qiniuUploader.upload(imgUrl, (res: any) => { let audioURL = (这里写你们的服务器域名进行拼接,例如:https://www.baidu.com/) + res.key that.state.imgUrl = audioURL // 最后生成的网络连接,是可以直接在网页上打开看到图片的,然后复制给到全局变量给分享的时候获取 }, (error: any) => { console.error(‘error: ‘ + JSON.stringify(error)); }, { uptoken: res.token, region: ‘ECN‘, // 华东区 key: `longtou/share/${Math.random().toString(36).slice(2, 10)}.png` // 自动生成随机命名 }, ) } // 自定义分享 onShareAppMessage() {return { title: ‘我是分享标题~好不好看~‘, path: shareUrl, imageUrl: this.state.imgUrl, // 生成的分享图赋值给到小程序自定义分享图链接 success: function () { // 转发成功 console.log(shareUrl) }, fail: function () { // 转发失败 console.log(‘转发失败‘) } } }
以上就是主要的思路代码,最后注意要在进入页面后就执行canvas画图,即在onlaod的时候执行drawTitle方法,这样就避免在页面加载完后用户马上点击分享转发canvas图还没画完的情况
具体效果就如下(demo可能比较粗糙哈哈):