|
|
- <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: '',
- // 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
- }
- },
- created(){
- console.log(this.configList);
- console.log(this.configList.user_url);
- this.qrCodeValue = `${this.configList.user_url}?vid=${this.userInfo.id}`
- },
- methods: {
- async draw() { //绘制海报
-
- uni.showLoading({
- title: '拼命绘画中...'
- })
-
- 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 = this.configList.qr_code_image
- // bg.src = this.configList.user_url + '/static/placard/placard-bg.png'
- //logo
- let logo = new Image();
- logo.src = this.configList.logo_image
- // logo.src = import.meta.env.VITE_REDIRECT_URI + '/static/placard/logo.png'
-
- console.log(this.configList.logo_image);
-
- 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) {
- uni.hideLoading()
- 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 }
- })
- },
- }
- }
- </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: 1;
- position: fixed;
- top: 100%;
- left: 0;
- }
- </style>
|