refactor(canvas): 优化画布尺寸计算逻辑以保持宽高比

This commit is contained in:
2026-04-21 09:14:32 +08:00
parent 84d51d30c8
commit 50379cc4b1

View File

@@ -2065,39 +2065,54 @@
return /MicroMessenger/i.test(navigator.userAgent);
}
// 生成画布(高清无损,根据设备像素比自适应分辨率)
// 生成画布(高清无损,保持与显示容器相同的宽高比)
async function generateCanvas() {
const canvas = exportCanvas;
const ctx = canvas.getContext('2d');
const container = imageContainer;
// 根据设备像素比决定输出分辨率,移动端至少 2x
// 微信等浏览器 canvas 最大尺寸通常为 4096,所以上限设为 2160×3840
const dpr = window.devicePixelRatio || 1;
const minScale = Math.max(dpr, 2); // 至少 2x
// 获取显示容器的实际尺寸和宽高比
const displayWidth = container.clientWidth;
const displayHeight = container.clientHeight;
const displayRatio = displayWidth / displayHeight;
// 根据设备像素比决定输出分辨率,移动端至少 2x
const dpr = window.devicePixelRatio || 1;
const minScale = Math.max(dpr, 2); // 至少 2x
// 先计算目标尺寸
let TARGET_WIDTH = Math.round(displayWidth * minScale);
let TARGET_HEIGHT = Math.round(displayHeight * minScale);
// 微信特殊处理:微信内置浏览器 canvas 限制更严格
// 实测微信中 4096 可能不稳定,使用 2048 更安全
const MAX_CANVAS_SIZE = isWechat() ? 2048 : 4096;
if (TARGET_HEIGHT > MAX_CANVAS_SIZE) {
const ratio = MAX_CANVAS_SIZE / TARGET_HEIGHT;
TARGET_WIDTH = Math.round(TARGET_WIDTH * ratio);
TARGET_HEIGHT = MAX_CANVAS_SIZE;
}
if (TARGET_WIDTH > MAX_CANVAS_SIZE) {
const ratio = MAX_CANVAS_SIZE / TARGET_WIDTH;
TARGET_HEIGHT = Math.round(TARGET_HEIGHT * ratio);
TARGET_WIDTH = MAX_CANVAS_SIZE;
// 如果超出限制,按宽高比等比例缩放
if (TARGET_HEIGHT > MAX_CANVAS_SIZE || TARGET_WIDTH > MAX_CANVAS_SIZE) {
const maxDimension = Math.max(TARGET_WIDTH, TARGET_HEIGHT);
const scaleFactor = MAX_CANVAS_SIZE / maxDimension;
TARGET_WIDTH = Math.round(TARGET_WIDTH * scaleFactor);
TARGET_HEIGHT = Math.round(TARGET_HEIGHT * scaleFactor);
}
// 确保最小分辨率
TARGET_WIDTH = Math.max(TARGET_WIDTH, 1080);
TARGET_HEIGHT = Math.max(TARGET_HEIGHT, 1920);
// 确保最小分辨率,同时保持宽高比
const minWidth = 1080;
const minHeight = 1920;
if (TARGET_WIDTH < minWidth || TARGET_HEIGHT < minHeight) {
const widthScale = minWidth / TARGET_WIDTH;
const heightScale = minHeight / TARGET_HEIGHT;
const scaleFactor = Math.max(widthScale, heightScale);
TARGET_WIDTH = Math.round(TARGET_WIDTH * scaleFactor);
TARGET_HEIGHT = Math.round(TARGET_HEIGHT * scaleFactor);
// 再次检查是否超出限制
if (TARGET_HEIGHT > MAX_CANVAS_SIZE || TARGET_WIDTH > MAX_CANVAS_SIZE) {
const maxDimension = Math.max(TARGET_WIDTH, TARGET_HEIGHT);
const limitScale = MAX_CANVAS_SIZE / maxDimension;
TARGET_WIDTH = Math.round(TARGET_WIDTH * limitScale);
TARGET_HEIGHT = Math.round(TARGET_HEIGHT * limitScale);
}
}
console.log('目标画布尺寸:', TARGET_WIDTH, 'x', TARGET_HEIGHT, 'dpr:', dpr, '微信:', isWechat());
console.log('显示容器尺寸:', displayWidth, 'x', displayHeight);