Skip to content

Commit

Permalink
Feat: added workspace auto centering
Browse files Browse the repository at this point in the history
  • Loading branch information
Akalanka47000 committed Mar 9, 2024
1 parent c277dd8 commit 60ae7ce
Show file tree
Hide file tree
Showing 5 changed files with 464 additions and 30 deletions.
22 changes: 20 additions & 2 deletions src/components/workspace/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { useCallback, useLayoutEffect } from "react";
import { useSelector } from "react-redux";
import { twMerge } from "tailwind-merge";
import { ids } from "@/constants";
import { ids, selectors } from "@/constants";
import { store } from "@/store";
import { initializeElements, sync } from "@/store/reducers/editor";
import { type ISTKProps } from "@/types";
import { d3Extended } from "@/utils";
import { Tool, tools } from "../toolbar/data";
import { default as Crosshairs } from "./crosshairs";
import { default as Element, ElementType } from "./elements";
import { default as Grid } from "./grid";
import { default as Zoom } from "./zoom";
import { default as Zoom, zoomAndPan } from "./zoom";

export { default as Cursor } from "./cursor";

Expand All @@ -29,6 +30,23 @@ export const Workspace: React.FC<ISTKProps> = (props) => {
useLayoutEffect(() => {
if (props.data) {
store.dispatch(sync(props.data));
setTimeout(() => {
const { height: workspaceheight, width: workspaceWidth } = d3Extended.selectionBounds(
d3Extended.selectById(ids.workspace)
);
const {
left: wgOffsetLeft,
top: wgOffsetTop,
height: workspaceGroupHeight,
width: workspaceGroupWidth
} = d3Extended.selectionBounds(d3Extended.select(selectors.workspaceGroup));
const scaleFactor = 1.05;
zoomAndPan({
k: scaleFactor,
y: (workspaceheight - (wgOffsetTop * scaleFactor * 2 + workspaceGroupHeight * scaleFactor)) / 2 - 5,
x: (workspaceWidth - (wgOffsetLeft * scaleFactor * 2 + workspaceGroupWidth * scaleFactor)) / 2
});
}, 0);
} else {
store.dispatch(initializeElements());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,63 @@
import { memo, useLayoutEffect } from "react";
import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Minus, Plus } from "lucide-react";
import { useSelector } from "react-redux";
import * as d3 from "d3";
import { twMerge } from "tailwind-merge";
import { ids, selectors } from "@/constants";
import { useSkipFirstRender } from "@/hooks";
import { d3Extended } from "@/utils";
import { Tool } from "../toolbar/data";

function handleZoom(e) {
const workspace = d3.select(selectors.workspaceGroup);
const workspace = d3Extended.select(selectors.workspaceGroup);
workspace.attr("transform", e.transform);
}

const zoom = d3.zoom().on("zoom", handleZoom);
const zoom = d3Extended.zoom().on("zoom", handleZoom);

const zoomIn = () => {
d3.select(`#${ids.workspace}`).transition().call(zoom.scaleBy, 1.1);
d3Extended.selectById(ids.workspace).transition().call(zoom.scaleBy, 1.1);
};

const zoomOut = () => {
d3.select(`#${ids.workspace}`).transition().call(zoom.scaleBy, 0.9);
d3Extended.selectById(ids.workspace).transition().call(zoom.scaleBy, 0.9);
};

const panLeft = () => {
d3.select(`#${ids.workspace}`).transition().call(zoom.translateBy, 50, 0);
d3Extended.selectById(ids.workspace).transition().call(zoom.translateBy, 50, 0);
};

const panRight = () => {
d3.select(`#${ids.workspace}`).transition().call(zoom.translateBy, -50, 0);
d3Extended.selectById(ids.workspace).transition().call(zoom.translateBy, -50, 0);
};

const panUp = () => {
d3.select(`#${ids.workspace}`).transition().call(zoom.translateBy, 0, 50);
d3Extended.selectById(ids.workspace).transition().call(zoom.translateBy, 0, 50);
};

const panDown = () => {
d3.select(`#${ids.workspace}`).transition().call(zoom.translateBy, 0, -50);
d3Extended.selectById(ids.workspace).transition().call(zoom.translateBy, 0, -50);
};

export const zoomAndPan = ({ k, x, y }) => {
d3Extended
.selectById(ids.workspace)
.transition()
.duration(1000)
.call(zoom.transform, d3Extended.zoomIdentity.translate(x, y).scale(k));
};

const panHandleClasses =
"absolute z-10 text-black/40 cursor-pointer hover:text-black/80 transition-all duration-medium";

const Zoom = () => {
const selectedTool = useSelector((state) => state.toolbar.selectedTool);
const showControls = useSelector((state) => state.editor.showControls);
const selectedTool = useSelector((state: any) => state.toolbar.selectedTool);
const showControls = useSelector((state: any) => state.editor.showControls);

useLayoutEffect(() => {
const selection = d3.select(`#${ids.workspace}`);
const selection = d3Extended.selectById(ids.workspace);
selection.on("zoom", null);
if (selectedTool == Tool.Pan) {
d3.select(`#${ids.workspace}`).call(zoom);
selection.call(zoom);
} else {
selection
.call(zoom)
Expand All @@ -62,7 +70,7 @@ const Zoom = () => {
const currentZoom = selection.property("__zoom").k || 1;
if (e.ctrlKey) {
const nextZoom = currentZoom * Math.pow(2, -e.deltaY * 0.01);
zoom.scaleTo(selection, nextZoom, d3.pointer(e));
zoom.scaleTo(selection, nextZoom, d3Extended.pointer(e));
} else {
zoom.translateBy(selection, -(e.deltaX / currentZoom), -(e.deltaY / currentZoom));
}
Expand All @@ -71,7 +79,7 @@ const Zoom = () => {
}, [selectedTool]);

useSkipFirstRender(() => {
const workspace = d3.select(`#${ids.workspace}`);
const workspace = d3Extended.selectById(ids.workspace);
const controlTransformActive = workspace.attr("control-transform-active");
if (showControls) {
if (!controlTransformActive) {
Expand Down
Loading

0 comments on commit 60ae7ce

Please sign in to comment.