hookehuyr

perf(poster): 优化海报生成性能,减小文件大小

- 动态调整canvas质量,大尺寸使用更低质量
- 使用jpg格式替代png减小文件体积
- 调整像素密度平衡显示质量和文件大小
- 按比例缩小海报尺寸和相关元素
......@@ -84,13 +84,28 @@ export default defineComponent({
})
/**
* @description 保存绘制的图片
* @description 保存绘制的图片(优化版本,添加质量和压缩控制)
* @param { object } config
*/
const getTempFile = (canvas) => {
// 根据Canvas尺寸动态调整质量,大尺寸用更低质量
const canvasArea = canvas.width * canvas.height
let quality = 0.8
// 如果Canvas面积超过100万像素,降低质量到0.7
if (canvasArea > 1000000) {
quality = 0.7
}
// 如果Canvas面积超过200万像素,降低质量到0.6
if (canvasArea > 2000000) {
quality = 0.6
}
Taro.canvasToTempFilePath(
{
canvas,
quality: quality, // 动态调整图片质量
fileType: 'jpg', // 使用jpg格式,比png文件更小
success: (result) => {
Taro.hideLoading()
context.emit("success", result)
......@@ -117,7 +132,7 @@ export default defineComponent({
}
/**
* step2: 开始绘制任务
* step2: 开始绘制任务(优化版本,添加像素密度控制)
* @param { Array } drawTasks 待绘制任务
*/
const startDrawing = async (drawTasks) => {
......@@ -125,8 +140,14 @@ export default defineComponent({
// const configHeight = getHeight(config)
const { ctx, canvas } = await initCanvas()
canvas.width = width
canvas.height = height
// 设置合适的像素密度,平衡质量和文件大小
const pixelRatio = Math.min(Taro.getSystemInfoSync().pixelRatio || 2, 2)
canvas.width = width * pixelRatio
canvas.height = height * pixelRatio
// 缩放画布以适应高DPI显示
ctx.scale(pixelRatio, pixelRatio)
// 如果有圆角配置,设置全局裁剪路径
if (borderRadius || borderRadiusGroup) {
......
......@@ -373,55 +373,55 @@ const posterConfig = computed(() => {
const bgImage = backgroundImages.value[currentPosterIndex.value] || currentPosterData?.backgroundImage || defaultBackground
return {
width: 750,
height: 1334,
width: 600, // 从750减少到600,减小Canvas尺寸以控制文件大小
height: 1067, // 按比例调整高度 (1334 * 600/750 = 1067)
backgroundColor: '#f5f5f5',
debug: false,
borderRadius: 15,
borderRadius: 12, // 按比例调整圆角 (15 * 600/750 = 12)
images: [
// 背景图
{
x: 0,
y: 0,
width: 750,
height: 1100,
width: 600, // 按比例调整 (750 * 0.8 = 600)
height: 880, // 按比例调整 (1100 * 0.8 = 880)
url: bgImage,
zIndex: 0
},
// 用户头像
{
x: 40,
y: 40,
width: 130,
height: 130,
x: 32, // 按比例调整 (40 * 0.8 = 32)
y: 32, // 按比例调整 (40 * 0.8 = 32)
width: 104, // 按比例调整 (130 * 0.8 = 104)
height: 104, // 按比例调整 (130 * 0.8 = 104)
url: currentMockData.value.user.avatar,
borderRadius: 65,
borderRadius: 52, // 按比例调整 (65 * 0.8 = 52)
zIndex: 2
},
// 活动logo
{
x: 450,
y: 40,
width: 250,
height: 80,
x: 360, // 按比例调整 (450 * 0.8 = 360)
y: 32, // 按比例调整 (40 * 0.8 = 32)
width: 200, // 按比例调整 (250 * 0.8 = 200)
height: 64, // 按比例调整 (80 * 0.8 = 64)
url: currentMockData.value.activity.logo,
zIndex: 2
},
// 关卡徽章
{
x: 10,
y: 880,
width: 380,
height: 100,
x: 8, // 按比例调整 (10 * 0.8 = 8)
y: 704, // 按比例调整 (880 * 0.8 = 704)
width: 304, // 按比例调整 (380 * 0.8 = 304)
height: 80, // 按比例调整 (100 * 0.8 = 80)
url: currentMockData.value.level.logo,
zIndex: 2
},
// 小程序码
{
x: 30,
y: 1100,
width: 180,
height: 180,
x: 24, // 按比例调整 (30 * 0.8 = 24)
y: 880, // 按比例调整 (1100 * 0.8 = 880)
width: 144, // 按比例调整 (180 * 0.8 = 144)
height: 144, // 按比例调整 (180 * 0.8 = 144)
url: currentMockData.value.qrcode,
zIndex: 1
}
......@@ -429,10 +429,10 @@ const posterConfig = computed(() => {
texts: [
// 家庭名称
{
x: 40,
y: 190,
x: 32, // 按比例调整 (40 * 0.8 = 32)
y: 152, // 按比例调整 (190 * 0.8 = 152)
text: currentMockData.value.family.name,
fontSize: 36,
fontSize: 29, // 按比例调整 (36 * 0.8 = 29)
color: '#ffffff',
fontWeight: 'bold',
textAlign: 'left',
......@@ -444,10 +444,10 @@ const posterConfig = computed(() => {
},
// 家庭描述
// {
// x: 40,
// y: 250,
// x: 32, // 按比例调整 (40 * 0.8 = 32)
// y: 200, // 按比例调整 (250 * 0.8 = 200)
// text: currentMockData.value.family.description,
// fontSize: 28,
// fontSize: 22, // 按比例调整 (28 * 0.8 = 22)
// color: '#ffffff',
// textAlign: 'left',
// shadowColor: 'rgba(0, 0, 0, 0.6)',
......@@ -458,27 +458,27 @@ const posterConfig = computed(() => {
// },
// 小程序码描述
{
x: 260,
y: 1125,
x: 208, // 按比例调整 (260 * 0.8 = 208)
y: 900, // 按比例调整 (1125 * 0.8 = 900)
text: currentMockData.value.qrcodeDesc,
fontSize: 30,
fontSize: 24, // 按比例调整 (30 * 0.8 = 24)
color: '#333333',
lineHeight: 40,
lineHeight: 32, // 按比例调整 (40 * 0.8 = 32)
lineNum: 2,
width: 440,
width: 352, // 按比例调整 (440 * 0.8 = 352)
textAlign: 'left',
zIndex: 1
},
// 关卡描述
{
x: 260,
y: 1180,
x: 208, // 按比例调整 (260 * 0.8 = 208)
y: 944, // 按比例调整 (1180 * 0.8 = 944)
text: '打卡点: ' + currentMockData.value.level.name,
fontSize: 32,
fontSize: 26, // 按比例调整 (32 * 0.8 = 26)
color: '#333333',
lineHeight: 50,
lineHeight: 40, // 按比例调整 (50 * 0.8 = 40)
lineNum: 2,
width: 440,
width: 352, // 按比例调整 (440 * 0.8 = 352)
textAlign: 'left',
zIndex: 1
},
......@@ -487,20 +487,20 @@ const posterConfig = computed(() => {
// 下半部分白色背景
{
x: 0,
y: 1050,
width: 750,
height: 534,
y: 840, // 按比例调整 (1050 * 0.8 = 840)
width: 600, // 按比例调整 (750 * 0.8 = 600)
height: 427, // 按比例调整 (534 * 0.8 = 427)
backgroundColor: '#ffffff',
zIndex: 0
},
// 用户信息背景遮罩
// {
// x: 30,
// y: 180,
// width: 450,
// height: 140,
// x: 24, // 按比例调整 (30 * 0.8 = 24)
// y: 144, // 按比例调整 (180 * 0.8 = 144)
// width: 360, // 按比例调整 (450 * 0.8 = 360)
// height: 112, // 按比例调整 (140 * 0.8 = 112)
// backgroundColor: 'rgba(0,0,0,0.3)',
// borderRadius: 10,
// borderRadius: 8, // 按比例调整 (10 * 0.8 = 8)
// zIndex: 1
// }
]
......