perf(poster): 优化海报生成性能,减小文件大小
- 动态调整canvas质量,大尺寸使用更低质量 - 使用jpg格式替代png减小文件体积 - 调整像素密度平衡显示质量和文件大小 - 按比例缩小海报尺寸和相关元素
Showing
2 changed files
with
71 additions
and
50 deletions
| ... | @@ -84,13 +84,28 @@ export default defineComponent({ | ... | @@ -84,13 +84,28 @@ export default defineComponent({ |
| 84 | }) | 84 | }) |
| 85 | 85 | ||
| 86 | /** | 86 | /** |
| 87 | - * @description 保存绘制的图片 | 87 | + * @description 保存绘制的图片(优化版本,添加质量和压缩控制) |
| 88 | * @param { object } config | 88 | * @param { object } config |
| 89 | */ | 89 | */ |
| 90 | const getTempFile = (canvas) => { | 90 | const getTempFile = (canvas) => { |
| 91 | + // 根据Canvas尺寸动态调整质量,大尺寸用更低质量 | ||
| 92 | + const canvasArea = canvas.width * canvas.height | ||
| 93 | + let quality = 0.8 | ||
| 94 | + | ||
| 95 | + // 如果Canvas面积超过100万像素,降低质量到0.7 | ||
| 96 | + if (canvasArea > 1000000) { | ||
| 97 | + quality = 0.7 | ||
| 98 | + } | ||
| 99 | + // 如果Canvas面积超过200万像素,降低质量到0.6 | ||
| 100 | + if (canvasArea > 2000000) { | ||
| 101 | + quality = 0.6 | ||
| 102 | + } | ||
| 103 | + | ||
| 91 | Taro.canvasToTempFilePath( | 104 | Taro.canvasToTempFilePath( |
| 92 | { | 105 | { |
| 93 | canvas, | 106 | canvas, |
| 107 | + quality: quality, // 动态调整图片质量 | ||
| 108 | + fileType: 'jpg', // 使用jpg格式,比png文件更小 | ||
| 94 | success: (result) => { | 109 | success: (result) => { |
| 95 | Taro.hideLoading() | 110 | Taro.hideLoading() |
| 96 | context.emit("success", result) | 111 | context.emit("success", result) |
| ... | @@ -117,7 +132,7 @@ export default defineComponent({ | ... | @@ -117,7 +132,7 @@ export default defineComponent({ |
| 117 | } | 132 | } |
| 118 | 133 | ||
| 119 | /** | 134 | /** |
| 120 | - * step2: 开始绘制任务 | 135 | + * step2: 开始绘制任务(优化版本,添加像素密度控制) |
| 121 | * @param { Array } drawTasks 待绘制任务 | 136 | * @param { Array } drawTasks 待绘制任务 |
| 122 | */ | 137 | */ |
| 123 | const startDrawing = async (drawTasks) => { | 138 | const startDrawing = async (drawTasks) => { |
| ... | @@ -125,8 +140,14 @@ export default defineComponent({ | ... | @@ -125,8 +140,14 @@ export default defineComponent({ |
| 125 | // const configHeight = getHeight(config) | 140 | // const configHeight = getHeight(config) |
| 126 | const { ctx, canvas } = await initCanvas() | 141 | const { ctx, canvas } = await initCanvas() |
| 127 | 142 | ||
| 128 | - canvas.width = width | 143 | + // 设置合适的像素密度,平衡质量和文件大小 |
| 129 | - canvas.height = height | 144 | + const pixelRatio = Math.min(Taro.getSystemInfoSync().pixelRatio || 2, 2) |
| 145 | + | ||
| 146 | + canvas.width = width * pixelRatio | ||
| 147 | + canvas.height = height * pixelRatio | ||
| 148 | + | ||
| 149 | + // 缩放画布以适应高DPI显示 | ||
| 150 | + ctx.scale(pixelRatio, pixelRatio) | ||
| 130 | 151 | ||
| 131 | // 如果有圆角配置,设置全局裁剪路径 | 152 | // 如果有圆角配置,设置全局裁剪路径 |
| 132 | if (borderRadius || borderRadiusGroup) { | 153 | if (borderRadius || borderRadiusGroup) { | ... | ... |
| ... | @@ -373,55 +373,55 @@ const posterConfig = computed(() => { | ... | @@ -373,55 +373,55 @@ const posterConfig = computed(() => { |
| 373 | const bgImage = backgroundImages.value[currentPosterIndex.value] || currentPosterData?.backgroundImage || defaultBackground | 373 | const bgImage = backgroundImages.value[currentPosterIndex.value] || currentPosterData?.backgroundImage || defaultBackground |
| 374 | 374 | ||
| 375 | return { | 375 | return { |
| 376 | - width: 750, | 376 | + width: 600, // 从750减少到600,减小Canvas尺寸以控制文件大小 |
| 377 | - height: 1334, | 377 | + height: 1067, // 按比例调整高度 (1334 * 600/750 = 1067) |
| 378 | backgroundColor: '#f5f5f5', | 378 | backgroundColor: '#f5f5f5', |
| 379 | debug: false, | 379 | debug: false, |
| 380 | - borderRadius: 15, | 380 | + borderRadius: 12, // 按比例调整圆角 (15 * 600/750 = 12) |
| 381 | images: [ | 381 | images: [ |
| 382 | // 背景图 | 382 | // 背景图 |
| 383 | { | 383 | { |
| 384 | x: 0, | 384 | x: 0, |
| 385 | y: 0, | 385 | y: 0, |
| 386 | - width: 750, | 386 | + width: 600, // 按比例调整 (750 * 0.8 = 600) |
| 387 | - height: 1100, | 387 | + height: 880, // 按比例调整 (1100 * 0.8 = 880) |
| 388 | url: bgImage, | 388 | url: bgImage, |
| 389 | zIndex: 0 | 389 | zIndex: 0 |
| 390 | }, | 390 | }, |
| 391 | // 用户头像 | 391 | // 用户头像 |
| 392 | { | 392 | { |
| 393 | - x: 40, | 393 | + x: 32, // 按比例调整 (40 * 0.8 = 32) |
| 394 | - y: 40, | 394 | + y: 32, // 按比例调整 (40 * 0.8 = 32) |
| 395 | - width: 130, | 395 | + width: 104, // 按比例调整 (130 * 0.8 = 104) |
| 396 | - height: 130, | 396 | + height: 104, // 按比例调整 (130 * 0.8 = 104) |
| 397 | url: currentMockData.value.user.avatar, | 397 | url: currentMockData.value.user.avatar, |
| 398 | - borderRadius: 65, | 398 | + borderRadius: 52, // 按比例调整 (65 * 0.8 = 52) |
| 399 | zIndex: 2 | 399 | zIndex: 2 |
| 400 | }, | 400 | }, |
| 401 | // 活动logo | 401 | // 活动logo |
| 402 | { | 402 | { |
| 403 | - x: 450, | 403 | + x: 360, // 按比例调整 (450 * 0.8 = 360) |
| 404 | - y: 40, | 404 | + y: 32, // 按比例调整 (40 * 0.8 = 32) |
| 405 | - width: 250, | 405 | + width: 200, // 按比例调整 (250 * 0.8 = 200) |
| 406 | - height: 80, | 406 | + height: 64, // 按比例调整 (80 * 0.8 = 64) |
| 407 | url: currentMockData.value.activity.logo, | 407 | url: currentMockData.value.activity.logo, |
| 408 | zIndex: 2 | 408 | zIndex: 2 |
| 409 | }, | 409 | }, |
| 410 | // 关卡徽章 | 410 | // 关卡徽章 |
| 411 | { | 411 | { |
| 412 | - x: 10, | 412 | + x: 8, // 按比例调整 (10 * 0.8 = 8) |
| 413 | - y: 880, | 413 | + y: 704, // 按比例调整 (880 * 0.8 = 704) |
| 414 | - width: 380, | 414 | + width: 304, // 按比例调整 (380 * 0.8 = 304) |
| 415 | - height: 100, | 415 | + height: 80, // 按比例调整 (100 * 0.8 = 80) |
| 416 | url: currentMockData.value.level.logo, | 416 | url: currentMockData.value.level.logo, |
| 417 | zIndex: 2 | 417 | zIndex: 2 |
| 418 | }, | 418 | }, |
| 419 | // 小程序码 | 419 | // 小程序码 |
| 420 | { | 420 | { |
| 421 | - x: 30, | 421 | + x: 24, // 按比例调整 (30 * 0.8 = 24) |
| 422 | - y: 1100, | 422 | + y: 880, // 按比例调整 (1100 * 0.8 = 880) |
| 423 | - width: 180, | 423 | + width: 144, // 按比例调整 (180 * 0.8 = 144) |
| 424 | - height: 180, | 424 | + height: 144, // 按比例调整 (180 * 0.8 = 144) |
| 425 | url: currentMockData.value.qrcode, | 425 | url: currentMockData.value.qrcode, |
| 426 | zIndex: 1 | 426 | zIndex: 1 |
| 427 | } | 427 | } |
| ... | @@ -429,10 +429,10 @@ const posterConfig = computed(() => { | ... | @@ -429,10 +429,10 @@ const posterConfig = computed(() => { |
| 429 | texts: [ | 429 | texts: [ |
| 430 | // 家庭名称 | 430 | // 家庭名称 |
| 431 | { | 431 | { |
| 432 | - x: 40, | 432 | + x: 32, // 按比例调整 (40 * 0.8 = 32) |
| 433 | - y: 190, | 433 | + y: 152, // 按比例调整 (190 * 0.8 = 152) |
| 434 | text: currentMockData.value.family.name, | 434 | text: currentMockData.value.family.name, |
| 435 | - fontSize: 36, | 435 | + fontSize: 29, // 按比例调整 (36 * 0.8 = 29) |
| 436 | color: '#ffffff', | 436 | color: '#ffffff', |
| 437 | fontWeight: 'bold', | 437 | fontWeight: 'bold', |
| 438 | textAlign: 'left', | 438 | textAlign: 'left', |
| ... | @@ -444,10 +444,10 @@ const posterConfig = computed(() => { | ... | @@ -444,10 +444,10 @@ const posterConfig = computed(() => { |
| 444 | }, | 444 | }, |
| 445 | // 家庭描述 | 445 | // 家庭描述 |
| 446 | // { | 446 | // { |
| 447 | - // x: 40, | 447 | + // x: 32, // 按比例调整 (40 * 0.8 = 32) |
| 448 | - // y: 250, | 448 | + // y: 200, // 按比例调整 (250 * 0.8 = 200) |
| 449 | // text: currentMockData.value.family.description, | 449 | // text: currentMockData.value.family.description, |
| 450 | - // fontSize: 28, | 450 | + // fontSize: 22, // 按比例调整 (28 * 0.8 = 22) |
| 451 | // color: '#ffffff', | 451 | // color: '#ffffff', |
| 452 | // textAlign: 'left', | 452 | // textAlign: 'left', |
| 453 | // shadowColor: 'rgba(0, 0, 0, 0.6)', | 453 | // shadowColor: 'rgba(0, 0, 0, 0.6)', |
| ... | @@ -458,27 +458,27 @@ const posterConfig = computed(() => { | ... | @@ -458,27 +458,27 @@ const posterConfig = computed(() => { |
| 458 | // }, | 458 | // }, |
| 459 | // 小程序码描述 | 459 | // 小程序码描述 |
| 460 | { | 460 | { |
| 461 | - x: 260, | 461 | + x: 208, // 按比例调整 (260 * 0.8 = 208) |
| 462 | - y: 1125, | 462 | + y: 900, // 按比例调整 (1125 * 0.8 = 900) |
| 463 | text: currentMockData.value.qrcodeDesc, | 463 | text: currentMockData.value.qrcodeDesc, |
| 464 | - fontSize: 30, | 464 | + fontSize: 24, // 按比例调整 (30 * 0.8 = 24) |
| 465 | color: '#333333', | 465 | color: '#333333', |
| 466 | - lineHeight: 40, | 466 | + lineHeight: 32, // 按比例调整 (40 * 0.8 = 32) |
| 467 | lineNum: 2, | 467 | lineNum: 2, |
| 468 | - width: 440, | 468 | + width: 352, // 按比例调整 (440 * 0.8 = 352) |
| 469 | textAlign: 'left', | 469 | textAlign: 'left', |
| 470 | zIndex: 1 | 470 | zIndex: 1 |
| 471 | }, | 471 | }, |
| 472 | // 关卡描述 | 472 | // 关卡描述 |
| 473 | { | 473 | { |
| 474 | - x: 260, | 474 | + x: 208, // 按比例调整 (260 * 0.8 = 208) |
| 475 | - y: 1180, | 475 | + y: 944, // 按比例调整 (1180 * 0.8 = 944) |
| 476 | text: '打卡点: ' + currentMockData.value.level.name, | 476 | text: '打卡点: ' + currentMockData.value.level.name, |
| 477 | - fontSize: 32, | 477 | + fontSize: 26, // 按比例调整 (32 * 0.8 = 26) |
| 478 | color: '#333333', | 478 | color: '#333333', |
| 479 | - lineHeight: 50, | 479 | + lineHeight: 40, // 按比例调整 (50 * 0.8 = 40) |
| 480 | lineNum: 2, | 480 | lineNum: 2, |
| 481 | - width: 440, | 481 | + width: 352, // 按比例调整 (440 * 0.8 = 352) |
| 482 | textAlign: 'left', | 482 | textAlign: 'left', |
| 483 | zIndex: 1 | 483 | zIndex: 1 |
| 484 | }, | 484 | }, |
| ... | @@ -487,20 +487,20 @@ const posterConfig = computed(() => { | ... | @@ -487,20 +487,20 @@ const posterConfig = computed(() => { |
| 487 | // 下半部分白色背景 | 487 | // 下半部分白色背景 |
| 488 | { | 488 | { |
| 489 | x: 0, | 489 | x: 0, |
| 490 | - y: 1050, | 490 | + y: 840, // 按比例调整 (1050 * 0.8 = 840) |
| 491 | - width: 750, | 491 | + width: 600, // 按比例调整 (750 * 0.8 = 600) |
| 492 | - height: 534, | 492 | + height: 427, // 按比例调整 (534 * 0.8 = 427) |
| 493 | backgroundColor: '#ffffff', | 493 | backgroundColor: '#ffffff', |
| 494 | zIndex: 0 | 494 | zIndex: 0 |
| 495 | }, | 495 | }, |
| 496 | // 用户信息背景遮罩 | 496 | // 用户信息背景遮罩 |
| 497 | // { | 497 | // { |
| 498 | - // x: 30, | 498 | + // x: 24, // 按比例调整 (30 * 0.8 = 24) |
| 499 | - // y: 180, | 499 | + // y: 144, // 按比例调整 (180 * 0.8 = 144) |
| 500 | - // width: 450, | 500 | + // width: 360, // 按比例调整 (450 * 0.8 = 360) |
| 501 | - // height: 140, | 501 | + // height: 112, // 按比例调整 (140 * 0.8 = 112) |
| 502 | // backgroundColor: 'rgba(0,0,0,0.3)', | 502 | // backgroundColor: 'rgba(0,0,0,0.3)', |
| 503 | - // borderRadius: 10, | 503 | + // borderRadius: 8, // 按比例调整 (10 * 0.8 = 8) |
| 504 | // zIndex: 1 | 504 | // zIndex: 1 |
| 505 | // } | 505 | // } |
| 506 | ] | 506 | ] | ... | ... |
-
Please register or login to post a comment