微信小程序wxml-to-canvas保存图片时图片缺失(已解决)
原生微信小程序使用了多个生成海报保存到相册的插件,没有一个是不坑的
其中painter,会出现部分华为继续图片缺失,而且官方是GitHub,似乎2年都没更新了
最终选择了微信小程序官方推荐的wxml-to-canvas,生成海报保存相册
wxml-to-canvas问题:
1. 图片圆角时灵时不灵
2. 所有半透明背景代码失效, 半透明图片是黑色
3. 没有做海报的展示,让用户看到海报是否加载完毕,就直接保存到相册,海报如果体积太大,会出现保存的图片部分缺失
解决方法:
1. 圆角图片不要用代码设置,直接使用已生成的圆角图片贴上去
2. 放弃半透明背景代码, 直接让UI切个半透明的图, 底下要垫一张非半透明的图, 一起贴上去
3. 出现图片缺失,是因为用户网速或系统或图片域名等因素各不相同,影响了体积较大的图片加载未完成,就直接调用保存到相册,导致图片缺失,根本解决方法,始终只有一个,就是要捕捉到图片加载完毕,已全部显示出来,再保存到相册,我使用了很多方法,比如定时器延长时间,让图片加载,但定时器也不能完全满足,最终使用了微信小程序提供的image图片标签里的图片加载完毕事件,bindload事件,完美解决
代码如下:
wxml页面:
这个是vant的弹窗温馨提示 请选择相册授权
页面里的图片和海报,全部用定位给隐藏到边缘看不见,但实际上海报加载完毕的bindload依然会触发sharePath => 海报地址是画布生成的地址
上面 canvas 的 width 和 height, 可以控制海报的体积大小, 实际生成的海报像素比例, 是这里值的 3 倍
JS:
data: {isModal: false, // 强制授权相册弹窗canvasImgYes: false, // 海报图片是否加载完毕},onLoad周期里绘制海报onLoad(options) {// 获取海报 canvasthis.widget = this.selectComponent('.widget')// 开始绘制海报setTimeout(()=>{this.renderToCanvas()}, 3000) // 上面一定要用定时器, 图片越大, 时间越长, 图片越小, 时间可以缩短, 可自行尝试, 只要不报错就可以},//海报架构renderToCanvas() {// 这里汇总canvas要渲染的所有图片和文字let obj = {qrCodeUrl: this.data.shareObj.qrCodeUrl, // 二维码topImg: this.data.userInfo.topImg, // 头像contentBg: this.data.placeBgImg, // 场地图片blueOp: this.data.blueOp, // 蓝色渐变图name: this.data.userInfo.name, // 姓名,centerPlaceRadius: this.data.centerPlaceRadius, // 圆角图placeName: this.data.placeName, // 名称visitTime: this.data.shareObj.visitTime, // 时间visitorsAddress: this.data.shareObj.visitorsAddress, // 地址}const wxmls = (info) => {return ` ${info.name} ${info.placeName} ${info.placeName} 时间:${info.visitTime} 地址:${info.visitorsAddress} 长按扫码 `}// 传入要填入的动态数据let wxml = wxmls(obj)// 下方的尺寸全部除以 3 , 除以3之后的宽高, 等于wxml页面中的宽高值, 除以 3 之前的单位, // 就是设计图的尺寸大小, 3 也是控制生成海报尺寸大小的, 越大则海报体积越小const style = {container: {position: 'relative',width: 750 / 3, height: 1505 / 3,display: 'flex',flexDirection: 'column',alignItems: 'center',backgroundColor: '#5886FF',},bg: {width: 750 / 3,height: 489 / 3,},blueOp: {position: 'absolute',left: 0,top: 0,width: 750 / 3,height: 489 / 3,},content: {position: 'relative',width: 702 / 3,height: 1205 / 3,display: 'flex',alignItems: 'center',justifyContent: 'center',flexDirection: 'column',backgroundColor: '#FFFFFF',borderRadius: '15',marginTop: -224 / 3,},topImg: {position: 'absolute',width: 80 / 3,height: 80 / 3,top: 64 / 3,left: 30 / 3,borderRadius: 40 / 3,},name: {position: 'absolute',width: 200 / 3,height: 64 / 3,top: 60 / 3,left: 130 / 3,fontWeight: 600,color: '#000000',fontSize: 32 / 3,fontFamily: 'PingFangSC-Medium',},welcome: {position: 'absolute',width: 500 / 3,height: 28 * 3,fontSize: 28 / 3,color: '#666666',fontWeight: 400,left: 130 / 3,top: 107 / 3,fontFamily: 'PingFangSC-Regular',},bgCenter: {width: 642 / 3,height: 274 / 3,position: 'absolute',top: 177 / 3,left: 30 / 3,},centerImg: {width: 642 / 3,height: 274 / 3,},nameBox: {width: 340 / 3,height: 80/ 3,display: 'flex',alignItems: 'center',justifyContent: 'center',marginTop: 60 / 3,},placeName: {width: 240 / 3,height: 80 / 3,fontSize: 40 / 3,fontWeight: 500,color: '#000000',fontFamily: 'PingFangSC-Medium',},timePlaceBox: {width: 542/ 3,height: 64 / 3,},timePlace: {width: 542/ 3,height: 64 / 3,fontSize: 32 / 3,fontWeight: 400,color: '#666666',fontFamily: 'PingFangSC-Regular',},qrCodeUrl: {width: 300 / 3,height: 300 / 3,position: 'absolute',top: 757 / 3,left: 206 / 3,},hold: {width: 220 / 3,height: 52 / 3,fontSize: 26 / 3,color: '#666666',position: 'absolute',top: 1062 / 3,left: 247 / 3,fontFamily: 'PingFangSC-Regular',}}const p1 = this.widget.renderToCanvas({ wxml, style })p1.then((res) => {// 该方法是开始生成海报链接的方法this.createImage()}).catch(err => {// 下方的提示, 就是如果onLoad中的方法报错, 给的提示, 一般重新进入页面, 就不会出错wx.showToast({title: '加载失败,请重新进入页面',icon: 'none'})})},// 生成海报链接createImage() {const p2 = this.widget.canvasToTempFilePath()p2.then(res => {// 这就是海报的链接// console.log(res.tempFilePath)this.setData({sharePath: res.tempFilePath})}).catch(err=>{wx.showToast({title: '加载失败,请重新进入页面',icon: 'none'})})},// 页面中海报图片加载完毕回调canvasImgLoad() {console.log('海报图片加载完毕');this.setData({canvasImgYes: true // 用来判断海报是否已加载渲染完毕})},//点击保存按钮 该方法给页面中的保存到相册按钮extraImage() {if (this.data.canvasImgYes) { // 判断是否加载完毕的变量// 如果还是有图片缺失, 就在这里加个定时器如 2 秒后再执行下方方法this.savePhotos(this.data.sharePath)} else {wx.showToast({title: '正在生成海报,请等待~',icon: 'none',duration: 3000, //持续的时间success: res => {this.extraImage() // 还没加载完就调自己继续判断}})}},// 保存到相册的方法savePhotos(path) {wx.saveImageToPhotosAlbum({filePath: path,success(res) {wx.hideLoading()wx.showToast({title: '海报生成成功,已保存到相册',icon: 'none'})},fail: (res) => {wx.getSetting({success: res => {let authSetting = res.authSettingif (!authSetting['scope.writePhotosAlbum']) { // 如果没有授权相册, 弹窗授权相册wx.hideLoading()this.setData({isModal: true, // 控制是否弹窗强制授权的变量})}}})}})},
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
