Files
Genarrative/src/components/common/platformImagePreviewModel.ts
T
kdletters a51e63415f 收口生成队列与图片预览
将外部生成队列概览移到我的页签展示

移除生成页和进度页中的队列概览区域

新增全屏黑底图片预览器并支持缩放和边界拖拽

补充队列概览和图片预览的聚焦测试

同步更新玩法链路、运维、UI Kit 和团队共享记忆文档
2026-06-13 22:25:22 +08:00

97 lines
2.6 KiB
TypeScript

export type PlatformImagePreviewSize = {
width: number;
height: number;
};
export type PlatformImagePreviewTransform = {
scale: number;
offsetX: number;
offsetY: number;
};
export const MIN_PLATFORM_IMAGE_PREVIEW_SCALE = 1;
export const MAX_PLATFORM_IMAGE_PREVIEW_SCALE = 4;
export const PLATFORM_IMAGE_PREVIEW_SCALE_STEP = 0.5;
export const DEFAULT_PLATFORM_IMAGE_PREVIEW_TRANSFORM: PlatformImagePreviewTransform =
{
scale: MIN_PLATFORM_IMAGE_PREVIEW_SCALE,
offsetX: 0,
offsetY: 0,
};
function clampNumber(value: number, min: number, max: number) {
if (!Number.isFinite(value)) {
return min;
}
return Math.max(min, Math.min(max, value));
}
function normalizePreviewSize(size: PlatformImagePreviewSize | null) {
if (!size || size.width <= 0 || size.height <= 0) {
return { width: 1, height: 1 };
}
return size;
}
export function resolvePlatformImagePreviewContainedSize(
viewportSize: PlatformImagePreviewSize,
naturalSize: PlatformImagePreviewSize | null,
) {
const viewport = normalizePreviewSize(viewportSize);
const natural = normalizePreviewSize(naturalSize);
const imageRatio = natural.width / natural.height;
const viewportRatio = viewport.width / viewport.height;
if (imageRatio > viewportRatio) {
return {
width: viewport.width,
height: viewport.width / imageRatio,
};
}
return {
width: viewport.height * imageRatio,
height: viewport.height,
};
}
export function samePlatformImagePreviewTransform(
left: PlatformImagePreviewTransform,
right: PlatformImagePreviewTransform,
) {
return (
left.scale === right.scale &&
left.offsetX === right.offsetX &&
left.offsetY === right.offsetY
);
}
export function clampPlatformImagePreviewTransform(
transform: PlatformImagePreviewTransform,
viewportSize: PlatformImagePreviewSize,
naturalSize: PlatformImagePreviewSize | null,
): PlatformImagePreviewTransform {
const viewport = normalizePreviewSize(viewportSize);
const containedSize = resolvePlatformImagePreviewContainedSize(
viewport,
naturalSize,
);
const scale = clampNumber(
transform.scale,
MIN_PLATFORM_IMAGE_PREVIEW_SCALE,
MAX_PLATFORM_IMAGE_PREVIEW_SCALE,
);
const scaledWidth = containedSize.width * scale;
const scaledHeight = containedSize.height * scale;
const panLimitX = Math.max(0, (scaledWidth - viewport.width) / 2);
const panLimitY = Math.max(0, (scaledHeight - viewport.height) / 2);
return {
scale,
offsetX: clampNumber(transform.offsetX, -panLimitX, panLimitX),
offsetY: clampNumber(transform.offsetY, -panLimitY, panLimitY),
};
}