refactor(canvas): 优化画布尺寸计算逻辑以保持宽高比
This commit is contained in:
51
js/script.js
51
js/script.js
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user