mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): slider working for all aspect ratios
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
import { Box, Flex, Icon } from '@invoke-ai/ui-library';
|
import { Box, Flex, Icon } from '@invoke-ai/ui-library';
|
||||||
import { useMeasure } from '@reactuses/core';
|
import { useMeasure } from '@reactuses/core';
|
||||||
|
import type { Dimensions } from 'features/canvas/store/canvasTypes';
|
||||||
import { memo, useCallback, useMemo, useRef } from 'react';
|
import { memo, useCallback, useMemo, useRef } from 'react';
|
||||||
import { PiCaretLeftBold, PiCaretRightBold } from 'react-icons/pi';
|
import { PiCaretLeftBold, PiCaretRightBold } from 'react-icons/pi';
|
||||||
import type { ImageDTO } from 'services/api/types';
|
import type { ImageDTO } from 'services/api/types';
|
||||||
@ -55,24 +56,32 @@ export const ImageSliderComparison = memo(({ firstImage, secondImage }: Props) =
|
|||||||
[onMouseMove, onMouseUp, updateHandlePos]
|
[onMouseMove, onMouseUp, updateHandlePos]
|
||||||
);
|
);
|
||||||
|
|
||||||
const fittedSize = useMemo(() => {
|
const fittedSize = useMemo<Dimensions>(() => {
|
||||||
let width = containerSize.width;
|
// Fit the first image to the container
|
||||||
let height = containerSize.height;
|
const targetAspectRatio = containerSize.width / containerSize.height;
|
||||||
const aspectRatio = firstImage.width / firstImage.height;
|
const imageAspectRatio = firstImage.width / firstImage.height;
|
||||||
if (firstImage.width > firstImage.height) {
|
|
||||||
width = firstImage.width;
|
if (firstImage.width <= containerSize.width && firstImage.height <= containerSize.height) {
|
||||||
height = width / aspectRatio;
|
return { width: firstImage.width, height: firstImage.height };
|
||||||
|
}
|
||||||
|
|
||||||
|
let width: number;
|
||||||
|
let height: number;
|
||||||
|
|
||||||
|
if (imageAspectRatio > targetAspectRatio) {
|
||||||
|
// Image is wider than container's aspect ratio
|
||||||
|
width = containerSize.width;
|
||||||
|
height = width / imageAspectRatio;
|
||||||
} else {
|
} else {
|
||||||
height = firstImage.height;
|
// Image is taller than container's aspect ratio
|
||||||
width = height * aspectRatio;
|
height = containerSize.height;
|
||||||
|
width = height * imageAspectRatio;
|
||||||
}
|
}
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}, [containerSize.height, containerSize.width, firstImage.height, firstImage.width]);
|
}, [containerSize.height, containerSize.width, firstImage]);
|
||||||
|
|
||||||
console.log({ containerSize, fittedSize });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex w="full" h="full" maxW="full" maxH="full" position="relative" alignItems="center" justifyContent="center">
|
<Flex w="full" h="full" maxW="full" maxH="full" position="relative" alignItems="center" justifyContent="center" bg='green'>
|
||||||
<Flex
|
<Flex
|
||||||
id="image-comparison-container"
|
id="image-comparison-container"
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
@ -81,13 +90,12 @@ export const ImageSliderComparison = memo(({ firstImage, secondImage }: Props) =
|
|||||||
maxW="full"
|
maxW="full"
|
||||||
maxH="full"
|
maxH="full"
|
||||||
position="relative"
|
position="relative"
|
||||||
border="1px solid cyan"
|
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
position="relative"
|
position="relative"
|
||||||
id="image-comparison-first-image-container"
|
id="image-comparison-second-image-container"
|
||||||
w={fittedSize.width}
|
w={fittedSize.width}
|
||||||
h={fittedSize.height}
|
h={fittedSize.height}
|
||||||
maxW="full"
|
maxW="full"
|
||||||
@ -96,18 +104,17 @@ export const ImageSliderComparison = memo(({ firstImage, secondImage }: Props) =
|
|||||||
backgroundSize="contain"
|
backgroundSize="contain"
|
||||||
backgroundRepeat="no-repeat"
|
backgroundRepeat="no-repeat"
|
||||||
userSelect="none"
|
userSelect="none"
|
||||||
border="1px solid green"
|
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
id="image-comparison-second-image-container"
|
id="image-comparison-first-image-container"
|
||||||
ref={secondImageContainerRef}
|
ref={secondImageContainerRef}
|
||||||
backgroundImage={`url(${firstImage.image_url})`}
|
backgroundImage={`url(${firstImage.image_url})`}
|
||||||
backgroundSize="auto"
|
backgroundSize={`${fittedSize.width}px ${fittedSize.height}px`}
|
||||||
backgroundPosition="top left"
|
backgroundPosition="top left"
|
||||||
backgroundRepeat="no-repeat"
|
backgroundRepeat="no-repeat"
|
||||||
w={INITIAL_POS}
|
w={INITIAL_POS}
|
||||||
h="full"
|
h={fittedSize.height}
|
||||||
maxW="full"
|
maxW="full"
|
||||||
maxH="full"
|
maxH="full"
|
||||||
position="absolute"
|
position="absolute"
|
||||||
@ -137,7 +144,14 @@ export const ImageSliderComparison = memo(({ firstImage, secondImage }: Props) =
|
|||||||
top={0}
|
top={0}
|
||||||
left={HANDLE_INNER_LEFT_INITIAL_PX}
|
left={HANDLE_INNER_LEFT_INITIAL_PX}
|
||||||
/>
|
/>
|
||||||
<Flex gap={4} position="absolute" left="50%" top="50%" transform="translate(-50%, 0)">
|
<Flex
|
||||||
|
gap={4}
|
||||||
|
position="absolute"
|
||||||
|
left="50%"
|
||||||
|
top="50%"
|
||||||
|
transform="translate(-50%, 0)"
|
||||||
|
filter="drop-shadow(0px 0px 4px rgb(0, 0, 0)) drop-shadow(0px 0px 4px rgb(0, 0, 0))"
|
||||||
|
>
|
||||||
<Icon as={PiCaretLeftBold} />
|
<Icon as={PiCaretLeftBold} />
|
||||||
<Icon as={PiCaretRightBold} />
|
<Icon as={PiCaretRightBold} />
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -151,7 +165,6 @@ export const ImageSliderComparison = memo(({ firstImage, secondImage }: Props) =
|
|||||||
left={0}
|
left={0}
|
||||||
onMouseDown={onMouseDown}
|
onMouseDown={onMouseDown}
|
||||||
userSelect="none"
|
userSelect="none"
|
||||||
bg="rgba(255,0,0,0.3)"
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
Reference in New Issue
Block a user