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";
|
||||
|
||||
function OpenImage({ close }: DialogProps) {
|
||||
const { version, setVersion, setBlocks } = useContext(CanvasContext);
|
||||
const { version, setBlocks, setVersion, centerCanvas } = useContext(CanvasContext);
|
||||
const { setLoading } = useContext(LoadingContext);
|
||||
|
||||
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
|
||||
|
|
@ -52,6 +52,8 @@ function OpenImage({ close }: DialogProps) {
|
|||
falling: false,
|
||||
});
|
||||
|
||||
const [isFinished, setIsFinished] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (acceptedFiles[0]) {
|
||||
const img = new Image();
|
||||
|
|
@ -96,6 +98,7 @@ function OpenImage({ close }: DialogProps) {
|
|||
|
||||
const onSubmit = async () => {
|
||||
if (image) {
|
||||
setIsFinished(false);
|
||||
setLoading(true);
|
||||
// Wait for loading indicator to appear
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
|
@ -131,10 +134,18 @@ function OpenImage({ close }: DialogProps) {
|
|||
}
|
||||
|
||||
setLoading(false);
|
||||
close();
|
||||
setIsFinished(true);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isFinished) return;
|
||||
centerCanvas();
|
||||
close();
|
||||
|
||||
return () => setIsFinished(false);
|
||||
}, [isFinished, centerCanvas, close]);
|
||||
|
||||
useEffect(() => {
|
||||
Object.keys(blockTypeCheckboxesChecked).forEach((property) => {
|
||||
const blocksWithProperty = Object.entries(blockData)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ interface Context {
|
|||
setCoords: React.Dispatch<React.SetStateAction<Position>>;
|
||||
setScale: React.Dispatch<React.SetStateAction<number>>;
|
||||
setVersion: React.Dispatch<React.SetStateAction<number>>;
|
||||
centerCanvas: () => void;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
|
@ -29,6 +30,7 @@ export const CanvasProvider = ({ children }: Props) => {
|
|||
const [scale, setScale] = useState(1);
|
||||
const [version, setVersion] = useState(1214);
|
||||
|
||||
// Get the farthest away blocks in each direction
|
||||
const canvasSize = useMemo(() => {
|
||||
let minX = Infinity,
|
||||
maxX = -Infinity;
|
||||
|
|
@ -50,9 +52,32 @@ export const CanvasProvider = ({ children }: Props) => {
|
|||
};
|
||||
}, [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 (
|
||||
<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}
|
||||
</CanvasContext.Provider>
|
||||
|
|
|
|||
Loading…
Reference in a new issue