uniapp canvas 生成超简单海报带小程序码
canvas官网链接,可以先看下官方介绍,更好理解
uniapp官网canvas介绍
一、首先自定义一个生成海报的组件 uni-xcxcanvas.vue,创建同名目录
模板文件代码:
<template>
<view>
<view :z-index="90" :show="share_qrcode_flag" :zoom="true" :custom-style="{ background: 'rgba(0,0,0,.6)' }"
:duration="300">
<view class="share_qrcode">
<canvas canvas-id="myCanvas" class="canvas-view"></canvas>
<image @longpress="this.showSaveImgWin = true" class="show-img-view"
:src="canvasToTempFilePath"></image>
</view>
</view>
</view>
</template>
<style lang="scss">
.canvas-view {
width: 690px;
height: 1060px;
position: fixed;
top: -10000px;
left: -10000px;
}
.show-img-view {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
</style>
js代码
<script>
export default {
name: 'tr-xqgenrate',
props: {
MyXqOption: {}
},
data() {
return {
ratio: 1,
ctx: null, // 创建canvas对象
canvasToTempFilePath: null, // 保存最终生成的导出的图片地址
openStatus: true, // 声明一个全局变量判断是否授权保存到相册
share_qrcode_flag: false,
showSaveImgWin: false, //保存图片到相册
};
},
mounted() {
this.share_qrcode(this.MyXqOption)
},
methods: {
Close() {
this.share_qrcode_flag = false
setTimeout(() => {}, 180)
},
share_qrcode(XqOption) {
if (!this.canvasToTempFilePath) {
this.createCanvasImage(XqOption);
} else {}
this.share_qrcode_flag = true;
},
// 生成海报
async createCanvasImage(option) {
var that = this
if (!this.ctx) {
uni.showLoading({
title: '正在生成海报...'
});
let code = this.downloadFileImg(option.codeUrl); //小程序太阳码
let cover = this.downloadFileImg(option.GoodsImage); //商品图片
let headImg = '' //店铺头像
let bgUrl = ''; //背景图片
if (option.bgUrl) {
bgUrl = new Promise(resolve => {
uni.downloadFile({
url: option.bgUrl,
success: res => {
console.log("res.tempFilePath====", res.tempFilePath)
resolve(res.tempFilePath);
},
fail: erros => {
uni.showToast({
title: '请求错误请重试',
icon: 'loading'
});
}
});
});
}
//headImg:头像,暂未使用,对应的result[0]
Promise.all([headImg, code, cover, bgUrl]).then(result => {
const ctx = uni.createCanvasContext('myCanvas', this);
let canvasWidthPx = 620 * this.ratio,
canvasHeightPx = 1060 * this.ratio,
codeurl_width = 110, //小程序太阳码宽度
codeurl_heigth = 110, //小程序太阳码高度
codeurl_x = 545, //小程序太阳码在画布上的位置
codeurl_y = 920, //小程序太阳码在画布上的位置
coverurl_width = 690, //封面宽度
coverurl_heigth = 1060, //封面高度
coverurl_x = 0, //封面在画布上的位置
coverurl_y = 0, //封面在画布上的位置
//绘制圆角矩形
ctx.save();
ctx.translate(0, 0);
//绘制圆角矩形的各个边
this.drawRoundRectPath(ctx, 690, 1060, 10);
ctx.fillStyle = option.fillStyle || '#ffffff';
ctx.fill();
ctx.restore();
ctx.save();
ctx.beginPath(); //开始绘制
ctx.clip();
ctx.restore();
ctx.drawImage(result[2], coverurl_x, coverurl_y, coverurl_width,
coverurl_heigth);
ctx.drawImage(result[1], codeurl_x, codeurl_y, codeurl_width, codeurl_heigth);
// 绘制矩形
ctx.lineWidth = 2;
// ctx.setStrokeStyle('rgba(0, 0, 0, 0.05)');
ctx.setStrokeStyle('transparent');
this.drawRoundRect(ctx, 30, 910, 620, 120, 10)
ctx.stroke();
ctx.closePath();
ctx.draw(false, () => {
uni.canvasToTempFilePath({
canvasId: 'myCanvas',
success: res => {
that.canvasToTempFilePath = res.tempFilePath;
//将图片地址返回到父类
that.$emit("generateImageSuccessful", res
.tempFilePath);
that.showSaveImgWin = true
//保存图片到相册
that.saveShareImg(this.canvasToTempFilePath)
},
fail: err => {
uni.showToast({
title: '绘制失败'
});
},
complete: () => {
uni.hideLoading();
uni.hideToast();
},
},
this
);
});
});
}
},
drawRoundRect(ctx, x, y, width, height, radius) { //圆角
ctx.beginPath();
ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
ctx.lineTo(width - radius + x, y);
ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);
ctx.lineTo(width + x, height + y - radius);
ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2);
ctx.lineTo(radius + x, height + y);
ctx.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI);
ctx.closePath();
},
drawRoundRectPath(cxt, width, height, radius) {
cxt.beginPath(0);
//从右下角顺时针绘制,弧度从0到1/2PI
cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
//矩形下边线
cxt.lineTo(radius, height);
//左下角圆弧,弧度从1/2PI到PI
cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
//矩形左边线
cxt.lineTo(0, radius);
//左上角圆弧,弧度从PI到3/2PI
cxt.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2);
//上边线
cxt.lineTo(width - radius, 0);
//右上角圆弧
cxt.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2);
//右边线
cxt.lineTo(width, height - radius);
cxt.closePath();
},
// 保存到系统相册
saveShareImg(canvasToTempFilePath) {
uni.saveImageToPhotosAlbum({
filePath: canvasToTempFilePath,
success: () => {
uni.showToast({
title: '已保存到相册',
duration: 2000
});
},
fail: () => {}
});
}
}
};
</script>
二、使用组件 uni-xcxcanvas
@generateImageSuccessful:组件返回结果返回到父类
MYXqOption:父类数据渲染到组件
<uni-xcxcanvas @generateImageSuccessful="generateImageSuccessful" :MyXqOption='MyXqOption'>
</uni-xcxcanvas>
详细代码如下:
<view class="downloadBtn" @click="createImage">点击下载</view>
<block v-if="isDraw">
<view style="z-index: 100;">
<view @click.stop="closeMask" class="mask">
<!-- //显示一下绘制完成后的路径 aspectFill scaleToFill aspectFit -->
<image :src="tempImage" mode="widthFix" style="width: 90%;height: 100%;"
:show-menu-by-longpress="true">
</image>
<uni-xcxcanvas @generateImageSuccessful="generateImageSuccessful" :MyXqOption='MyXqOption'>
</uni-xcxcanvas>
</view>
</view>
</block>
async createImage() { //生成海报
this.isDraw = true
this.MyXqOption= {
codeUrl: this.qrCode,
GoodsImage: this.postImgUrl,
StoreHeadUrl: '',
fillStyle: '#FFFFFF',
money: 10,
primaryMoney: '原价',
Sold: 1,
GoodsName: 'dfsdfa',
StoreName: 'sdfad',
SoreAddress: 'sdfa',
SoldElementLeft: 62
}
},
/** 绘制成功后的回调 - 返回一个临时路径 */
generateImageSuccessful(image) {
// this.tempImage = image
this.uploadBanner(image, 2)
},
uploadBanner(filePath) {
var _this = this
let random_name = 's' + _this.random_string(6) + '_' + new Date().getTime();
let promise = new Promise(function(resolve, reject) {
getOssParams().then((response) => {
uni.getFileInfo({
filePath: filePath,
success: res => {
uni.uploadFile({
url: 'https://阿里云图片存储域名',
filePath: filePath,
name: 'file',
formData: {
name: filePath,
key: random_name,
policy: response.policy,
signature: response.signature,
OSSAccessKeyId: response.accessid,
success_action_status: '200'
},
success: res => {
_this.tempImage =
'https://阿里云图片存储域名' +
random_name
},
fail: uploadFileRes => {
reject(uploadFileRes);
},
complete: () => {
}
});
},
fail: uploadFileRes => {
reject(uploadFileRes);
}
});
}).catch(err => {
})
});
},
//获取随机字符
random_string(len) {
len = len || 32;
var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
var maxPos = chars.length;
var pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
},
生成海报如下图:一个背景图、一个小程序太阳码