修复客户端资源画布图片预览

限制美术资源总览初次适配倍率,避免位图插值放大
扩大美术资源聚焦态原图预览区域
补充布局模型测试与技术方案验收口径
This commit is contained in:
2026-08-26 19:05:26 +08:00
parent d585ad93d5
commit c1f32d230f
5 changed files with 57 additions and 2 deletions
+26
View File
@@ -5113,6 +5113,11 @@ iframe.preview-frame {
transform: translate(-50%, -50%);
}
.game-resource-focus--art {
width: min(920px, calc(100% - 48px));
max-height: calc(100% - 48px);
}
.game-resource-image-preview {
display: grid;
min-height: 160px;
@@ -5124,6 +5129,12 @@ iframe.preview-frame {
place-items: center;
}
.game-resource-focus--art .game-resource-image-preview {
min-height: clamp(320px, 58vh, 720px);
max-height: none;
padding: 18px;
}
.game-resource-image-preview img {
display: block;
width: auto;
@@ -5131,6 +5142,21 @@ iframe.preview-frame {
height: auto;
max-height: 252px;
object-fit: contain;
outline: 1px solid rgb(0 0 0 / 10%);
outline-offset: -1px;
}
.game-resource-focus--art .game-resource-image-preview img,
.game-resource-focus--art .game-resource-image-preview video {
max-width: 100%;
max-height: min(62vh, 680px);
}
.game-resource-focus--art .game-resource-image-preview video {
display: block;
width: auto;
height: auto;
object-fit: contain;
}
.game-resource-focus-titlebar {
@@ -82,6 +82,7 @@ import {
normalizeInfiniteResourceCanvasViewport,
RESOURCE_CANVAS_DRAG_THRESHOLD,
RESOURCE_CANVAS_FIT_PADDING,
RESOURCE_CANVAS_INITIAL_FIT_MAX_SCALE,
RESOURCE_CANVAS_SECTION_MIN_HEIGHT,
RESOURCE_CANVAS_SECTION_MIN_WIDTH,
RESOURCE_CANVAS_SECTION_ORDER,
@@ -2244,6 +2245,10 @@ export default function ProjectDevelopmentView({
bounds: resourceCanvasFitBounds,
canvasSize: { width: measuredWidth, height: measuredHeight },
padding: RESOURCE_CANVAS_FIT_PADDING,
maxScale:
activePageCategory === 'art'
? RESOURCE_CANVAS_INITIAL_FIT_MAX_SCALE
: undefined,
}),
);
return;
@@ -2848,6 +2853,10 @@ export default function ProjectDevelopmentView({
bounds: resourceCanvasFitBounds,
canvasSize,
padding: RESOURCE_CANVAS_FIT_PADDING,
maxScale:
activePageCategory === 'art'
? RESOURCE_CANVAS_INITIAL_FIT_MAX_SCALE
: undefined,
}),
);
}, [activePageCategory, resourceCanvasFitBounds, setResourceCanvasViewport]);
@@ -30,6 +30,11 @@ export const RESOURCE_CANVAS_TYPE_COLUMNS = 3;
export const RESOURCE_CANVAS_SECTION_MIN_WIDTH = 620;
export const RESOURCE_CANVAS_SECTION_MIN_HEIGHT = 108;
export const RESOURCE_CANVAS_CLUSTER_GAP = 48;
/**
* 总览是导航面,不是图片查看器。初次适配不要把卡片位图放大到明显插值
* 失真的范围;用户主动缩放仍可使用 MAX_SCALE。
*/
export const RESOURCE_CANVAS_INITIAL_FIT_MAX_SCALE = 1.5;
/**
* Initial fit inset only. The resource canvas background itself is infinite;
* this value must not be used to clamp a later pan or zoom.
@@ -1341,10 +1346,12 @@ export function fitResourceCanvasViewportToContent({
bounds,
canvasSize,
padding = RESOURCE_CANVAS_FIT_PADDING,
maxScale = MAX_SCALE,
}: {
bounds: { x: number; y: number; width: number; height: number };
canvasSize: { width: number; height: number };
padding?: number;
maxScale?: number;
}): CanvasViewport {
const normalizedPadding = Math.max(0, padding);
const boundsWidth = Math.max(1, bounds.width);
@@ -1354,10 +1361,13 @@ export function fitResourceCanvasViewportToContent({
1,
canvasSize.height - normalizedPadding * 2,
);
const normalizedMaxScale = Number.isFinite(maxScale)
? clampResourceCanvasNumber(maxScale, MIN_SCALE, MAX_SCALE)
: MAX_SCALE;
const scale = clampResourceCanvasNumber(
Math.min(availableWidth / boundsWidth, availableHeight / boundsHeight),
MIN_SCALE,
MAX_SCALE,
normalizedMaxScale,
);
return {
x:
@@ -831,6 +831,16 @@ describe('resource canvas variable card geometry', () => {
expect(viewport.x + bounds.x * viewport.scale).toBeCloseTo(16, 8);
});
it('caps the initial fit without limiting explicit canvas zoom', () => {
const viewport = fitResourceCanvasViewportToContent({
bounds: { x: 0, y: 0, width: 180, height: 128 },
canvasSize: { width: 800, height: 600 },
maxScale: 1.5,
});
expect(viewport.scale).toBe(1.5);
});
it('accepts card sizes directly on resource items for hook integration', () => {
const wide = {
...resource('wide', 'art', 0),