uniapp 生成商品海报并分享保存
<template>
<view class="center">
<view class="icon-item" @click="formposter">
<view class="haibao-icon icon"></view>
<text>生成海报</text>
</view>
<view class="canvas1"><canvas canvas-id="firstCanvas" id="firstCanvas" :style="{ height: `${HH}px`, width: `${WW * 0.85}px` }"></canvas></view>
<view class="canvas2"><canvas id="qrcode" canvas-id="qrcode" :style="{ width: `${qrcodeSize}px`, height: `${qrcodeSize}px` }" /></view>
<uni-popup ref="dialogPopup" type="dialog" :duration="100">
<uni-popup-dialog :before-close="true" @close="close" @confirm="saveImg" class="dialog">
<image v-if="isShow" class="posterImg" :src="base64" show-menu-by-longpress="true" :style="{ height: `${HH}px`, width: `${WW * 0.85}px` }"></image>
</uni-popup-dialog>
</uni-popup>
</view>
</template>
<script>
import uQRCode from '@/common/uqrcode.js';
export default {
data() {
return {
base64: '', // 海报
HH: 0, // 弹窗高度
WW: 0, // 弹窗宽度
qrcodeSize: 80, // 二维码大小
qrcodeSrc: '', // 二维码
isSave: false,
tempFilePath: '', //生成的海报路径
isShow: true, //海报显示和隐藏
bgimg: '***', //海报背景
bgadorn: '***',//海报背景
btnImg: '***',//海报背景
qrcodeText: '***',//二维码路径
productImg: '***'//产品图片
};
},
mounted() {
//获取设备的高度 *0.7是弹框高度
uni.getSystemInfo({
success: res => {
console.log(res);
this.HH = res.windowHeight * 0.7;
}
});
},
methods: {
// 生成海报
formposter() {
this.isShow = true;
this.$refs.dialogPopup.open('center');
this.WW = this.$refs.dialogPopup.popupWidth;
this.base64 = '';
this.makeEQ();
},
// 绘画 canvas海报
make_canvas(bgImg, adorn, btnImg, productImg) {
let that = this;
let ctx = uni.createCanvasContext('firstCanvas'); //绑定画布
ctx.fillRect(0, 0, that.WW, that.HH); // 海报背景色参数以此:x轴 y轴 宽 高
// ctx.drawImage(file,x,y,w,h)
// file: 图片文件
// x: x轴位置
// y: y轴位置
// w: 宽
// h: 高
// 图片大小不同的话,需要自己去调整位置与宽高,这是个细致活
console.log(that.WW * 0.85, that.HH);
ctx.drawImage(bgImg.tempFilePath, 0, 0, that.WW * 0.85, that.HH); //填充进图片 背景
ctx.setFillStyle('#000'); //设置文字color
ctx.font = 'normal bold 14px Arial,sans-serif ';
ctx.setTextAlign('center'); //同上
that.canvasWraptitleText(ctx, '', that.shareParam.productName, that.WW / 2.35, that.HH / 10, 170, 17, 1);
ctx.lineWidth = 3;
ctx.strokeRect(that.WW * 0.06, that.HH * 0.12, that.WW * 0.72, that.HH * 0.73);
ctx.drawImage(productImg.tempFilePath, that.WW * 0.065, that.HH * 0.12, that.WW * 0.72, that.HH * 0.7);
ctx.drawImage(adorn.tempFilePath, 0, that.HH * 0.7, that.WW * 0.85, that.HH * 0.35);
ctx.setFillStyle('#FFFFFF'); // 二维码后面的白色背景
ctx.lineWidth = 3;
ctx.strokeRect(that.WW * 0.54, that.HH * 0.75, that.WW * 0.276, that.HH * 0.21); //二维码边框
ctx.fillRect(that.WW * 0.54, that.HH * 0.75, that.WW * 0.273, that.HH * 0.21); // 二维码后面的白色背景
ctx.drawImage(that.qrcodeSrc, that.WW * 0.551, that.HH * 0.76, that.WW * 0.25, that.HH * 0.187); //填充进图片 二维码
ctx.setFillStyle('#fff');
ctx.font = 'normal bold 15px Arial,sans-serif ';
that.canvasWraptitleText(ctx, '商品价格: ¥', that.shareParam.productPrice + '', that.WW * 0.2, that.HH * 0.81, 100, 17, 1);
// ctx.fillText('商品价格: ¥15.8',that.WW*0.22, that.HH*0.81);
that.canvasWraptitleText(ctx, '名称: ', that.userParam.name, that.WW * 0.2, that.HH * 0.87, 100, 17, 1);
// ctx.fillText('姓名: 张兮兮',that.WW*0.22, that.HH*0.87);
ctx.drawImage(btnImg.tempFilePath, that.WW * 0.022, that.HH * 0.9, that.WW * 0.43, that.HH * 0.065);
ctx.draw(); //输出到画布中
setTimeout(() => {
//不加延迟的话,base64有时候会赋予undefined
uni.canvasToTempFilePath({
canvasId: 'firstCanvas',
success: res => {
this.base64 = res.tempFilePath;
that.isSave = true;
}
});
uni.hideLoading();
}, 300);
},
// 下载画布需要的图片
uploadImg() {
uni.showLoading({
//增加loading等待效果
title: '正在生成海报',
mask: true
});
var that = this;
// 背景图
let promise1 = new Promise((resolve, reject) => {
uni.downloadFile({
url: that.bgimg,
success: function(res) {
resolve(res);
},
fail: err => {
uni.hideLoading();
console.log(err, that.bgimg, 'err1');
}
});
});
// 底部装饰图
let promise2 = new Promise((resolve, reject) => {
uni.downloadFile({
url: that.bgadorn,
success: function(res) {
resolve(res);
},
fail: err => {
uni.hideLoading();
console.log(err, that.bgadorn, 'err2');
}
});
});
// 按钮图片
let promise3 = new Promise((resolve, reject) => {
uni.downloadFile({
url: that.btnImg,
success: function(res) {
resolve(res);
},
fail: err => {
uni.hideLoading();
console.log(err, that.btnImg, 'err3');
}
});
});
// 商品图片
let promise4 = new Promise((resolve, reject) => {
uni.downloadFile({
url: that.shareParam.productImg,
success: function(res) {
resolve(res);
},
fail: err => {
uni.hideLoading();
console.log(err, that.shareParam.productImg, 'err4');
}
});
});
Promise.all([promise1, promise2, promise3, promise4]).then(values => {
console.log(values);
this.make_canvas(values[0], values[1], values[2], values[3]);
});
},
// 生成二维码
makeEQ() {
var that = this;
uQRCode.make({
canvasId: 'qrcode',
text: that.qrcodeText,
size: that.qrcodeSize,
success: res => {
console.log(res);
that.qrcodeSrc = res;
that.uploadImg(); // 开始 本地下载图片
}
});
},
showposter() {
this.isShow = true;
this.$refs.dialogPopup.open('center');
this.WW = this.$refs.dialogPopup.popupWidth;
if (this.base64) {
setTimeout(() => {
this.createposter();
}, 2000);
console.log(this.base64, 'this.base64');
} else {
this.makeEQ();
}
},
createposter() {
let ctx = uni.createCanvasContext('firstCanvas'); //绑定画布
ctx.fillRect(0, 0, this.WW * 0.85, this.HH); // 海报背景色参数以此:x轴 y轴 宽 高
ctx.drawImage(this.base64, 0, 0, this.WW * 0.85, this.HH); //填充进图片 背景
ctx.draw();
},
// 处理商品文字信息
canvasWraptitleText(canvas, title, text, x, y, maxWidth, lineHeight, maxRowNum) {
if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') {
return;
}
// canvas.font = '20px Bold PingFang SC'; //绘制文字的字号和大小
// 字符分隔为数组
var arrText = text.split('');
var line = '';
var rowNum = 1;
for (var n = 0; n < arrText.length; n++) {
var testLine = line + arrText[n];
var metrics = canvas.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
if (rowNum >= maxRowNum) {
var arrLine = testLine.split('');
arrLine.splice(-5);
var newTestLine = arrLine.join('');
newTestLine += '...';
canvas.fillText(title + newTestLine, x, y);
//如果需要在省略号后面添加其他的东西,就在这个位置写(列如添加扫码查看详情字样)
//canvas.fillStyle = '#2259CA';
//canvas.fillText('扫码查看详情',x + maxWidth-90, y);
return;
}
canvas.fillText(title + line, x, y);
line = arrText[n];
y += lineHeight;
rowNum += 1;
} else {
line = testLine;
}
}
canvas.fillText(title + line, x, y);
},
close() {
this.isShow = false;
this.$refs.dialogPopup.close();
},
saveImg() {
if (!this.isSave) {
uni.showToast({
title: '请等待海报生成',
icon: 'none'
});
}
uni.showLoading({
title: '正在存储图片',
mask: true
});
uni.saveImageToPhotosAlbum({
filePath: this.base64,
success: () => {
uni.showToast({
title: '已存至系统相册',
duration: 500,
success: () => {
uni.hideLoading();
this.isShow = false;
this.$refs.dialogPopup.close();
}
});
},
fail: () => {
uni.hideLoading();
}
});
},
}
};
</script>
<style lang="less">
.canvas1 {
height: 100%;
width: 100%;
position: fixed;
left: 100%;
margin: 0;
}
.canvas2 {
position: absolute;
position: fixed;
left: 100%;
}
.dialog {
.posterImg {
width: 100%;
height: 100%;
}
}
.product-intro {
padding: 40rpx 30rpx;
}
</style>
效果图(想达到以下效果背景图需自行添加)
注意:
1、数据中使用到的地址均为网络图片,须通过downloadFile来将网络图片下载只本地
(在这时候遇到过真机调试无法下载要到微信公众平台配置downloadFile合法域名如下图)
2、如果需要让用户可以下载或分享图片 需要将海报转成图片 其中用到的canvas就需要通过css将其移出屏幕以外(使用隐藏会使整个canvas不生效)
3、项目中使用到了uni-popup和uni-popup-dialog插件 不需要自行省略