Improves behaviour when setting init canvas image/reset view

This commit is contained in:
psychedelicious 2022-11-18 16:18:07 +11:00 committed by blessedcoolant
parent 425a1713ab
commit bb70c32ad5
4 changed files with 118 additions and 97 deletions

View File

@ -131,6 +131,7 @@ const IAICanvasOutpaintingControls = () => {
const handleSelectMoveTool = () => dispatch(setTool('move'));
const handleResetCanvasView = () => {
const canvasBaseLayer = getCanvasBaseLayer()
if (!canvasBaseLayer) return;
const clientRect = canvasBaseLayer.getClientRect({
skipTransform: true,

View File

@ -1,14 +1,10 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store';
import { activeTabNameSelector } from 'features/options/optionsSelectors';
import Konva from 'konva';
import { KonvaEventObject } from 'konva/lib/Node';
import _ from 'lodash';
import { MutableRefObject, useCallback } from 'react';
import {
canvasSelector,
initialCanvasImageSelector,
} from 'features/canvas/store/canvasSelectors';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import {
setStageCoordinates,
setStageScale,
@ -20,21 +16,12 @@ import {
} from '../util/constants';
const selector = createSelector(
[activeTabNameSelector, canvasSelector, initialCanvasImageSelector],
(activeTabName, canvas, initialCanvasImage) => {
const {
isMoveStageKeyHeld,
stageScale,
stageDimensions,
minimumStageScale,
} = canvas;
[canvasSelector],
(canvas) => {
const { isMoveStageKeyHeld, stageScale } = canvas;
return {
isMoveStageKeyHeld,
stageScale,
activeTabName,
initialCanvasImage,
stageDimensions,
minimumStageScale,
};
},
{ memoizeOptions: { resultEqualityCheck: _.isEqual } }
@ -42,20 +29,12 @@ const selector = createSelector(
const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
const dispatch = useAppDispatch();
const {
isMoveStageKeyHeld,
stageScale,
activeTabName,
initialCanvasImage,
stageDimensions,
minimumStageScale,
} = useAppSelector(selector);
const { isMoveStageKeyHeld, stageScale } = useAppSelector(selector);
return useCallback(
(e: KonvaEventObject<WheelEvent>) => {
// stop default scrolling
if (!stageRef.current || isMoveStageKeyHeld || !initialCanvasImage)
return;
if (!stageRef.current || isMoveStageKeyHeld) return;
e.evt.preventDefault();
@ -90,7 +69,7 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
dispatch(setStageScale(newScale));
dispatch(setStageCoordinates(newCoordinates));
},
[stageRef, isMoveStageKeyHeld, initialCanvasImage, stageScale, dispatch]
[stageRef, isMoveStageKeyHeld, stageScale, dispatch]
);
};

View File

@ -369,51 +369,6 @@ export const canvasSlice = createSlice({
const initialCanvasImage =
state.layerState.objects.find(isCanvasBaseImage);
if (!initialCanvasImage) return;
const { width: imageWidth, height: imageHeight } = initialCanvasImage;
const padding = 0.95;
const newScale = calculateScale(
containerWidth,
containerHeight,
imageWidth,
imageHeight,
padding
);
const newDimensions = {
width: Math.floor(containerWidth),
height: Math.floor(containerHeight),
};
const newCoordinates = calculateCoordinates(
newDimensions.width,
newDimensions.height,
0,
0,
imageWidth,
imageHeight,
newScale
);
if (!_.isEqual(state.stageDimensions, newDimensions)) {
state.minimumStageScale = newScale;
state.stageScale = newScale;
state.stageCoordinates = floorCoordinates(newCoordinates);
state.stageDimensions = newDimensions;
}
state.isCanvasInitialized = true;
},
resizeCanvas: (state) => {
const { width: containerWidth, height: containerHeight } =
state.canvasContainerDimensions;
const initialCanvasImage =
state.layerState.objects.find(isCanvasBaseImage);
const newStageDimensions = {
width: Math.floor(containerWidth),
height: Math.floor(containerHeight),
@ -441,9 +396,72 @@ export const canvasSlice = createSlice({
state.stageScale = newScale;
state.stageCoordinates = newCoordinates;
return;
}
const { width: imageWidth, height: imageHeight } = initialCanvasImage;
const padding = 0.95;
const newScale = calculateScale(
containerWidth,
containerHeight,
imageWidth,
imageHeight,
padding
);
const newCoordinates = calculateCoordinates(
newStageDimensions.width,
newStageDimensions.height,
0,
0,
imageWidth,
imageHeight,
newScale
);
state.minimumStageScale = newScale;
state.stageScale = newScale;
state.stageCoordinates = floorCoordinates(newCoordinates);
state.stageDimensions = newStageDimensions;
state.isCanvasInitialized = true;
},
resizeCanvas: (state) => {
const { width: containerWidth, height: containerHeight } =
state.canvasContainerDimensions;
const newStageDimensions = {
width: Math.floor(containerWidth),
height: Math.floor(containerHeight),
};
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
);
state.stageScale = newScale;
state.stageCoordinates = newCoordinates;
}
},
resetCanvasView: (
state,
@ -452,38 +470,57 @@ export const canvasSlice = createSlice({
}>
) => {
const { contentRect } = action.payload;
const baseCanvasImage = state.layerState.objects.find(isCanvasBaseImage);
if (!baseCanvasImage) return;
const {
stageDimensions: { width: stageWidth, height: stageHeight },
} = state;
const { x, y, width, height } = contentRect;
const newScale = calculateScale(
stageWidth,
stageHeight,
width,
height,
STAGE_PADDING_PERCENTAGE
);
if (width !== 0 && height !== 0) {
const newScale = calculateScale(
stageWidth,
stageHeight,
width,
height,
STAGE_PADDING_PERCENTAGE
);
const newCoordinates = calculateCoordinates(
stageWidth,
stageHeight,
x,
y,
width,
height,
newScale
);
const newCoordinates = calculateCoordinates(
stageWidth,
stageHeight,
x,
y,
width,
height,
newScale
);
state.stageScale = newScale;
state.stageScale = newScale;
state.stageCoordinates = newCoordinates;
state.stageCoordinates = newCoordinates;
} else {
const newScale = calculateScale(
stageWidth,
stageHeight,
512,
512,
STAGE_PADDING_PERCENTAGE
);
const newCoordinates = calculateCoordinates(
stageWidth,
stageHeight,
0,
0,
512,
512,
newScale
);
state.stageScale = newScale;
state.stageCoordinates = newCoordinates;
}
},
nextStagingAreaImage: (state) => {
const currentIndex = state.layerState.stagingArea.selectedImageIndex;

View File

@ -23,10 +23,13 @@ import {
import * as InvokeAI from 'app/invokeai';
import * as ContextMenu from '@radix-ui/react-context-menu';
import {
resetCanvasView,
resizeAndScaleCanvas,
setDoesCanvasNeedScaling,
setInitialCanvasImage,
} from 'features/canvas/store/canvasSlice';
import { hoverableImageSelector } from './gallerySliceSelectors';
import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider';
interface HoverableImageProps {
image: InvokeAI.Image;
@ -99,7 +102,8 @@ const HoverableImage = memo((props: HoverableImageProps) => {
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
dispatch(setInitialCanvasImage(image));
dispatch(setDoesCanvasNeedScaling(true));
dispatch(resizeAndScaleCanvas());
if (activeTabName !== 'unifiedCanvas') {
dispatch(setActiveTab('unifiedCanvas'));