|
@@ -12,6 +12,13 @@ import { StorageConfig } from "src/typings/global";
|
|
import { defaultValue } from "../JsonEditor";
|
|
import { defaultValue } from "../JsonEditor";
|
|
import { getEdgeNodes } from "./helpers";
|
|
import { getEdgeNodes } from "./helpers";
|
|
import { NodeWrapper } from "./CustomNode";
|
|
import { NodeWrapper } from "./CustomNode";
|
|
|
|
+import { Button } from "src/components/Button";
|
|
|
|
+import {
|
|
|
|
+ AiOutlineZoomIn,
|
|
|
|
+ AiOutlineZoomOut,
|
|
|
|
+ AiOutlineFullscreen,
|
|
|
|
+ AiFillSave,
|
|
|
|
+} from "react-icons/ai";
|
|
|
|
|
|
const StyledLiveEditor = styled.div`
|
|
const StyledLiveEditor = styled.div`
|
|
position: relative;
|
|
position: relative;
|
|
@@ -22,6 +29,17 @@ const StyledEditorWrapper = styled.div`
|
|
position: absolute;
|
|
position: absolute;
|
|
`;
|
|
`;
|
|
|
|
|
|
|
|
+const StyledControls = styled.div`
|
|
|
|
+ position: fixed;
|
|
|
|
+ display: grid;
|
|
|
|
+ grid-template-columns: 1fr 1fr;
|
|
|
|
+ grid-template-rows: 1fr 1fr;
|
|
|
|
+ gap: 8px;
|
|
|
|
+ bottom: 8px;
|
|
|
|
+ right: 8px;
|
|
|
|
+ opacity: 0.8;
|
|
|
|
+`;
|
|
|
|
+
|
|
export const LiveEditor: React.FC = () => {
|
|
export const LiveEditor: React.FC = () => {
|
|
const canvasRef = React.useRef<CanvasRef | null>(null);
|
|
const canvasRef = React.useRef<CanvasRef | null>(null);
|
|
const wrapperRef = React.useRef<ReactZoomPanPinchRef | null>(null);
|
|
const wrapperRef = React.useRef<ReactZoomPanPinchRef | null>(null);
|
|
@@ -39,22 +57,48 @@ export const LiveEditor: React.FC = () => {
|
|
wrapperRef.current?.resetTransform();
|
|
wrapperRef.current?.resetTransform();
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ const zoomIn = (scale: number) => {
|
|
|
|
+ if (
|
|
|
|
+ wrapperRef.current?.state.scale &&
|
|
|
|
+ wrapperRef.current?.state.scale < 2
|
|
|
|
+ ) {
|
|
|
|
+ wrapperRef.current?.setTransform(
|
|
|
|
+ wrapperRef.current.instance.transformState.positionX - 200,
|
|
|
|
+ wrapperRef.current.instance.transformState.positionY - 200,
|
|
|
|
+ wrapperRef.current.state.scale + scale
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const zoomOut = (scale: number) => {
|
|
|
|
+ if (
|
|
|
|
+ wrapperRef.current?.state.scale &&
|
|
|
|
+ wrapperRef.current?.state.scale > 0.4
|
|
|
|
+ ) {
|
|
|
|
+ wrapperRef.current?.setTransform(
|
|
|
|
+ wrapperRef.current.instance.transformState.positionX + 200,
|
|
|
|
+ wrapperRef.current.instance.transformState.positionY + 200,
|
|
|
|
+ wrapperRef.current.state.scale - scale
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
return (
|
|
return (
|
|
<StyledLiveEditor>
|
|
<StyledLiveEditor>
|
|
<StyledEditorWrapper>
|
|
<StyledEditorWrapper>
|
|
<TransformWrapper
|
|
<TransformWrapper
|
|
maxScale={2}
|
|
maxScale={2}
|
|
- limitToBounds={false}
|
|
|
|
- minScale={0.5}
|
|
|
|
|
|
+ minScale={0.4}
|
|
initialScale={0.8}
|
|
initialScale={0.8}
|
|
ref={wrapperRef}
|
|
ref={wrapperRef}
|
|
|
|
+ limitToBounds={false}
|
|
|
|
+ wheel={{
|
|
|
|
+ step: 0.4,
|
|
|
|
+ }}
|
|
>
|
|
>
|
|
<TransformComponent>
|
|
<TransformComponent>
|
|
<Canvas
|
|
<Canvas
|
|
ref={canvasRef}
|
|
ref={canvasRef}
|
|
- animated
|
|
|
|
- pannable
|
|
|
|
- zoomable={false}
|
|
|
|
nodes={nodes}
|
|
nodes={nodes}
|
|
edges={edges}
|
|
edges={edges}
|
|
layoutOptions={{
|
|
layoutOptions={{
|
|
@@ -62,15 +106,31 @@ export const LiveEditor: React.FC = () => {
|
|
}}
|
|
}}
|
|
maxWidth={20000}
|
|
maxWidth={20000}
|
|
maxHeight={20000}
|
|
maxHeight={20000}
|
|
- fit={true}
|
|
|
|
center={false}
|
|
center={false}
|
|
|
|
+ zoomable={false}
|
|
|
|
+ fit
|
|
readonly
|
|
readonly
|
|
|
|
+ animated
|
|
node={NodeWrapper}
|
|
node={NodeWrapper}
|
|
onLayoutChange={onLayoutChange}
|
|
onLayoutChange={onLayoutChange}
|
|
/>
|
|
/>
|
|
</TransformComponent>
|
|
</TransformComponent>
|
|
</TransformWrapper>
|
|
</TransformWrapper>
|
|
</StyledEditorWrapper>
|
|
</StyledEditorWrapper>
|
|
|
|
+ <StyledControls>
|
|
|
|
+ <Button onClick={() => zoomIn(0.8)}>
|
|
|
|
+ <AiOutlineZoomIn size={20} />
|
|
|
|
+ </Button>
|
|
|
|
+ <Button onClick={() => zoomOut(0.4)}>
|
|
|
|
+ <AiOutlineZoomOut size={20} />
|
|
|
|
+ </Button>
|
|
|
|
+ <Button onClick={() => wrapperRef.current?.resetTransform()}>
|
|
|
|
+ <AiOutlineFullscreen size={20} />
|
|
|
|
+ </Button>
|
|
|
|
+ <Button>
|
|
|
|
+ <AiFillSave size={20} />
|
|
|
|
+ </Button>
|
|
|
|
+ </StyledControls>
|
|
</StyledLiveEditor>
|
|
</StyledLiveEditor>
|
|
);
|
|
);
|
|
};
|
|
};
|