<template>
|
|
<view class="placard">
|
|
<view class="placard-content">
|
|
<view class="img-box" :style="{ width: canvasW + 'px', height: canvasH + 'px' }">
|
|
<img v-show="tempFilePath" :style="{ width: canvasW + 'px', height: canvasH + 'px' }" :src="tempFilePath" alt="" />
|
|
</view>
|
|
<div class="qrcode" style="display: none;">
|
|
<vue-qrcode :value="qrCodeValue" :width="qrCodeSize"
|
|
:color="{ dark: qrCodeDarkColor, light: qrCodeLightColor }" :margin="margin"
|
|
type="image/png"></vue-qrcode>
|
|
</div>
|
|
<canvas :style="{ width: canvasW + 'px', height: canvasH + 'px' }"
|
|
canvas-id="myCanvas" id="myCanvas"></canvas>
|
|
|
|
<view class="add-btn">
|
|
<view class="btn">
|
|
长按图片保存到手机
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import drawTextVertical from '@/utils/Canvas.js'
|
|
import VueQrcode from 'vue-qrcode'
|
|
export default {
|
|
name: 'Placard',
|
|
components : { VueQrcode },
|
|
data() {
|
|
return {
|
|
qrCodeValue: import.meta.env.VITE_REDIRECT_URI + `?vid=${this.getUserInfo()}`,
|
|
qrCodeSize: 180 * (window.innerWidth / 750),
|
|
qrCodeDarkColor: '#000',
|
|
qrCodeLightColor: '#fff',
|
|
margin: 0,
|
|
|
|
//画布信息
|
|
canvasW: 299,
|
|
canvasH: 403,
|
|
|
|
//设备信息
|
|
systemInfo: {},
|
|
|
|
//图片路径
|
|
tempFilePath: '',
|
|
|
|
_rpx: 0,
|
|
_center: 0
|
|
}
|
|
},
|
|
methods: {
|
|
async draw() { //绘制海报
|
|
let self = this
|
|
//获取设备信息
|
|
self.systemInfo = await self.getSystemInfo();
|
|
//转换相对单位
|
|
let rpx = self.systemInfo.windowWidth / 750
|
|
self._rpx = rpx
|
|
//设置画布宽高
|
|
self.canvasW = 542 * rpx
|
|
self.canvasH = 731 * rpx
|
|
|
|
//海报背景
|
|
let bg = new Image();
|
|
bg.src = import.meta.env.VITE_REDIRECT_URI + '/static/placard/placard-bg.png'
|
|
//logo
|
|
let logo = new Image();
|
|
logo.src = import.meta.env.VITE_REDIRECT_URI + '/static/placard/logo.png'
|
|
|
|
bg.onload = () => {
|
|
logo.onload = () => { //确保背景和logo加载完成(不然海报可能会少logo)
|
|
setTimeout(() => {
|
|
let ctx = document.querySelector('canvas').getContext('2d')
|
|
let img = document.querySelector('.qrcode img')
|
|
|
|
let center = self.canvasW / 2; //画布中心位置
|
|
self._center = center
|
|
|
|
//绘制图片
|
|
ctx.drawImage(bg, 0, 0, self.canvasW, self.canvasH)
|
|
ctx.drawImage(img, center - (self.qrCodeSize / 2), 295 * rpx, self.qrCodeSize, self
|
|
.qrCodeSize)
|
|
ctx.drawImage(logo, center - (100 * rpx / 2) , 60 * rpx , 100 * rpx, 100 * rpx)
|
|
|
|
//绘制文字
|
|
ctx.font = `bold ${40 * rpx}px 楷体`
|
|
ctx.textAlign = 'center'
|
|
ctx.fillStyle = "#59B495";
|
|
ctx.fillText('上门服务', center, 200 * rpx, 400)
|
|
|
|
ctx.fillStyle = "#0A543B";
|
|
ctx.font = `100 ${25 * rpx}px 楷体`
|
|
ctx.fillText(`一扫疲劳 舒服入眠`, center, 240 * rpx, 400)
|
|
|
|
ctx.font = `100 ${25 * rpx}px 宋体`
|
|
ctx.fillStyle = "#0A543B";
|
|
ctx.textAlign = 'center';
|
|
drawTextVertical(ctx, '微信扫码下单', 130 * rpx, 315 * rpx, self.qrCodeSize);
|
|
|
|
ctx.textAlign = 'center';
|
|
drawTextVertical(ctx, '在线选择技师', 400 * rpx, 315 * rpx, self.qrCodeSize);
|
|
|
|
ctx.font = `100 ${18 * rpx}px 宋体`
|
|
ctx.fillStyle = '#053323'
|
|
ctx.fillText(`长按扫一扫下单可领取`, center, 525 * rpx, 400)
|
|
|
|
ctx.font = `bold ${43 * rpx}px 宋体`
|
|
ctx.fillStyle = '#EC8D44'
|
|
ctx.fillText(`200元`, center, 580 * rpx, 400)
|
|
|
|
ctx.font = `100 ${18 * rpx}px 宋体`
|
|
ctx.fillText(`百万明星技师在线接单`, center, 625 * rpx, 400)
|
|
|
|
//画图形
|
|
this.paintingCapsule(ctx, center - (90 * rpx / 2), 250 * rpx, 90 * rpx, 25 * rpx,
|
|
13 * rpx, '#59B495', 'time')
|
|
this.paintingCapsule(ctx, center + (130 * rpx / 2), 530 * rpx, 25 * rpx, 70 * rpx,
|
|
13 * rpx, '#BCEED6', 'coupon')
|
|
|
|
////画海报最后的标签列表
|
|
this.drawList(ctx, 135 * rpx, 650 * rpx, 60 * rpx, 20 * rpx, 10 * rpx, '#59B495')
|
|
|
|
uni.canvasToTempFilePath({
|
|
x: 0, // 起点坐标
|
|
y: 0,
|
|
width: self.canvasW, // canvas 宽
|
|
height: self.canvasH, // canvas 高
|
|
canvasId: 'myCanvas', // canvas id
|
|
success(res) {
|
|
self.tempFilePath = res.tempFilePath //相对路径
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
},
|
|
// 获取设备信息
|
|
getSystemInfo() {
|
|
return new Promise((req, rej) => {
|
|
uni.getSystemInfo({
|
|
success: function(res) {
|
|
req(res)
|
|
}
|
|
});
|
|
})
|
|
},
|
|
paintingCapsule(ctx, x, y, width, height, radius, color, current) { //画椭圆(胶囊)
|
|
// 开始新的路径
|
|
ctx.beginPath();
|
|
// 绘制左上角圆角
|
|
ctx.moveTo(x + radius, y);
|
|
ctx.arcTo(x + width, y, x + width, y + height, radius);
|
|
// 绘制右上角圆角
|
|
ctx.arcTo(x + width, y + height, x, y + height, radius);
|
|
// 绘制右下角圆角
|
|
ctx.arcTo(x, y + height, x, y, radius);
|
|
// 绘制左下角圆角
|
|
ctx.arcTo(x, y, x + width, y, radius);
|
|
// 闭合路径(实际上在arcTo后已经是闭合的,但显式调用可以增加可读性)
|
|
ctx.closePath();
|
|
// 设置填充颜色
|
|
ctx.fillStyle = color;
|
|
// 填充路径
|
|
ctx.fill();
|
|
|
|
//下面是再写不同区域的内容
|
|
if (current == 'time') {
|
|
ctx.fillStyle = "#fff";
|
|
ctx.font = `100 ${17 * this._rpx}px 楷体`
|
|
ctx.fillText(`24小时`, this._center, 267 * this._rpx);
|
|
} else if (current == 'coupon') {
|
|
ctx.fillStyle = "#EC8D44";
|
|
ctx.font = `100 ${13 * this._rpx}px 楷体`
|
|
let offset = 13 * this._rpx
|
|
drawTextVertical(ctx, '优惠券', 349 * this._rpx, 555 * this._rpx, height - offset);
|
|
}
|
|
},
|
|
drawList(ctx, x, y, width, height, radius, color) { //画海报最后的标签列表
|
|
let list = ['安全', '正规', '健康', '便捷']
|
|
let offset = 15 //偏移量
|
|
let currentTagInfo = {
|
|
x
|
|
}
|
|
|
|
list.forEach(item => {
|
|
// 开始新的路径
|
|
ctx.beginPath();
|
|
// 绘制左上角圆角
|
|
ctx.moveTo(currentTagInfo.x + radius, y);
|
|
ctx.arcTo(currentTagInfo.x + width, y, currentTagInfo.x + width, y + height, radius);
|
|
// 绘制右上角圆角
|
|
ctx.arcTo(currentTagInfo.x + width, y + height, currentTagInfo.x, y + height, radius);
|
|
// 绘制右下角圆角
|
|
ctx.arcTo(currentTagInfo.x, y + height, currentTagInfo.x, y, radius);
|
|
// 绘制左下角圆角
|
|
ctx.arcTo(currentTagInfo.x, y, currentTagInfo.x + width, y, radius);
|
|
// 设置边框颜色
|
|
ctx.strokeStyle = color;
|
|
// 设置边框宽度(可选)
|
|
ctx.lineWidth = 1; // 或者你想要的任何宽度
|
|
// 闭合路径(实际上在arcTo后已经是闭合的,但显式调用可以增加可读性)
|
|
ctx.closePath();
|
|
// 绘制边框
|
|
ctx.stroke();
|
|
|
|
//圆点
|
|
ctx.beginPath();
|
|
ctx.fillStyle = color;
|
|
ctx.arc(currentTagInfo.x + (10 * this._rpx), y + (10 * this._rpx), 2, 0,360)
|
|
ctx.fill()
|
|
|
|
//绘制文本
|
|
ctx.font = `100 ${13 * this._rpx}px 楷体`
|
|
ctx.fillText(item, currentTagInfo.x + (33 * this._rpx), y + (15 * this._rpx), 400)
|
|
|
|
let next = currentTagInfo.x + width + offset; //下一个标签的位置
|
|
currentTagInfo = { x : next }
|
|
})
|
|
},
|
|
getUserInfo(){
|
|
if(localStorage.getItem('userInfo')){
|
|
return JSON.parse(localStorage.getItem('userInfo')).id
|
|
}else{
|
|
uni.navigateTo({
|
|
url: '/pages/login/login'
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.placard {
|
|
display: flex;
|
|
min-height: 100vh;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.placard-content{
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
|
|
.add-btn {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 100rpx;
|
|
width: 750rpx;
|
|
|
|
.btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 72%;
|
|
height: 80rpx;
|
|
border-radius: 40rpx;
|
|
color: white;
|
|
font-size: 28rpx;
|
|
background: linear-gradient(180deg, #6FDFBE, #5AC796);
|
|
margin-top: 40rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
canvas{
|
|
opacity: 0;
|
|
position: fixed;
|
|
top: 100%;
|
|
left: 0;
|
|
}
|
|
</style>
|