手机浏览器图片长按无法下载之华为手机的限制问题(uniapp实现的H5推广海报图片点击下载问题)
直接上代码
解决问题的核心代码
make_canvas(img01, img02, scale) {img02.tempFilePath = this.qrcode;const query = uni.createSelectorQuery().in(this);var system_info = this.system_info;let ww = system_info.windowWidth; //准确的宽高var rpx = system_info.windowWidth / 375;var rpx1 = system_info.windowHeight / 667;var ctx = uni.createCanvasContext('myCanvas'); //绑定画布ctx.fillStyle = 'white';ctx.fillRect(0, 0, ww, this.hh);ctx.drawImage(img01.tempFilePath, 10, 10, this.ww, this.hh - 150); //填充进图片// ctx.drawImage(img01.tempFilePath, 0, 0,ww,hh); //填充进图片ctx.drawImage(this.logo, 0.68 * ww, 0.81 * this.hh, 100 * rpx, 35 * rpx); //填充进图片'../../static/img/矢量智能对象 拷贝@2x.png'ctx.drawImage(img02.tempFilePath, 0.05 * ww, this.hh * 0.825, 100 * rpx, 100 * rpx); //填充进图片ctx.setFillStyle('#41B1E6'); //设置内容1的文字样式ctx.setTextAlign('right'); //设置对于坐标点的对齐方式ctx.setFontSize(rpx * 16);ctx.fillText(this.title, ww - 14, this.hh * 0.9);ctx.setFontSize(rpx * 14);ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式ctx.fillText(this.info1, ww - 14, this.hh * 0.938);ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式ctx.fillText(this.info2, ww - 14, this.hh * 0.968);ctx.draw(); //输出到画布中uni.showLoading({//增加loading等待效果mask: true,title: '海报生成中',});setTimeout(() => {//不加延迟的话,base64有时候会赋予undefineduni.canvasToTempFilePath({canvasId: 'myCanvas',destWidth: devicePixelRatio * (scale || 1) * ww,destHeight: devicePixelRatio * (scale || 1) * this.hh,success: res => {/* 解决图片过大时, 部分手机浏览器不识别问题 */const size = this.dataURLtoBlob(res.tempFilePath).size / 1024 / 1024;if (size > 1.4) {this.make_canvas(img01, img02, 1.4 / size);} else {this.base64 = res.tempFilePath;this.canvasShow = false;}},});uni.hideLoading();}, 500);},
生成海报的全部代码 promotionPoster.vue 文件
<template><view><navator :iconStyle="iconStyle" :navStyle="navStyle"><text>我的推广海报</text></navator><view class="index" :style="{ height: hh * 0.6 + 'px' }"><view style="margin: 0 auto" :style="{ height: 90 + '%', width: 95 + '%' }"><canvas canvas-id="qrcode" class="qrcode" style="width: 400rpx; height: 400rpx" /><canvas canvas-id="myCanvas" v-show="canvasShow" id="sss" :style="{ height: hh + 'px' }"></canvas><view><img :src="base64" mode="scaleToFill" v-if="!canvasShow" class="immm" /></view></view></view><view :style="{ 'margin-top': hh * 0.38 + 'px' }"><view style="text-align: center; font-size: 28upx; font-weight: 400; color: #ffffff">长按上方图片保存,分享给朋友</view><view class="img-box" :style="{ width: phoneWidth * 0.94 + 'px' }"><img v-for="(item, index) in imgList" :key="index" class="rec" :src="item" alt="" @click="selectImg(item)" /></view></view></view>
</template><script>
import uQRCode from '../../common/uqrcode.js';
import gaussBlur from '../../utils/guessBlur.js';
import '../../utils/screen';
const StackBlur = require('stackblur-canvas');
export default {data() {return {iconStyle: 'white',navStyle: 'default1',phoneHeight: 0,phoneWidth: 0,w: 700,title: '我是智教',info1: '重新定义未来智慧教育',info2: '课桌先生不止是一张简单的课桌',qrcode: '',code: '',nickName: '',sceneStr: '',link: '',canvasShow: true,header: '',rpx: 0,base64: '',baseURL: '',imgList: ['../../static/img/1-1.png','../../static/img/1-2.png','../../static/img/1-3.png','../../static/img/1-4.png','../../static/img/1-5.png',],ewm: '',logo: '../../static/img/矢量智能对象 拷贝@2x.png',bg_img: '../../static/img/1-1.png', //线上图片system_info: [], //系统信息hh: '',ww: '',};},onLoad(option) {if (!uni.getStorageSync('token')) {uni.navigateTo({url: '/pages/login/index',});} else {this.link = option.link;this.code = option.code;this.nickName = option.nickName;if (this.nickName.length > 6) {this.title = this.title + this.nickName.substring(0, 8) + '...';} else {this.title = this.title + this.nickName;}// 获取屏幕尺寸this.system_info = uni.getSystemInfoSync(); //屏幕宽高this.phoneWidth = this.system_info.windowWidth; //:style="{'height': phoneHeight + 'upx'}":style="{'height':phoneHeight*0.8+'px'}"this.phoneHeight = this.system_info.windowHeight;this.rpx = this.windowWidth / 375;// 获取图片的宽高var img = new Image();img.src = this.imgList[0];var h = 942;var w = 658;this.ww = this.phoneWidth - 20;var ration = w / h;this.hh = this.ww / ration + 150;}
},onLoad(option) {if (!uni.getStorageSync("token")) {uni.navigateTo({url: '/pages/login/index'})}else{this.link=option.link +'?upperCode=' + option.code ;this.code = option.code;this.nickName =option.nickName;console.log('link', this.link)if(this.nickName.length>6){this.title = this.title+this.nickName.substring(0,8)+'...';}else{this.title = this.title+this.nickName} // 获取屏幕尺寸this.system_info = uni.getSystemInfoSync(); //屏幕宽高this.phoneWidth =this.system_info.windowWidth;//:style="{'height': phoneHeight + 'upx'}":style="{'height':phoneHeight*0.8+'px'}"this.phoneHeight =this.system_info.windowHeight;this.rpx = this.windowWidth /375;// 获取图片的宽高var img = new Image();img.src = this.imgList[0];var h=942;var w=658;this.ww =this.phoneWidth-20;var ration =w/h;this.hh =this.ww/ration+150; }},onShow(){},async mounted(){this.getPromoteLink();if (uni.getStorageSync("token")) {await this.getQRcode(this.link)this.$myRequest.get('/posters/page-list').then(res => {if (res.code === '0' || res.code === 0) {} else {uni.showToast({ title: res.message, icon: 'none', duration: 2000 });}}).catch(err => {console.log(err);});} else {uni.navigateTo({url: '/pages/login/index',});}},methods: {// 获取推广链接getPromoteLink() {this.$myRequest.get('/mobile/promotersbindrules/promotersurl').then(res => {if (res.code === '0' || res.code === 0) {} else {uni.showToast({ title: res.message, icon: 'none', duration: 2000 });}}).catch(err => {console.log(err);});},// 获取图片的宽高getImgProps() {var img_url = '../../static/img/kaka_bg.png';var img = new Image();img.src = img_url;//加载完成执行img.onload = function () {// 打印alert('width:' + img.width + ',height:' + img.height);};},async selectImg(value) {this.canvasShow = true;this.bg_img = value;this.ewm = value;await this.getQRcode(this.link);},// 生成验证码async getQRcode(v) {this.qrcode = await uQRCode.make({canvasId: 'qrcode',componentInstance: this,//二维码内容text: v,size: 160,margin: 5,backgroundColor: '#ffffff',foregroundColor: '#000000',//生成的图片类型fileType: 'png',errorCorrectLevel: uQRCode.errorCorrectLevel.H,});this.getImg();},getImg() {var that = this;//这里等promise执行,避免拿不到图片临时路径,只能绘制本地图片,所以要先下载,下载本地图片页不影响const promise1 = new Promise((resolve, reject) => {uni.downloadFile({url: that.bg_img,// header: {// 'content-type': 'application/jpg'// },success: res => {resolve(res);},fail: err => {uni.showLoading({//增加loading等待效果mask: true,title: '失败1',});console.log(err);},});});//TODO 二维码图片获取接口使用返回图片类型接口直接获取const promise2 = new Promise((resolve, reject) => {uni.downloadFile({url: that.ewm,//根据需要看是否要配置// header: {// 'content-type': 'application/jpg'// },success: res => {resolve(res);},fail: err => {uni.showLoading({//增加loading等待效果mask: true,title: '失败2',});},});});Promise.all([promise1, promise2]).then(values => {this.make_canvas(values[0], values[1]);});},make_canvas(img01, img02, scale) {img02.tempFilePath = this.qrcode;const query = uni.createSelectorQuery().in(this);var system_info = this.system_info;let ww = system_info.windowWidth; //准确的宽高var rpx = system_info.windowWidth / 375;var rpx1 = system_info.windowHeight / 667;var ctx = uni.createCanvasContext('myCanvas'); //绑定画布ctx.fillStyle = 'white';ctx.fillRect(0, 0, ww, this.hh);ctx.drawImage(img01.tempFilePath, 10, 10, this.ww, this.hh - 150); //填充进图片// ctx.drawImage(img01.tempFilePath, 0, 0,ww,hh); //填充进图片ctx.drawImage(this.logo, 0.68 * ww, 0.81 * this.hh, 100 * rpx, 35 * rpx); //填充进图片'../../static/img/矢量智能对象 拷贝@2x.png'ctx.drawImage(img02.tempFilePath, 0.05 * ww, this.hh * 0.825, 100 * rpx, 100 * rpx); //填充进图片ctx.setFillStyle('#41B1E6'); //设置内容1的文字样式ctx.setTextAlign('right'); //设置对于坐标点的对齐方式ctx.setFontSize(rpx * 16);ctx.fillText(this.title, ww - 14, this.hh * 0.9);ctx.setFontSize(rpx * 14);ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式ctx.fillText(this.info1, ww - 14, this.hh * 0.938);ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式ctx.fillText(this.info2, ww - 14, this.hh * 0.968);ctx.draw(); //输出到画布中uni.showLoading({//增加loading等待效果mask: true,title: '海报生成中',});setTimeout(() => {//不加延迟的话,base64有时候会赋予undefineduni.canvasToTempFilePath({canvasId: 'myCanvas',destWidth: devicePixelRatio * (scale || 1) * ww,destHeight: devicePixelRatio * (scale || 1) * this.hh,success: res => {/* 解决图片过大时, 部分手机浏览器不识别问题 */const size = this.dataURLtoBlob(res.tempFilePath).size / 1024 / 1024;if (size > 1.4) {this.make_canvas(img01, img02, 1.4 / size);} else {this.base64 = res.tempFilePath;this.canvasShow = false;}},});uni.hideLoading();}, 500);},dataURLtoBlob(dataurl) {var arr = dataurl.split(','),mime = arr[0].match(/:(.*?);/)[1],bstr = atob(arr[1]),n = bstr.length,u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}return new Blob([u8arr], { type: mime });},bcFn() {//uniapp不支持哦uni.saveImageToPhotosAlbum({//保存图片filePath: this.base64,success: res => {uni.showToast({title: '保存成功',});},fail(r) {uni.showToast({title: '保存失败',});},});},},
};
</script><style lang="scss" scoped>
.img-box {padding-top: 5%;padding-bottom: 5%;height: 230upx;overflow-x: scroll;margin: 0 auto;white-space: nowrap;
}
page {background-image: url(../../static/img/bg23.png);background-size: 100% 100%;background-color: #ffab43;background-repeat: no-repeat;
}
.rec {width: 20%;height: 220upx;margin-right: 20upx;border-radius: 4px;
}
.index {text-align: center;padding-top: 30upx;
}
#sss {position: absolute;width: 100%;top: -99999999rpx;left: -99999999rpx;z-index: 1;/* background-color: #18B566; */
}
.immm {position: relative;width: 100%;height: 100%;z-index: 9999;border-radius: 10upx;-webkit-touch-callout: default;
}.qrcode {position: absolute;top: -999rpx;left: -999rpx;z-index: 1;
}
</style>