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);
|
return /MicroMessenger/i.test(navigator.userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成画布(高清无损,根据设备像素比自适应分辨率)
|
// 生成画布(高清无损,保持与显示容器相同的宽高比)
|
||||||
async function generateCanvas() {
|
async function generateCanvas() {
|
||||||
const canvas = exportCanvas;
|
const canvas = exportCanvas;
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
const container = imageContainer;
|
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 displayWidth = container.clientWidth;
|
||||||
const displayHeight = container.clientHeight;
|
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_WIDTH = Math.round(displayWidth * minScale);
|
||||||
let TARGET_HEIGHT = Math.round(displayHeight * minScale);
|
let TARGET_HEIGHT = Math.round(displayHeight * minScale);
|
||||||
|
|
||||||
// 微信特殊处理:微信内置浏览器 canvas 限制更严格
|
// 微信特殊处理:微信内置浏览器 canvas 限制更严格
|
||||||
// 实测微信中 4096 可能不稳定,使用 2048 更安全
|
|
||||||
const MAX_CANVAS_SIZE = isWechat() ? 2048 : 4096;
|
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);
|
if (TARGET_HEIGHT > MAX_CANVAS_SIZE || TARGET_WIDTH > MAX_CANVAS_SIZE) {
|
||||||
TARGET_HEIGHT = MAX_CANVAS_SIZE;
|
const maxDimension = Math.max(TARGET_WIDTH, TARGET_HEIGHT);
|
||||||
}
|
const scaleFactor = MAX_CANVAS_SIZE / maxDimension;
|
||||||
if (TARGET_WIDTH > MAX_CANVAS_SIZE) {
|
TARGET_WIDTH = Math.round(TARGET_WIDTH * scaleFactor);
|
||||||
const ratio = MAX_CANVAS_SIZE / TARGET_WIDTH;
|
TARGET_HEIGHT = Math.round(TARGET_HEIGHT * scaleFactor);
|
||||||
TARGET_HEIGHT = Math.round(TARGET_HEIGHT * ratio);
|
|
||||||
TARGET_WIDTH = MAX_CANVAS_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保最小分辨率
|
// 确保最小分辨率,同时保持宽高比
|
||||||
TARGET_WIDTH = Math.max(TARGET_WIDTH, 1080);
|
const minWidth = 1080;
|
||||||
TARGET_HEIGHT = Math.max(TARGET_HEIGHT, 1920);
|
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('目标画布尺寸:', TARGET_WIDTH, 'x', TARGET_HEIGHT, 'dpr:', dpr, '微信:', isWechat());
|
||||||
console.log('显示容器尺寸:', displayWidth, 'x', displayHeight);
|
console.log('显示容器尺寸:', displayWidth, 'x', displayHeight);
|
||||||
|
|||||||
Reference in New Issue
Block a user