hookehuyr

feat(PosterBuilder): 添加海报图片cover/contain适配模式支持

补充Image类型的mode属性定义,重构图片绘制的尺寸计算逻辑以适配两种缩放模式;同时更新签到详情页的活动logo配置,使用contain模式并调整其位置与尺寸参数
...@@ -48,6 +48,7 @@ export interface Image { ...@@ -48,6 +48,7 @@ export interface Image {
48 url: string; 48 url: string;
49 width: number; 49 width: number;
50 height: number; 50 height: number;
51 + mode?: 'cover' | 'contain';
51 borderRadius?: number; 52 borderRadius?: number;
52 borderRadiusGroup?: number[]; 53 borderRadiusGroup?: number[];
53 borderWidth?: number; 54 borderWidth?: number;
......
...@@ -251,7 +251,7 @@ export const batchGetImageInfo = (images) => { ...@@ -251,7 +251,7 @@ export const batchGetImageInfo = (images) => {
251 */ 251 */
252 export const getImageInfo = (item, index) => 252 export const getImageInfo = (item, index) =>
253 new Promise((resolve, reject) => { 253 new Promise((resolve, reject) => {
254 - const { x, y, width, height, url, zIndex } = item; 254 + const { x, y, width, height, url, zIndex, mode = 'cover' } = item;
255 255
256 // 预先计算一些固定值,避免重复计算 256 // 预先计算一些固定值,避免重复计算
257 const borderRadius = item.borderRadius || 0; 257 const borderRadius = item.borderRadius || 0;
...@@ -265,21 +265,36 @@ export const getImageInfo = (item, index) => ...@@ -265,21 +265,36 @@ export const getImageInfo = (item, index) =>
265 Taro.getImageInfo({ src: imgPath }) 265 Taro.getImageInfo({ src: imgPath })
266 .then((imgInfo) => { 266 .then((imgInfo) => {
267 // 获取图片信息 267 // 获取图片信息
268 - // 根据画布的宽高计算出图片绘制的大小,这里会保证图片绘制不变形, 即宽高比不变,截取再拉伸 268 + // 根据画布的宽高计算出图片绘制的大小
269 const imgWidth = toRpx(imgInfo.width); // 图片真实宽度 单位 px 269 const imgWidth = toRpx(imgInfo.width); // 图片真实宽度 单位 px
270 const imgHeight = toRpx(imgInfo.height); // 图片真实高度 单位 px 270 const imgHeight = toRpx(imgInfo.height); // 图片真实高度 单位 px
271 271
272 - // 优化计算逻辑,减少重复计算
273 const aspectRatio = imgWidth / imgHeight; 272 const aspectRatio = imgWidth / imgHeight;
274 const targetRatio = width / height; 273 const targetRatio = width / height;
275 274
276 - let sx, sy; // 截图的起点坐标 275 + let sx = 0;
277 - if (aspectRatio <= targetRatio) { 276 + let sy = 0;
278 - sx = 0; 277 + let sw = imgWidth;
278 + let sh = imgHeight;
279 + let drawX = x;
280 + let drawY = y;
281 + let drawW = width;
282 + let drawH = height;
283 +
284 + if (mode === 'contain') {
285 + if (aspectRatio > targetRatio) {
286 + drawH = width / aspectRatio;
287 + drawY = y + (height - drawH) / 2;
288 + } else {
289 + drawW = height * aspectRatio;
290 + drawX = x + (width - drawW) / 2;
291 + }
292 + } else if (aspectRatio <= targetRatio) {
279 sy = (imgHeight - (imgWidth / width) * height) / 2; 293 sy = (imgHeight - (imgWidth / width) * height) / 2;
294 + sh = imgHeight - sy * 2;
280 } else { 295 } else {
281 - sy = 0;
282 sx = (imgWidth - (imgHeight / height) * width) / 2; 296 sx = (imgWidth - (imgHeight / height) * width) / 2;
297 + sw = imgWidth - sx * 2;
283 } 298 }
284 299
285 // 给 canvas 画图准备参数,详见 ./draw.ts-drawImage 300 // 给 canvas 画图准备参数,详见 ./draw.ts-drawImage
...@@ -291,14 +306,15 @@ export const getImageInfo = (item, index) => ...@@ -291,14 +306,15 @@ export const getImageInfo = (item, index) =>
291 borderRadiusGroup, 306 borderRadiusGroup,
292 zIndex: itemZIndex, 307 zIndex: itemZIndex,
293 imgPath: imgPath, // 使用下载后的临时文件路径 308 imgPath: imgPath, // 使用下载后的临时文件路径
309 + mode,
294 sx, 310 sx,
295 sy, 311 sy,
296 - sw: imgWidth - sx * 2, 312 + sw,
297 - sh: imgHeight - sy * 2, 313 + sh,
298 - x, 314 + x: drawX,
299 - y, 315 + y: drawY,
300 - w: width, 316 + w: drawW,
301 - h: height 317 + h: drawH
302 }; 318 };
303 resolve(result); 319 resolve(result);
304 }) 320 })
......
...@@ -448,11 +448,12 @@ const posterConfig = computed(() => { ...@@ -448,11 +448,12 @@ const posterConfig = computed(() => {
448 }, 448 },
449 // 活动logo 449 // 活动logo
450 { 450 {
451 - x: 360, // 按比例调整 (450 * 0.8 = 360) 451 + x: 328,
452 - y: 32, // 按比例调整 (40 * 0.8 = 32) 452 + y: 24,
453 - width: 200, // 按比例调整 (250 * 0.8 = 200) 453 + width: 240,
454 - height: 64, // 按比例调整 (80 * 0.8 = 64) 454 + height: 88,
455 url: currentMockData.value.activity.logo, 455 url: currentMockData.value.activity.logo,
456 + mode: 'contain',
456 zIndex: 2, 457 zIndex: 2,
457 }, 458 },
458 // 关卡徽章 459 // 关卡徽章
......