diff --git a/.eslintrc.js b/.eslintrc.js
index bfd8cce..28cf5a9 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -37,7 +37,6 @@ module.exports = {
'prettier/@typescript-eslint',
],
rules: {
- '@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'no-param-reassign': 'off',
'import/extensions': [
diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json
index 13c0852..f81a506 100644
--- a/packages/core/package-lock.json
+++ b/packages/core/package-lock.json
@@ -27,9 +27,9 @@
}
},
"@ant-design/icons-svg": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.0.0.tgz",
- "integrity": "sha512-Nai+cd3XUrv/z50gSk1FI08j6rENZ1e93rhKeLTBGwa5WrmHvhn2vowa5+voZW2qkXJn1btS6tdvTEDB90M0Pw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.1.0.tgz",
+ "integrity": "sha512-Fi03PfuUqRs76aI3UWYpP864lkrfPo0hluwGqh7NJdLhvH4iRDc3jbJqZIvRDLHKbXrvAfPPV3+zjUccfFvWOQ==",
"dev": true
},
"@ant-design/react-slick": {
diff --git a/packages/core/package.json b/packages/core/package.json
index f2b7c2b..320cd7c 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -36,6 +36,7 @@
"url": "https://github.com/suanmei/iMove/issues"
},
"devDependencies": {
+ "@ant-design/icons": "^4.0.6",
"@antv/x6": "^0.3.4",
"@antv/x6-react-shape": "^0.2.2",
"@emotion/core": "^10.0.28",
@@ -47,6 +48,7 @@
"watch": "^1.0.2"
},
"peerDependencies": {
+ "@ant-design/icons": "^4.0.6",
"@antv/x6": "^0.3.4",
"@antv/x6-react-shape": "^0.2.2",
"@emotion/core": "^10.0.28",
diff --git a/packages/core/src/components/toolbar.tsx b/packages/core/src/components/toolbar.tsx
new file mode 100644
index 0000000..957654a
--- /dev/null
+++ b/packages/core/src/components/toolbar.tsx
@@ -0,0 +1,72 @@
+import * as React from 'react';
+import styled from '@emotion/styled';
+import { Graph, UndoManager } from '@antv/x6';
+import { Tooltip } from 'antd';
+import { bindKey } from '../utils/tool';
+import getCommands from '../data/commands';
+import 'antd/lib/tooltip/style';
+
+export interface ToolbarProps {
+ graph: Graph;
+}
+
+const Group = styled.div`
+ position: relative;
+ display: inline-block;
+ box-sizing: border-box;
+ padding: 5px;
+ line-height: 25px;
+
+ :first-of-type {
+ :before {
+ display: none;
+ }
+ }
+
+ :before {
+ content: '';
+ display: block;
+ position: absolute;
+ width: 1px;
+ height: 12px;
+ background: #d2d2d2;
+ top: 50%;
+ left: 0;
+ transform: translateY(-50%);
+ }
+`;
+
+const Item = styled.span`
+ display: inline-block;
+ margin: 0 2px;
+ padding: 0 5px;
+ border-radius: 3px;
+ cursor: pointer;
+
+ :hover {
+ background: #ddd;
+ }
+`;
+
+const Toolbar = ({ graph }: ToolbarProps): JSX.Element => {
+ const undoManager = UndoManager.create(graph);
+ const commands = getCommands(graph, undoManager);
+
+ bindKey(commands, graph);
+
+ return (
+
+ {commands.map((items) => (
+ i.name).join('-')}>
+ {items.map((item) => (
+
+ - {item.icon}
+
+ ))}
+
+ ))}
+
+ );
+};
+
+export default Toolbar;
diff --git a/packages/core/src/data/cells.ts b/packages/core/src/data/cells.ts
index 6a6cd34..41e8faa 100644
--- a/packages/core/src/data/cells.ts
+++ b/packages/core/src/data/cells.ts
@@ -1,4 +1,4 @@
-import { Style, Point } from '@antv/x6';
+import { Style } from '@antv/x6';
import { CellTypes } from '../components/cells';
interface CellStyle extends Style {
@@ -8,13 +8,12 @@ interface CellStyle extends Style {
export interface DataItem {
label?: string;
title: string;
- data?: any;
width: number;
height: number;
scale: number;
+ data?: any;
style: CellStyle;
isEdge?: boolean;
- points?: Point[];
}
export const generals: DataItem[] = [
diff --git a/packages/core/src/data/commands.tsx b/packages/core/src/data/commands.tsx
new file mode 100644
index 0000000..3d6b688
--- /dev/null
+++ b/packages/core/src/data/commands.tsx
@@ -0,0 +1,88 @@
+import * as React from 'react';
+import {
+ UndoOutlined,
+ RedoOutlined,
+ ZoomInOutlined,
+ ZoomOutOutlined,
+ RetweetOutlined,
+ FullscreenOutlined,
+ DeleteOutlined,
+ SaveOutlined,
+} from '@ant-design/icons';
+import { Graph, UndoManager } from '@antv/x6';
+import * as Tool from '../utils/tool';
+import { Commands } from '../model';
+
+export default function getCommands(graph: Graph, undoManager: UndoManager): Commands {
+ return [
+ [
+ {
+ name: 'undo',
+ icon: ,
+ tooltip: '撤销',
+ shortcut: 'Cmd + Z',
+ handler: (): void => undoManager.undo(),
+ },
+ {
+ name: 'redo',
+ icon: ,
+ tooltip: '重做',
+ shortcut: 'Cmd + Shift + Z',
+ handler: (): void => undoManager.redo(),
+ },
+ ],
+ [
+ {
+ name: 'zoomIn',
+ icon: ,
+ tooltip: '放大',
+ handler: Tool.zoomIn(graph),
+ },
+ {
+ name: 'zoomOut',
+ icon: ,
+ tooltip: '缩小',
+ handler: Tool.zoomOut(graph),
+ },
+ ],
+ [
+ {
+ name: 'resetView',
+ icon: ,
+ tooltip: '重置视口',
+ handler: (): void => {
+ graph.zoomTo(1);
+ graph.center();
+ },
+ },
+ {
+ name: 'fitWindow',
+ icon: ,
+ tooltip: '适应窗口',
+ handler: (): void => {
+ graph.fit(8);
+ },
+ },
+ ],
+ [
+ {
+ name: 'delete',
+ icon: ,
+ tooltip: '删除',
+ shortcut: 'Delete',
+ handler: (): void => graph.deleteCells(),
+ },
+ ],
+ [
+ {
+ name: 'save',
+ icon: ,
+ tooltip: '保存',
+ shortcut: 'Cmd + S',
+ handler: (): void => {
+ // code
+ },
+ },
+ ],
+ ];
+}
diff --git a/packages/core/src/index.tsx b/packages/core/src/index.tsx
index 41fe77f..7e85c0e 100644
--- a/packages/core/src/index.tsx
+++ b/packages/core/src/index.tsx
@@ -4,6 +4,7 @@ import { Graph, Shape, DomEvent } from '@antv/x6';
import { ReactShape } from '@antv/x6-react-shape';
import styled from '@emotion/styled';
import Sidebar from './components/sidebar';
+import Toolbar from './components/toolbar';
import createGraph from './utils/create-graph';
import 'antd/lib/layout/style';
@@ -20,14 +21,33 @@ const IMoveLayout = styled(Layout)`
`;
const IMoveHeader = styled(Header)`
+ height: 50px;
background: #fff;
border-bottom: 1px solid #ddd;
`;
+const IMoveTitle = styled.h2`
+ line-height: 50px;
+`;
+
const IMoveSider = styled(Sider)`
background: #fff;
`;
+const IMoveContent = styled(Content)`
+ position: relative;
+ padding-top: 35px;
+`;
+
+const ToolWrapper = styled.div`
+ position: absolute;
+ top: 0;
+ width: 100%;
+ height: 35px;
+ line-height: 35px;
+ background: #fff;
+`;
+
class Core extends React.Component<{}, CoreState> {
private graph: Graph | null = null;
@@ -57,13 +77,14 @@ class Core extends React.Component<{}, CoreState> {
return (
- iMove
+ iMove
{this.graph && inited && }
-
+
+ {this.graph && inited && }
-
+
Sider
diff --git a/packages/core/src/model/commands.ts b/packages/core/src/model/commands.ts
new file mode 100644
index 0000000..19de9b9
--- /dev/null
+++ b/packages/core/src/model/commands.ts
@@ -0,0 +1,9 @@
+interface Command {
+ name: string;
+ icon: JSX.Element;
+ tooltip: string;
+ shortcut?: string;
+ handler: () => void;
+}
+
+export type Commands = Command[][];
diff --git a/packages/core/src/model/index.ts b/packages/core/src/model/index.ts
new file mode 100644
index 0000000..30272ff
--- /dev/null
+++ b/packages/core/src/model/index.ts
@@ -0,0 +1 @@
+export * from './commands';
diff --git a/packages/core/src/utils/create-graph.ts b/packages/core/src/utils/create-graph.ts
index 4c7fb62..630ca16 100644
--- a/packages/core/src/utils/create-graph.ts
+++ b/packages/core/src/utils/create-graph.ts
@@ -6,6 +6,7 @@ export default function createGraph(container: HTMLDivElement): Graph {
rotate: false,
resize: false,
infinite: true,
+ rubberband: true,
backgroundColor: '#f8f9fa',
grid: {
type: 'dot',
@@ -55,7 +56,9 @@ export default function createGraph(container: HTMLDivElement): Graph {
shouldRedrawOnDataChange(): boolean {
return true;
},
- getAnchors(cell): [number, number][] {
+ getAnchors(cell): [number, number][] | null {
+ if (!cell || !cell.data) return null;
+
if (cell.data.style.type === 'start') {
return [[0.5, 1]];
}
diff --git a/packages/core/src/utils/patch-dnd.tsx b/packages/core/src/utils/patch-dnd.tsx
index fa1c3b8..1254ce6 100644
--- a/packages/core/src/utils/patch-dnd.tsx
+++ b/packages/core/src/utils/patch-dnd.tsx
@@ -59,7 +59,7 @@ export default function patchDnd(
component: | ,
});
- graph.selectCell(cell);
+ graph.unSelectCells(graph.getSelectedCells()).selectCell(cell);
});
});
}
diff --git a/packages/core/src/utils/tool.ts b/packages/core/src/utils/tool.ts
new file mode 100644
index 0000000..85a4c0b
--- /dev/null
+++ b/packages/core/src/utils/tool.ts
@@ -0,0 +1,68 @@
+import { Graph } from '@antv/x6';
+import { Commands } from '../model';
+
+export function zoomIn(graph: Graph) {
+ return (): void => {
+ let { scale } = graph.view;
+ if (scale >= 8) {
+ scale += 8;
+ } else if (scale >= 4) {
+ scale += 4;
+ } else if (scale >= 2) {
+ scale += 1;
+ } else if (scale >= 1.5) {
+ scale += 0.5;
+ } else if (scale >= 1) {
+ scale += 0.25;
+ } else if (scale >= 0.7) {
+ scale += 0.15;
+ } else if (scale >= 0.4) {
+ scale += 0.1;
+ } else if (scale >= 0.15) {
+ scale += 0.05;
+ } else if (scale >= 0.01) {
+ scale += 0.01;
+ }
+ graph.zoomTo(scale);
+ };
+}
+
+export function zoomOut(graph: Graph) {
+ return (): void => {
+ let { scale } = graph.view;
+ if (scale <= 0.15) {
+ scale -= 0.01;
+ } else if (scale <= 0.4) {
+ scale -= 0.05;
+ } else if (scale <= 0.7) {
+ scale -= 0.1;
+ } else if (scale <= 1) {
+ scale -= 0.15;
+ } else if (scale <= 1.5) {
+ scale -= 0.25;
+ } else if (scale <= 2) {
+ scale -= 0.5;
+ } else if (scale <= 4) {
+ scale -= 1;
+ } else if (scale <= 8) {
+ scale -= 4;
+ } else if (scale <= 16) {
+ scale -= 8;
+ }
+ graph.zoomTo(scale);
+ };
+}
+
+export function bindKey(commands: Commands, graph: Graph): void {
+ commands.forEach((items) =>
+ items.forEach((item) => {
+ if (item.shortcut) {
+ if (item.shortcut === 'Delete') {
+ graph.bindKey(['del', 'backspace'], item.handler);
+ } else {
+ graph.bindKey(item.shortcut, item.handler);
+ }
+ }
+ })
+ );
+}