完善全类型资源非破坏性编辑
禁用新增资源并为所有现役资源提供按类型编辑入口。 图片、视频、音频、文本、任务产物和项目版本派生新资源且保留原资源。 完善 External operation 私有账本、幂等恢复、旧指纹迁移与安全校验。 修复画布生成期间交互冻结、滚轮平移缩放与 Shift 选择行为。 同步资源编辑合同、决策记录与排障经验。
This commit is contained in:
@@ -243,6 +243,40 @@ export function zoomViewportFromWheel({
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveViewportFromWheel({
|
||||
viewport,
|
||||
deltaX,
|
||||
deltaY,
|
||||
shiftKey,
|
||||
ctrlKey,
|
||||
metaKey,
|
||||
screenPoint,
|
||||
}: {
|
||||
viewport: CanvasViewport;
|
||||
deltaX: number;
|
||||
deltaY: number;
|
||||
shiftKey: boolean;
|
||||
ctrlKey: boolean;
|
||||
metaKey: boolean;
|
||||
screenPoint: CanvasPoint;
|
||||
}): { mode: 'pan' | 'zoom'; viewport: CanvasViewport } {
|
||||
if (ctrlKey || metaKey) {
|
||||
return {
|
||||
mode: 'zoom',
|
||||
viewport: zoomViewportFromWheel({ viewport, deltaY, screenPoint }),
|
||||
};
|
||||
}
|
||||
const useShiftWheelHorizontalFallback = shiftKey && deltaX === 0;
|
||||
return {
|
||||
mode: 'pan',
|
||||
viewport: panViewportFromWheel({
|
||||
viewport,
|
||||
deltaX: useShiftWheelHorizontalFallback ? deltaY : deltaX,
|
||||
deltaY: useShiftWheelHorizontalFallback ? 0 : deltaY,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export function moveViewportFromPan(
|
||||
dragState: Extract<DragState, { kind: 'pan' }>,
|
||||
pointer: CanvasPoint,
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
panViewportFromWheel,
|
||||
resizeCanvasLayerBounds,
|
||||
resolvePointerSelection,
|
||||
resolveViewportFromWheel,
|
||||
scaleViewportFromScreenPoint,
|
||||
selectLayersInsideMarquee,
|
||||
transformCanvasLayers,
|
||||
@@ -62,6 +63,43 @@ describe('shared image canvas core', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('shares pan, shift-pan and modifier-zoom wheel semantics', () => {
|
||||
const viewport = { x: 20, y: 30, scale: 1 };
|
||||
expect(
|
||||
resolveViewportFromWheel({
|
||||
viewport,
|
||||
deltaX: 4,
|
||||
deltaY: 10,
|
||||
shiftKey: false,
|
||||
ctrlKey: false,
|
||||
metaKey: false,
|
||||
screenPoint: { x: 100, y: 100 },
|
||||
}),
|
||||
).toEqual({ mode: 'pan', viewport: { x: 16, y: 20, scale: 1 } });
|
||||
expect(
|
||||
resolveViewportFromWheel({
|
||||
viewport,
|
||||
deltaX: 0,
|
||||
deltaY: 10,
|
||||
shiftKey: true,
|
||||
ctrlKey: false,
|
||||
metaKey: false,
|
||||
screenPoint: { x: 100, y: 100 },
|
||||
}),
|
||||
).toEqual({ mode: 'pan', viewport: { x: 10, y: 30, scale: 1 } });
|
||||
expect(
|
||||
resolveViewportFromWheel({
|
||||
viewport,
|
||||
deltaX: 0,
|
||||
deltaY: -10,
|
||||
shiftKey: false,
|
||||
ctrlKey: true,
|
||||
metaKey: false,
|
||||
screenPoint: { x: 100, y: 100 },
|
||||
}).mode,
|
||||
).toBe('zoom');
|
||||
});
|
||||
|
||||
it('supports additive selection, marquee and multi-layer movement', () => {
|
||||
expect(
|
||||
resolvePointerSelection({
|
||||
|
||||
@@ -12,9 +12,8 @@ import {
|
||||
getWorldPointFromClient,
|
||||
moveViewportFromMinimapDrag as resolveViewportFromMinimapDrag,
|
||||
moveViewportFromMinimapPointer as resolveViewportFromMinimapPointer,
|
||||
panViewportFromWheel,
|
||||
resolveViewportFromWheel,
|
||||
scaleViewportFromScreenPoint,
|
||||
zoomViewportFromWheel,
|
||||
} from '@genarrative/image-canvas-core';
|
||||
import {
|
||||
type Dispatch,
|
||||
@@ -369,32 +368,22 @@ export function useImageCanvasViewportControls({
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (!event.ctrlKey && !event.metaKey) {
|
||||
const useShiftWheelHorizontalFallback =
|
||||
event.shiftKey && event.deltaX === 0;
|
||||
setViewport((currentViewport) =>
|
||||
panViewportFromWheel({
|
||||
viewport: currentViewport,
|
||||
deltaX: useShiftWheelHorizontalFallback
|
||||
? event.deltaY
|
||||
: event.deltaX,
|
||||
deltaY: useShiftWheelHorizontalFallback ? 0 : event.deltaY,
|
||||
}),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const rect = viewportElement.getBoundingClientRect();
|
||||
const screenPoint = {
|
||||
x: event.clientX - rect.left,
|
||||
y: event.clientY - rect.top,
|
||||
};
|
||||
setViewport((currentViewport) =>
|
||||
zoomViewportFromWheel({
|
||||
viewport: currentViewport,
|
||||
deltaY: event.deltaY,
|
||||
screenPoint,
|
||||
}),
|
||||
setViewport(
|
||||
(currentViewport) =>
|
||||
resolveViewportFromWheel({
|
||||
viewport: currentViewport,
|
||||
deltaX: event.deltaX,
|
||||
deltaY: event.deltaY,
|
||||
shiftKey: event.shiftKey,
|
||||
ctrlKey: event.ctrlKey,
|
||||
metaKey: event.metaKey,
|
||||
screenPoint,
|
||||
}).viewport,
|
||||
);
|
||||
},
|
||||
[canvasViewportRef, setViewport],
|
||||
|
||||
Reference in New Issue
Block a user