feat(ui): canvas perf improvements

This commit is contained in:
psychedelicious 2023-12-31 13:46:20 +11:00 committed by Kent Keirsey
parent e108a2302e
commit 6f354f16ba
6 changed files with 36 additions and 61 deletions

View File

@ -21,12 +21,11 @@ type InpaintingCanvasLinesProps = GroupConfig;
* Uses globalCompositeOperation to handle the brush and eraser tools.
*/
const IAICanvasLines = (props: InpaintingCanvasLinesProps) => {
const { ...rest } = props;
const lines = useAppSelector(canvasLinesSelector);
const objects = useAppSelector((state) => state.canvas.layerState.objects);
return (
<Group listening={false} {...rest}>
{lines.map((line, i) => (
<Group listening={false} {...props}>
{objects.filter(isCanvasMaskLine).map((line, i) => (
<Line
key={i}
points={line.points}

View File

@ -1,5 +1,3 @@
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { stateSelector } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import {
isCanvasBaseImage,
@ -13,21 +11,8 @@ import { Group, Line, Rect } from 'react-konva';
import IAICanvasImage from './IAICanvasImage';
const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
const {
layerState: { objects },
} = canvas;
return {
objects,
};
});
const IAICanvasObjectRenderer = () => {
const { objects } = useAppSelector(selector);
if (!objects) {
return null;
}
const objects = useAppSelector((state) => state.canvas.layerState.objects);
return (
<Group name="outpainting-objects" listening={false}>

View File

@ -39,7 +39,6 @@ const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
type Props = GroupConfig;
const IAICanvasStagingArea = (props: Props) => {
const { ...rest } = props;
const {
currentStagingAreaImage,
shouldShowStagingImage,
@ -51,7 +50,7 @@ const IAICanvasStagingArea = (props: Props) => {
} = useAppSelector(selector);
return (
<Group {...rest}>
<Group {...props}>
{shouldShowStagingImage && currentStagingAreaImage && (
<IAICanvasImage canvasImage={currentStagingAreaImage} />
)}

View File

@ -110,7 +110,6 @@ const canvasBrushPreviewSelector = createMemoizedSelector(
* Draws a black circle around the canvas brush preview.
*/
const IAICanvasToolPreview = (props: GroupConfig) => {
const { ...rest } = props;
const {
brushX,
brushY,
@ -133,7 +132,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
}
return (
<Group listening={false} {...clip} {...rest}>
<Group listening={false} {...clip} {...props}>
{tool === 'colorPicker' ? (
<>
<Circle
@ -143,6 +142,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
stroke={brushColorString}
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
strokeScaleEnabled={false}
listening={false}
/>
<Circle
x={brushX}
@ -151,6 +151,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
stroke={colorPickerColorString}
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
strokeScaleEnabled={false}
listening={false}
/>
</>
) : (
@ -163,6 +164,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
globalCompositeOperation={
tool === 'eraser' ? 'destination-out' : 'source-out'
}
listening={false}
/>
<Circle
x={brushX}

View File

@ -125,7 +125,7 @@ const IAICanvasMaskOptions = () => {
);
return (
<InvPopover>
<InvPopover isLazy>
<InvPopoverTrigger>
<InvIconButton
aria-label={t('unifiedCanvas.maskingOptions')}

View File

@ -1,5 +1,3 @@
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import {
@ -9,50 +7,42 @@ import {
import type { KonvaEventObject } from 'konva/lib/Node';
import { useCallback } from 'react';
const selector = createMemoizedSelector(
[stateSelector, isStagingSelector],
({ canvas }, isStaging) => {
const { tool, isMovingBoundingBox } = canvas;
return {
tool,
isStaging,
isMovingBoundingBox,
};
}
);
const useCanvasDrag = () => {
const dispatch = useAppDispatch();
const { tool, isStaging, isMovingBoundingBox } = useAppSelector(selector);
const tool = useAppSelector((state) => state.canvas.tool);
const isMovingBoundingBox = useAppSelector(
(state) => state.canvas.isMovingBoundingBox
);
const isStaging = useAppSelector(isStagingSelector);
return {
handleDragStart: useCallback(() => {
const handleDragStart = useCallback(() => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
return;
}
dispatch(setIsMovingStage(true));
}, [dispatch, isMovingBoundingBox, isStaging, tool]);
const handleDragMove = useCallback(
(e: KonvaEventObject<MouseEvent>) => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
return;
}
dispatch(setIsMovingStage(true));
}, [dispatch, isMovingBoundingBox, isStaging, tool]),
handleDragMove: useCallback(
(e: KonvaEventObject<MouseEvent>) => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
return;
}
const newCoordinates = { x: e.target.x(), y: e.target.y() };
const newCoordinates = { x: e.target.x(), y: e.target.y() };
dispatch(setStageCoordinates(newCoordinates));
},
[dispatch, isMovingBoundingBox, isStaging, tool]
);
dispatch(setStageCoordinates(newCoordinates));
},
[dispatch, isMovingBoundingBox, isStaging, tool]
),
const handleDragEnd = useCallback(() => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
return;
}
dispatch(setIsMovingStage(false));
}, [dispatch, isMovingBoundingBox, isStaging, tool]);
handleDragEnd: useCallback(() => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
return;
}
dispatch(setIsMovingStage(false));
}, [dispatch, isMovingBoundingBox, isStaging, tool]),
};
return { handleDragStart, handleDragMove, handleDragEnd };
};
export default useCanvasDrag;