手机浏览器图片长按无法下载之华为手机的限制问题(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有时候会赋予undefined
uni.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有时候会赋予undefined
uni.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>