feat: center canvas on image open
This commit is contained in:
parent
e82a0ef158
commit
e22d51947a
2 changed files with 39 additions and 3 deletions
|
|
@ -24,7 +24,7 @@ import VersionCombobox from "../VersionCombobox";
|
||||||
import { findBlockFromRgb } from "@/utils/findBlockFromRgb";
|
import { findBlockFromRgb } from "@/utils/findBlockFromRgb";
|
||||||
|
|
||||||
function OpenImage({ close }: DialogProps) {
|
function OpenImage({ close }: DialogProps) {
|
||||||
const { version, setVersion, setBlocks } = useContext(CanvasContext);
|
const { version, setBlocks, setVersion, centerCanvas } = useContext(CanvasContext);
|
||||||
const { setLoading } = useContext(LoadingContext);
|
const { setLoading } = useContext(LoadingContext);
|
||||||
|
|
||||||
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
|
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
|
||||||
|
|
@ -52,6 +52,8 @@ function OpenImage({ close }: DialogProps) {
|
||||||
falling: false,
|
falling: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [isFinished, setIsFinished] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (acceptedFiles[0]) {
|
if (acceptedFiles[0]) {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
|
|
@ -96,6 +98,7 @@ function OpenImage({ close }: DialogProps) {
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
if (image) {
|
if (image) {
|
||||||
|
setIsFinished(false);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
// Wait for loading indicator to appear
|
// Wait for loading indicator to appear
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
|
|
@ -131,10 +134,18 @@ function OpenImage({ close }: DialogProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
close();
|
setIsFinished(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isFinished) return;
|
||||||
|
centerCanvas();
|
||||||
|
close();
|
||||||
|
|
||||||
|
return () => setIsFinished(false);
|
||||||
|
}, [isFinished, centerCanvas, close]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Object.keys(blockTypeCheckboxesChecked).forEach((property) => {
|
Object.keys(blockTypeCheckboxesChecked).forEach((property) => {
|
||||||
const blocksWithProperty = Object.entries(blockData)
|
const blocksWithProperty = Object.entries(blockData)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ interface Context {
|
||||||
setCoords: React.Dispatch<React.SetStateAction<Position>>;
|
setCoords: React.Dispatch<React.SetStateAction<Position>>;
|
||||||
setScale: React.Dispatch<React.SetStateAction<number>>;
|
setScale: React.Dispatch<React.SetStateAction<number>>;
|
||||||
setVersion: React.Dispatch<React.SetStateAction<number>>;
|
setVersion: React.Dispatch<React.SetStateAction<number>>;
|
||||||
|
centerCanvas: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -29,6 +30,7 @@ export const CanvasProvider = ({ children }: Props) => {
|
||||||
const [scale, setScale] = useState(1);
|
const [scale, setScale] = useState(1);
|
||||||
const [version, setVersion] = useState(1214);
|
const [version, setVersion] = useState(1214);
|
||||||
|
|
||||||
|
// Get the farthest away blocks in each direction
|
||||||
const canvasSize = useMemo(() => {
|
const canvasSize = useMemo(() => {
|
||||||
let minX = Infinity,
|
let minX = Infinity,
|
||||||
maxX = -Infinity;
|
maxX = -Infinity;
|
||||||
|
|
@ -50,9 +52,32 @@ export const CanvasProvider = ({ children }: Props) => {
|
||||||
};
|
};
|
||||||
}, [blocks]);
|
}, [blocks]);
|
||||||
|
|
||||||
|
const centerCanvas = () => {
|
||||||
|
// Margin of 8 blocks on each side
|
||||||
|
const margin = 8 * 16;
|
||||||
|
|
||||||
|
// Calculate the total width and height of the blocks, including margin
|
||||||
|
const blocksWidth = (canvasSize.maxX - canvasSize.minX) * 16 + margin * 2;
|
||||||
|
const blocksHeight = (canvasSize.maxY - canvasSize.minY) * 16 + margin * 2;
|
||||||
|
|
||||||
|
// Calculate the scale to fit the blocks (with margin) within the stage
|
||||||
|
const scaleX = stageSize.width / blocksWidth;
|
||||||
|
const scaleY = stageSize.height / blocksHeight;
|
||||||
|
|
||||||
|
// Use the smaller scale to fit the blocks inside the entire screen
|
||||||
|
const newScale = Math.min(scaleX, scaleY);
|
||||||
|
|
||||||
|
// Calculate the coordinates to center the blocks in the middle of the stage
|
||||||
|
const newX = stageSize.width / 2 - ((blocksWidth - margin * 2) * newScale) / 2 - canvasSize.minX * 16 * newScale;
|
||||||
|
const newY = stageSize.height / 2 - ((blocksHeight - margin * 2) * newScale) / 2 - canvasSize.minY * 16 * newScale;
|
||||||
|
|
||||||
|
setScale(newScale);
|
||||||
|
setCoords({ x: newX, y: newY });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CanvasContext.Provider
|
<CanvasContext.Provider
|
||||||
value={{ stageSize, canvasSize, blocks, coords, scale, version, setStageSize, setBlocks, setCoords, setScale, setVersion }}
|
value={{ stageSize, canvasSize, blocks, coords, scale, version, setStageSize, setBlocks, setCoords, setScale, setVersion, centerCanvas }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</CanvasContext.Provider>
|
</CanvasContext.Provider>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue