uniapp canvas generates super simple poster with small program code
Canvas official website link, you can read the official introduction first to understand better
uniapp official website canvas introduction
1. First customize a poster-generating component uni-xcxcanvas.vue and create a directory with the same name
Template file code:
<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 code
<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>
2. Use the component uni-xcxcanvas
@generateImageSuccessful: The component returns the result to the parent class
MYXqOption: Parent class data is rendered to the component
<uni-xcxcanvas @generateImageSuccessful="generateImageSuccessful" :MyXqOption='MyXqOption'>
</uni-xcxcanvas>
The detailed code is as follows:
<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;
},
Generate a poster as shown below: a background image, a small program sun code