mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): fix canvas scaling
This commit is contained in:
parent
06ac16a77d
commit
6efa953172
@ -1,6 +1,6 @@
|
|||||||
import { Box, chakra, Flex } from '@chakra-ui/react';
|
import { Box, chakra, Flex } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import {
|
import {
|
||||||
canvasSelector,
|
canvasSelector,
|
||||||
@ -9,7 +9,7 @@ import {
|
|||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import { KonvaEventObject } from 'konva/lib/Node';
|
import { KonvaEventObject } from 'konva/lib/Node';
|
||||||
import { Vector2d } from 'konva/lib/types';
|
import { Vector2d } from 'konva/lib/types';
|
||||||
import { memo, useCallback, useRef } from 'react';
|
import { memo, useCallback, useEffect, useRef } from 'react';
|
||||||
import { Layer, Stage } from 'react-konva';
|
import { Layer, Stage } from 'react-konva';
|
||||||
import useCanvasDragMove from '../hooks/useCanvasDragMove';
|
import useCanvasDragMove from '../hooks/useCanvasDragMove';
|
||||||
import useCanvasHotkeys from '../hooks/useCanvasHotkeys';
|
import useCanvasHotkeys from '../hooks/useCanvasHotkeys';
|
||||||
@ -18,6 +18,7 @@ import useCanvasMouseMove from '../hooks/useCanvasMouseMove';
|
|||||||
import useCanvasMouseOut from '../hooks/useCanvasMouseOut';
|
import useCanvasMouseOut from '../hooks/useCanvasMouseOut';
|
||||||
import useCanvasMouseUp from '../hooks/useCanvasMouseUp';
|
import useCanvasMouseUp from '../hooks/useCanvasMouseUp';
|
||||||
import useCanvasWheel from '../hooks/useCanvasZoom';
|
import useCanvasWheel from '../hooks/useCanvasZoom';
|
||||||
|
import { canvasResized } from '../store/canvasSlice';
|
||||||
import {
|
import {
|
||||||
setCanvasBaseLayer,
|
setCanvasBaseLayer,
|
||||||
setCanvasStage,
|
setCanvasStage,
|
||||||
@ -106,7 +107,8 @@ const IAICanvas = () => {
|
|||||||
shouldAntialias,
|
shouldAntialias,
|
||||||
} = useAppSelector(selector);
|
} = useAppSelector(selector);
|
||||||
useCanvasHotkeys();
|
useCanvasHotkeys();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const stageRef = useRef<Konva.Stage | null>(null);
|
const stageRef = useRef<Konva.Stage | null>(null);
|
||||||
const canvasBaseLayerRef = useRef<Konva.Layer | null>(null);
|
const canvasBaseLayerRef = useRef<Konva.Layer | null>(null);
|
||||||
|
|
||||||
@ -137,8 +139,30 @@ const IAICanvas = () => {
|
|||||||
const { handleDragStart, handleDragMove, handleDragEnd } =
|
const { handleDragStart, handleDragMove, handleDragEnd } =
|
||||||
useCanvasDragMove();
|
useCanvasDragMove();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!containerRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.contentBoxSize) {
|
||||||
|
const { width, height } = entry.contentRect;
|
||||||
|
dispatch(canvasResized({ width, height }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeObserver.observe(containerRef.current);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
resizeObserver.disconnect();
|
||||||
|
};
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
id="canvas-container"
|
||||||
|
ref={containerRef}
|
||||||
sx={{
|
sx={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@ -146,13 +170,18 @@ const IAICanvas = () => {
|
|||||||
borderRadius: 'base',
|
borderRadius: 'base',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ position: 'relative' }}>
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
// top: 0,
|
||||||
|
// insetInlineStart: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ChakraStage
|
<ChakraStage
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
ref={canvasStageRefCallback}
|
ref={canvasStageRefCallback}
|
||||||
sx={{
|
sx={{
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
// boxShadow: '0px 0px 0px 1px var(--border-color-light)',
|
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
cursor: stageCursor ? stageCursor : undefined,
|
cursor: stageCursor ? stageCursor : undefined,
|
||||||
canvas: {
|
canvas: {
|
||||||
@ -213,9 +242,9 @@ const IAICanvas = () => {
|
|||||||
/>
|
/>
|
||||||
</Layer>
|
</Layer>
|
||||||
</ChakraStage>
|
</ChakraStage>
|
||||||
<IAICanvasStatusText />
|
|
||||||
<IAICanvasStagingAreaToolbar />
|
|
||||||
</Box>
|
</Box>
|
||||||
|
<IAICanvasStatusText />
|
||||||
|
<IAICanvasStagingAreaToolbar />
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -623,6 +623,53 @@ export const canvasSlice = createSlice({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
canvasResized: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<{ width: number; height: number }>
|
||||||
|
) => {
|
||||||
|
const { width, height } = action.payload;
|
||||||
|
const newStageDimensions = {
|
||||||
|
width: Math.floor(width),
|
||||||
|
height: Math.floor(height),
|
||||||
|
};
|
||||||
|
|
||||||
|
state.stageDimensions = newStageDimensions;
|
||||||
|
|
||||||
|
if (!state.layerState.objects.find(isCanvasBaseImage)) {
|
||||||
|
const newScale = calculateScale(
|
||||||
|
newStageDimensions.width,
|
||||||
|
newStageDimensions.height,
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
STAGE_PADDING_PERCENTAGE
|
||||||
|
);
|
||||||
|
|
||||||
|
const newCoordinates = calculateCoordinates(
|
||||||
|
newStageDimensions.width,
|
||||||
|
newStageDimensions.height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
newScale
|
||||||
|
);
|
||||||
|
|
||||||
|
const newBoundingBoxDimensions = { width: 512, height: 512 };
|
||||||
|
|
||||||
|
state.stageScale = newScale;
|
||||||
|
|
||||||
|
state.stageCoordinates = newCoordinates;
|
||||||
|
state.boundingBoxCoordinates = { x: 0, y: 0 };
|
||||||
|
state.boundingBoxDimensions = newBoundingBoxDimensions;
|
||||||
|
|
||||||
|
if (state.boundingBoxScaleMethod === 'auto') {
|
||||||
|
const scaledDimensions = getScaledBoundingBoxDimensions(
|
||||||
|
newBoundingBoxDimensions
|
||||||
|
);
|
||||||
|
state.scaledBoundingBoxDimensions = scaledDimensions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
resetCanvasView: (
|
resetCanvasView: (
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<{
|
action: PayloadAction<{
|
||||||
@ -966,6 +1013,7 @@ export const {
|
|||||||
stagingAreaInitialized,
|
stagingAreaInitialized,
|
||||||
canvasSessionIdChanged,
|
canvasSessionIdChanged,
|
||||||
setShouldAntialias,
|
setShouldAntialias,
|
||||||
|
canvasResized,
|
||||||
} = canvasSlice.actions;
|
} = canvasSlice.actions;
|
||||||
|
|
||||||
export default canvasSlice.reducer;
|
export default canvasSlice.reducer;
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Flex } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAIDropOverlay from 'common/components/IAIDropOverlay';
|
import IAIDropOverlay from 'common/components/IAIDropOverlay';
|
||||||
import IAICanvas from 'features/canvas/components/IAICanvas';
|
import IAICanvas from 'features/canvas/components/IAICanvas';
|
||||||
import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer';
|
|
||||||
import IAICanvasToolbar from 'features/canvas/components/IAICanvasToolbar/IAICanvasToolbar';
|
import IAICanvasToolbar from 'features/canvas/components/IAICanvasToolbar/IAICanvasToolbar';
|
||||||
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
||||||
import { useDroppableTypesafe } from 'features/dnd/hooks/typesafeHooks';
|
import { useDroppableTypesafe } from 'features/dnd/hooks/typesafeHooks';
|
||||||
@ -54,49 +53,27 @@ const UnifiedCanvasContent = () => {
|
|||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Flex
|
||||||
|
layerStyle="first"
|
||||||
ref={setDroppableRef}
|
ref={setDroppableRef}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
sx={{
|
sx={{
|
||||||
layerStyle: 'first',
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 4,
|
||||||
|
p: 2,
|
||||||
|
borderRadius: 'base',
|
||||||
w: 'full',
|
w: 'full',
|
||||||
h: 'full',
|
h: 'full',
|
||||||
p: 4,
|
|
||||||
borderRadius: 'base',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex
|
<IAICanvasToolbar />
|
||||||
sx={{
|
<IAICanvas />
|
||||||
flexDirection: 'column',
|
{/* {doesCanvasNeedScaling ? <IAICanvasResizer /> : <IAICanvas />} */}
|
||||||
alignItems: 'center',
|
{isValidDrop(droppableData, active) && (
|
||||||
gap: 4,
|
<IAIDropOverlay isOver={isOver} label="Set Canvas Initial Image" />
|
||||||
w: 'full',
|
)}
|
||||||
h: 'full',
|
</Flex>
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IAICanvasToolbar />
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
gap: 4,
|
|
||||||
w: 'full',
|
|
||||||
h: 'full',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ w: 'full', h: 'full', position: 'relative' }}>
|
|
||||||
{doesCanvasNeedScaling ? <IAICanvasResizer /> : <IAICanvas />}
|
|
||||||
{isValidDrop(droppableData, active) && (
|
|
||||||
<IAIDropOverlay
|
|
||||||
isOver={isOver}
|
|
||||||
label="Set Canvas Initial Image"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user