diff --git a/js/script.js b/js/script.js index 9de4ac4..1ce3c82 100644 --- a/js/script.js +++ b/js/script.js @@ -2122,20 +2122,20 @@ ctx.fillRect(0, 0, TARGET_WIDTH, TARGET_HEIGHT); // 计算从显示尺寸到目标分辨率的缩放比例 - const scaleX = TARGET_WIDTH / displayWidth; - const scaleY = TARGET_HEIGHT / displayHeight; - console.log('缩放比例:', scaleX, 'x', scaleY); + // 使用统一的缩放比例,保持宽高比,确保所见即所得 + const scale = TARGET_WIDTH / displayWidth; + console.log('统一缩放比例:', scale); if (currentImage) { console.log('背景图原始尺寸:', currentImage.naturalWidth, 'x', currentImage.naturalHeight); - drawBgImageOnCanvasHD(ctx, currentImage, TARGET_WIDTH, TARGET_HEIGHT, scaleX, scaleY); + drawBgImageOnCanvasHD(ctx, currentImage, TARGET_WIDTH, TARGET_HEIGHT, scale); } - await drawOverlayImagesHD(ctx, scaleX, scaleY); + await drawOverlayImagesHD(ctx, scale); const textInputs = container.querySelectorAll('.preview-input-layer .text-input'); textInputs.forEach(textInput => { - drawTextOnCanvasHD(ctx, textInput, scaleX, scaleY); + drawTextOnCanvasHD(ctx, textInput, scale); }); return canvas; @@ -2174,8 +2174,8 @@ } // 绘制背景图(高清版本) - function drawBgImageOnCanvasHD(ctx, img, canvasWidth, canvasHeight, scaleX, scaleY) { - // 使用原始图片尺寸进行高清渲染 + function drawBgImageOnCanvasHD(ctx, img, canvasWidth, canvasHeight, scale) { + // 使用与编辑时完全相同的计算逻辑,只是按比例缩放 const containerWidth = canvasWidth; const containerHeight = canvasHeight; const imgRatio = img.naturalWidth / img.naturalHeight; @@ -2191,46 +2191,17 @@ imgHeight = imgWidth / imgRatio; } - // 应用缩放 + // 应用缩放(与编辑时的 bgImageScale 一致) const scaledWidth = imgWidth * bgImageScale; const scaledHeight = imgHeight * bgImageScale; - // 计算位置(考虑高清缩放) + // 计算位置(与 updateBgImage 函数完全一致,只是按比例缩放偏移量) const baseLeft = (containerWidth - scaledWidth) / 2; - const drawX = baseLeft + (imageOffsetX * scaleX); + const drawX = baseLeft + (imageOffsetX * scale); const drawY = (containerHeight - scaledHeight) / 2; ctx.globalAlpha = bgImageOpacity; - - // 微信中:如果原始图片比目标区域大,使用原始尺寸绘制以获得最佳质量 - // 否则按计算尺寸绘制 - if (isWechat() && img.naturalWidth > scaledWidth && img.naturalHeight > scaledHeight) { - // 计算裁剪区域,从原始图片中心裁剪 - const srcRatio = scaledWidth / scaledHeight; - let srcWidth = img.naturalWidth; - let srcHeight = img.naturalHeight; - let srcX = 0; - let srcY = 0; - - // 如果原始图片比例与目标不同,计算居中裁剪 - const naturalRatio = img.naturalWidth / img.naturalHeight; - if (naturalRatio > imgRatio) { - // 原始图片更宽,裁剪左右 - srcWidth = img.naturalHeight * imgRatio; - srcX = (img.naturalWidth - srcWidth) / 2; - } else if (naturalRatio < imgRatio) { - // 原始图片更高,裁剪上下 - srcHeight = img.naturalWidth / imgRatio; - srcY = (img.naturalHeight - srcHeight) / 2; - } - - // 使用 drawImage 的 9 参数版本进行高质量缩放 - ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight, drawX, drawY, scaledWidth, scaledHeight); - } else { - // 使用原始图片绘制,获得最佳清晰度 - ctx.drawImage(img, drawX, drawY, scaledWidth, scaledHeight); - } - + ctx.drawImage(img, drawX, drawY, scaledWidth, scaledHeight); ctx.globalAlpha = 1; } @@ -2281,7 +2252,7 @@ } // 绘制层叠图(高清版本) - function drawOverlayImagesHD(ctx, scaleX, scaleY) { + function drawOverlayImagesHD(ctx, scale) { return new Promise((resolve) => { const overlayImages = overlayLayer.querySelectorAll('.overlay-image'); if (overlayImages.length === 0) { @@ -2306,11 +2277,11 @@ return; } - // 使用 offsetLeft/offsetTop 获取相对于 overlayLayer 的位置,并应用高清缩放 - const left = overlayEl.offsetLeft * scaleX; - const top = overlayEl.offsetTop * scaleY; - const width = overlayEl.offsetWidth * scaleX; - const height = overlayEl.offsetHeight * scaleY; + // 使用 offsetLeft/offsetTop 获取相对于 overlayLayer 的位置,并应用统一缩放 + const left = overlayEl.offsetLeft * scale; + const top = overlayEl.offsetTop * scale; + const width = overlayEl.offsetWidth * scale; + const height = overlayEl.offsetHeight * scale; ctx.globalAlpha = overlayEl.style.opacity || 1; @@ -2365,7 +2336,7 @@ } // 在画布上绘制文字(高清版本) - function drawTextOnCanvasHD(ctx, inputElement, scaleX, scaleY) { + function drawTextOnCanvasHD(ctx, inputElement, scale) { const deleteBtn = inputElement.querySelector('.text-delete-btn'); let text = inputElement.textContent; if (deleteBtn) { @@ -2373,17 +2344,17 @@ } if (!text.trim()) return; - // 使用 offsetLeft/offsetTop 获取相对于 preview-input-layer 的位置,并应用高清缩放 - const inputLeft = inputElement.offsetLeft * scaleX; - const inputTop = inputElement.offsetTop * scaleY; + // 使用 offsetLeft/offsetTop 获取相对于 preview-input-layer 的位置,并应用统一缩放 + const inputLeft = inputElement.offsetLeft * scale; + const inputTop = inputElement.offsetTop * scale; const style = window.getComputedStyle(inputElement); - const fontSize = parseInt(style.fontSize) * scaleX; // 字体大小也按比例缩放 + const fontSize = parseInt(style.fontSize) * scale; // 字体大小也按比例缩放 const lineHeight = parseFloat(style.lineHeight); // 微信中:使用更粗的字体权重以获得更好的可读性 let fontWeight = style.fontWeight; - if (isWechat() && fontWeight === '400' || fontWeight === 'normal') { + if (isWechat() && (fontWeight === '400' || fontWeight === 'normal')) { fontWeight = '500'; // 稍微加粗一点 } @@ -2398,7 +2369,7 @@ } // 计算文本垂直偏移量,使其与 DOM 渲染一致 - const actualLineHeight = (lineHeight || fontSize * 1.4) * scaleY; + const actualLineHeight = (lineHeight || fontSize * 1.4); const textOffsetY = (actualLineHeight - fontSize) / 2 + fontSize * 0.85; ctx.fillText(text, inputLeft, inputTop + textOffsetY);