快速上手 | uQRCode 中文文档
<template>
<view class="box">
<view id="draw" style="overflow: hidden;" ref="shellContainerRef">
<canvas id="qrcode" canvas-id="qrcode" style="width: 250px;height: 250px;"></canvas>
<view class="carNo">{{obj.carNumber}}</view>
<view class="item">
<text>企业名称</text>
<text style="font-weight: bold;">{{obj.secondCompanyName}}</text>
</view>
<view class="item">
<text>客户名称</text>
<text>{{obj.cusName}}</text>
</view>
<view class="item">
<text>物料名称</text>
<text>{{obj.materialName}}</text>
</view>
<view class="item">
<text>下单重量</text>
<text>{{obj.weight}}吨</text>
</view>
</view>
<view class="btns">
<u-button text="保存图片" color="#07C15F" shape="circle" @click="SaveImage"></u-button>
<u-button text="分享图片" color="#F08E00" :plain="true" shape="circle"></u-button>
</view>
</view>
<canvas style="width: 350px; height: 500px;" canvas-id="firstCanvas" id="firstCanvas"></canvas>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import UQRCode from 'uqrcodejs';
import { pickQrcode } from "@/api/api.js";
let obj = reactive({});
onLoad(async (e) => {
let r = await pickQrcode({
id: e.id
});
Object.assign(obj, r.data);
var qr = new UQRCode();
qr.data = obj.ocrContext;
qr.size = 250;
qr.make();
var canvasContext = uni.createCanvasContext('qrcode', this);
qr.canvasContext = canvasContext;
qr.drawCanvas();
});
const SaveImage = () => {
uni.showLoading({
title: '绘制中',
mask: true
});
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: 250,
height: 250,
canvasId: 'qrcode',
success: (res) => {
console.log(res);
const ctx = uni.createCanvasContext('firstCanvas');
ctx.beginPath();
ctx.setFillStyle('#ffffff');
ctx.fillRect(0, 0, 350, 500);
ctx.drawImage(res.tempFilePath, 50, 20, 250, 250);
ctx.setFontSize(35);
ctx.setFillStyle('#F08E00');
ctx.fillText(obj.carNumber, 100, 323);
ctx.beginPath();
ctx.setStrokeStyle('#bbbbbb');
ctx.setLineWidth(4);
for (var i = 0; i < 50; i++) {
ctx.moveTo(10 * i, 350)
ctx.lineTo(10 * i + 5, 350)
}
ctx.stroke();
ctx.setFontSize(14);
ctx.setFillStyle('#868686');
ctx.fillText('企业名称', 12, 390);
ctx.fillText('客户名称', 12, 420);
ctx.fillText('物料名称', 12, 450);
ctx.fillText('下单重量', 12, 480);
ctx.setFontSize(14);
ctx.setFillStyle('#101010');
ctx.setTextAlign('left');
ctx.fillText(obj.secondCompanyName, 350 - 12 - ctx.measureText(obj.secondCompanyName).width, 390, 350 - 12 - 80);
ctx.fillText(obj.cusName, 350 - 12 - ctx.measureText(obj.cusName).width, 420, 350 - 12 - 80);
ctx.fillText(obj.materialName, 350 - 12 - ctx.measureText(obj.materialName).width, 450, 350 - 12 - 80);
ctx.fillText((obj.weight) + '吨', 350 - 12 - ctx.measureText((obj.weight) + '吨').width, 480, 350 - 12 - 80);
ctx.draw(true, () => {
setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
canvasId: 'firstCanvas',
fileType: 'png',
quality: 1,
success: (success) => {
savePoster(success.tempFilePath);
},
fail: (e) => {
uni.hideLoading();
uni.showToast({
title: '图片生成失败',
icon: 'none'
});
}
})
}, 500);
});
const savedFilePath = res.tempFilePath;
const path = plus.io.convertLocalFileSystemURL(savedFilePath)
const fileReader = new plus.io.FileReader()
fileReader.readAsDataURL(path)
fileReader.onloadend = (res) => {
const ctx = uni.createCanvasContext('firstCanvas');
ctx.beginPath();
ctx.setFillStyle('#ffffff');
ctx.fillRect(0, 0, 350, 500);
ctx.drawImage(res.target.result, 50, 20, 250, 250);
ctx.setFontSize(35);
ctx.setFillStyle('#F08E00');
ctx.fillText(obj.carNumber, 100, 323);
ctx.beginPath();
ctx.setStrokeStyle('#bbbbbb');
ctx.setLineWidth(4);
for (var i = 0; i < 50; i++) {
ctx.moveTo(10 * i, 350)
ctx.lineTo(10 * i + 5, 350)
}
ctx.stroke();
ctx.setFontSize(14);
ctx.setFillStyle('#868686');
ctx.fillText('企业名称', 12, 390);
ctx.fillText('客户名称', 12, 420);
ctx.fillText('物料名称', 12, 450);
ctx.fillText('下单重量', 12, 480);
ctx.setFontSize(14);
ctx.setFillStyle('#101010');
ctx.setTextAlign('left');
ctx.fillText(obj.secondCompanyName, 350 - 12 - ctx.measureText(obj.secondCompanyName).width, 390, 350 - 12 - 80);
ctx.fillText(obj.cusName, 350 - 12 - ctx.measureText(obj.cusName).width, 420, 350 - 12 - 80);
ctx.fillText(obj.materialName, 350 - 12 - ctx.measureText(obj.materialName).width, 450, 350 - 12 - 80);
ctx.fillText((obj.weight) + '吨', 350 - 12 - ctx.measureText((obj.weight) + '吨').width, 480, 350 - 12 - 80);
ctx.draw(true, () => {
setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
canvasId: 'firstCanvas',
fileType: 'png',
quality: 1,
success: (success) => {
savePoster(success.tempFilePath);
},
fail: (e) => {
uni.hideLoading();
uni.showToast({
title: '图片生成失败',
icon: 'none'
});
}
})
}, 500);
});
}
},
fail: () => {
uni.hideLoading();
uni.showToast({
title: '二维码绘制失败',
icon: 'none'
});
}
});
};
const savePoster = (posterImage) => {
uni.saveImageToPhotosAlbum({
filePath: posterImage,
success: () => {
setTimeout(() => {
uni.showToast({
title: '保存到相册成功',
icon: 'none'
});
}, 200)
},
fail: () => {
uni.showToast({
title: '保存失败',
icon: 'none'
});
},
complete: () => {
uni.hideLoading()
}
})
}
</script>
-
UQRCode
是用于生成二维码的库。
-
pickQrcode
是一个获取二维码数据的 API。
-
obj
是一个响应式对象,用于存储从 API 获取的数据。
-
SaveImage
函数用于将生成的二维码保存为图片,并支持在不同平台(小程序、APP、H5)上的保存逻辑。
-
savePoster
函数用于将生成的图片保存到相册
<style scoped lang="scss">
.box {
margin: 20rpx 24rpx 0;
background-color: #fff;
border-radius: 12rpx;
overflow: hidden;
#qrcode {
margin: 54rpx auto;
}
.carNo {
margin-bottom: 30rpx;
padding: 18rpx 0;
text-align: center;
font-size: 56rpx;
color: #F08E00;
border-bottom: 4rpx dashed #bbb;
}
.item {
padding: 0 26rpx;
display: flex;
justify-content: space-between;
align-items: center;
text {
padding: 14rpx 0;
color: #868686;
font-size: 28rpx;
}
text:last-child {
color: #101010;
}
}
.btns {
margin-top: 70rpx;
padding-bottom: 50rpx;
display: flex;
align-items: center;
:deep(.u-button) {
width: 230rpx;
}
}
}
#firstCanvas {
position: fixed;
top: -500px;
left: -350px;
opacity: 0;
}
</style>