hookehuyr

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

- 动态调整canvas质量,大尺寸使用更低质量
- 使用jpg格式替代png减小文件体积
- 调整像素密度平衡显示质量和文件大小
- 按比例缩小海报尺寸和相关元素
...@@ -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 ]
......