263 lines
11 KiB
Vue
263 lines
11 KiB
Vue
<template>
|
||
<view>
|
||
<view class="body">
|
||
<view class="list">
|
||
<view class="poster-container">
|
||
<canvas canvas-id="posterCanvas" class="poster-canvas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"></canvas>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
|
||
} from '@/utils/api.js'
|
||
import notHave from '@/components/not-have.vue';
|
||
import topSafety from '@/components/top-safety.vue';
|
||
import tabBar from '@/components/tab-bar.vue';
|
||
export default {
|
||
components: {
|
||
notHave,
|
||
topSafety,
|
||
tabBar,
|
||
},
|
||
data() {
|
||
return {
|
||
canvasWidth: 300,
|
||
canvasHeight: 600, // 减小画布高度
|
||
posterImageUrl: '',
|
||
// 示例数据,实际应从用户信息获取
|
||
userInfo: {
|
||
name: '154****9090', // 原来的手机号改为用户名
|
||
phone: '邀请您加入聊天', // 原来的姓名改为邀请文案
|
||
avatar: '/static/images/avatar.png' // 头像路径
|
||
},
|
||
topImageRatio: 0, // 顶部图片的宽高比
|
||
topImageLocalPath: '', // 顶部图片本地路径
|
||
qrCodeLocalPath: '' // 二维码图片本地路径
|
||
}
|
||
},
|
||
onLoad() {
|
||
this.initCanvas();
|
||
},
|
||
onReady() {
|
||
// 页面准备完成后自动生成海报
|
||
setTimeout(() => {
|
||
this.downloadImages().then(() => {
|
||
this.generatePoster();
|
||
}).catch(err => {
|
||
console.error('下载图片失败:', err);
|
||
uni.hideLoading();
|
||
uni.showToast({
|
||
title: '图片加载失败',
|
||
icon: 'none'
|
||
});
|
||
});
|
||
}, 500);
|
||
},
|
||
methods: {
|
||
initCanvas() {
|
||
// 获取设备信息来自适应不同屏幕
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
// 设置canvas宽度为屏幕宽度的90%,减少左右边距
|
||
this.canvasWidth = systemInfo.windowWidth * 0.9;
|
||
// 设置canvas高度
|
||
this.canvasHeight = this.canvasWidth * 2.0; // 减小长宽比到1.8:1
|
||
},
|
||
|
||
// 下载线上图片到本地临时文件
|
||
async downloadImages() {
|
||
return new Promise((resolve, reject) => {
|
||
uni.showLoading({
|
||
title: '图片加载中...'
|
||
});
|
||
|
||
// 同时下载两个图片
|
||
Promise.all([
|
||
this.downloadImage('https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/cb61a8209c59166e5a56e9c5c470e8f1.png'),
|
||
this.downloadImage('https://nvlovers.oss-cn-qingdao.aliyuncs.com/uploads/20251226/54a0da02080e49dbf2d6412791c58281.png')
|
||
]).then(([topImagePath, qrCodePath]) => {
|
||
this.topImageLocalPath = topImagePath;
|
||
this.qrCodeLocalPath = qrCodePath;
|
||
|
||
// 获取顶部图片信息
|
||
uni.getImageInfo({
|
||
src: topImagePath,
|
||
success: (res) => {
|
||
// 计算图片的宽高比
|
||
this.topImageRatio = res.width / res.height;
|
||
resolve();
|
||
},
|
||
fail: (err) => {
|
||
console.error('获取图片信息失败:', err);
|
||
// 如果获取失败,使用默认比例
|
||
this.topImageRatio = 3; // 默认宽高比 3:1
|
||
resolve();
|
||
}
|
||
});
|
||
}).catch(err => {
|
||
console.error('下载图片失败:', err);
|
||
reject(err);
|
||
});
|
||
});
|
||
},
|
||
|
||
// 下载单个图片
|
||
downloadImage(url) {
|
||
return new Promise((resolve, reject) => {
|
||
uni.downloadFile({
|
||
url: url,
|
||
success: (res) => {
|
||
if (res.statusCode === 200) {
|
||
resolve(res.tempFilePath);
|
||
} else {
|
||
reject(new Error(`下载失败: ${res.statusCode}`));
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
reject(err);
|
||
}
|
||
});
|
||
});
|
||
},
|
||
|
||
// 绘制圆角矩形的方法
|
||
drawRoundedRect(ctx, x, y, width, height, radius) {
|
||
ctx.beginPath();
|
||
ctx.moveTo(x + radius, y);
|
||
ctx.lineTo(x + width - radius, y);
|
||
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
|
||
ctx.lineTo(x + width, y + height - radius);
|
||
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
|
||
ctx.lineTo(x + radius, y + height);
|
||
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
|
||
ctx.lineTo(x, y + radius);
|
||
ctx.quadraticCurveTo(x, y, x + radius, y);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
},
|
||
|
||
generatePoster() {
|
||
uni.showLoading({
|
||
title: '海报生成中...'
|
||
});
|
||
|
||
const ctx = uni.createCanvasContext('posterCanvas', this);
|
||
|
||
// 清空画布
|
||
ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
|
||
|
||
// 绘制圆角背景
|
||
ctx.setFillStyle('#ffffff');
|
||
this.drawRoundedRect(ctx, 0, 0, this.canvasWidth, this.canvasHeight, 20);
|
||
|
||
// 计算居中位置
|
||
const centerX = this.canvasWidth / 2;
|
||
|
||
// 绘制顶部图片,宽度与canvas一致,高度自适应
|
||
const topImageWidth = this.canvasWidth;
|
||
// 根据图片原始宽高比计算高度
|
||
const topImageHeight = this.topImageRatio > 0 ? topImageWidth / this.topImageRatio : topImageWidth * 0.3;
|
||
const topImageX = 0;
|
||
const topImageY = 0; // 紧贴顶部
|
||
ctx.drawImage(this.topImageLocalPath, topImageX, topImageY, topImageWidth, topImageHeight);
|
||
|
||
// 绘制二维码,减小尺寸
|
||
const qrCodeSize = this.canvasWidth * 0.5; // 减小二维码尺寸
|
||
const qrCodeY = topImageHeight + 30; // 减少间距
|
||
const qrCodeX = (this.canvasWidth - qrCodeSize) / 2;
|
||
ctx.drawImage(this.qrCodeLocalPath, qrCodeX, qrCodeY, qrCodeSize, qrCodeSize);
|
||
|
||
// 绘制用户信息区域
|
||
const userInfoY = qrCodeY + qrCodeSize + 10;
|
||
const avatarSize = this.canvasWidth * 0.15;
|
||
|
||
// 计算头像和文字的整体高度,用于居中对齐
|
||
const textHeight = 40; // 文字区域高度估算
|
||
const totalHeight = Math.max(avatarSize, textHeight);
|
||
const avatarY = userInfoY + (totalHeight - avatarSize) / 2;
|
||
const textY = userInfoY + (totalHeight - textHeight) / 2;
|
||
|
||
// 头像居中对齐
|
||
const avatarX = (this.canvasWidth - (avatarSize + this.canvasWidth * 0.4)) / 2;
|
||
|
||
// 绘制头像
|
||
ctx.save();
|
||
ctx.beginPath();
|
||
ctx.arc(avatarX + avatarSize/2, avatarY + avatarSize/2, avatarSize/2, 0, 2 * Math.PI);
|
||
ctx.clip();
|
||
ctx.drawImage(this.userInfo.avatar, avatarX, avatarY, avatarSize, avatarSize);
|
||
ctx.restore();
|
||
|
||
// 绘制姓名和手机号(现在是手机号和邀请文案),与头像垂直居中对齐
|
||
const textAreaX = avatarX + avatarSize + 20;
|
||
ctx.setTextAlign('left');
|
||
ctx.setFontSize(18);
|
||
ctx.setFillStyle('#333333');
|
||
ctx.fillText(this.userInfo.name, textAreaX, textY + 20); // 垂直居中显示手机号
|
||
|
||
ctx.setFontSize(14);
|
||
ctx.setFillStyle('#999999');
|
||
ctx.fillText(this.userInfo.phone, textAreaX, textY + 45); // 垂直居中显示邀请文案
|
||
|
||
// 绘制完成,导出图片
|
||
ctx.draw(false, () => {
|
||
// 延迟执行以确保绘制完成
|
||
setTimeout(() => {
|
||
uni.canvasToTempFilePath({
|
||
canvasId: 'posterCanvas',
|
||
success: (res) => {
|
||
this.posterImageUrl = res.tempFilePath;
|
||
uni.hideLoading();
|
||
uni.showToast({
|
||
title: '海报生成成功',
|
||
icon: 'success'
|
||
});
|
||
},
|
||
fail: (err) => {
|
||
console.error('生成海报失败:', err);
|
||
uni.hideLoading();
|
||
uni.showToast({
|
||
title: '海报生成失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}, this);
|
||
}, 3000);
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
page {
|
||
background: #FFFFFF;
|
||
}
|
||
</style>
|
||
<style>
|
||
.body {
|
||
position: relative;
|
||
padding: 0 20rpx; /* 减少左右padding */
|
||
}
|
||
|
||
.list {
|
||
position: relative;
|
||
margin: 20rpx 0 0 0;
|
||
}
|
||
|
||
.poster-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.poster-canvas {
|
||
background-color: #f5f5f5;
|
||
/* 移除之前的圆角设置,因为现在在canvas中绘制 */
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
</style> |