Browse Source

feat: 工具栏

master
suanmei 5 years ago
committed by 拾邑
parent
commit
674daceec1
  1. 1
      .eslintrc.js
  2. 6
      packages/core/package-lock.json
  3. 2
      packages/core/package.json
  4. 72
      packages/core/src/components/toolbar.tsx
  5. 5
      packages/core/src/data/cells.ts
  6. 88
      packages/core/src/data/commands.tsx
  7. 27
      packages/core/src/index.tsx
  8. 9
      packages/core/src/model/commands.ts
  9. 1
      packages/core/src/model/index.ts
  10. 5
      packages/core/src/utils/create-graph.ts
  11. 2
      packages/core/src/utils/patch-dnd.tsx
  12. 68
      packages/core/src/utils/tool.ts

1
.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': [

6
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": {

2
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",

72
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 (
<div>
{commands.map((items) => (
<Group key={items.map((i) => i.name).join('-')}>
{items.map((item) => (
<Tooltip title={item.tooltip} key={item.name}>
<Item onClick={item.handler}>{item.icon}</Item>
</Tooltip>
))}
</Group>
))}
</div>
);
};
export default Toolbar;

5
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[] = [

88
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: <UndoOutlined />,
tooltip: '撤销',
shortcut: 'Cmd + Z',
handler: (): void => undoManager.undo(),
},
{
name: 'redo',
icon: <RedoOutlined />,
tooltip: '重做',
shortcut: 'Cmd + Shift + Z',
handler: (): void => undoManager.redo(),
},
],
[
{
name: 'zoomIn',
icon: <ZoomInOutlined />,
tooltip: '放大',
handler: Tool.zoomIn(graph),
},
{
name: 'zoomOut',
icon: <ZoomOutOutlined />,
tooltip: '缩小',
handler: Tool.zoomOut(graph),
},
],
[
{
name: 'resetView',
icon: <RetweetOutlined />,
tooltip: '重置视口',
handler: (): void => {
graph.zoomTo(1);
graph.center();
},
},
{
name: 'fitWindow',
icon: <FullscreenOutlined />,
tooltip: '适应窗口',
handler: (): void => {
graph.fit(8);
},
},
],
[
{
name: 'delete',
icon: <DeleteOutlined />,
tooltip: '删除',
shortcut: 'Delete',
handler: (): void => graph.deleteCells(),
},
],
[
{
name: 'save',
icon: <SaveOutlined />,
tooltip: '保存',
shortcut: 'Cmd + S',
handler: (): void => {
// code
},
},
],
];
}

27
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 (
<IMoveLayout>
<IMoveHeader>
<h2>iMove</h2>
<IMoveTitle>iMove</IMoveTitle>
</IMoveHeader>
<IMoveLayout>
<IMoveSider>{this.graph && inited && <Sidebar graph={this.graph} />}</IMoveSider>
<Content>
<IMoveContent>
<ToolWrapper>{this.graph && inited && <Toolbar graph={this.graph} />}</ToolWrapper>
<div ref={this.container} />
</Content>
</IMoveContent>
<IMoveSider>Sider</IMoveSider>
</IMoveLayout>
</IMoveLayout>

9
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[][];

1
packages/core/src/model/index.ts

@ -0,0 +1 @@
export * from './commands';

5
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]];
}

2
packages/core/src/utils/patch-dnd.tsx

@ -59,7 +59,7 @@ export default function patchDnd(
component: <Cell scale={scale} />,
});
graph.selectCell(cell);
graph.unSelectCells(graph.getSelectedCells()).selectCell(cell);
});
});
}

68
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);
}
}
})
);
}
Loading…
Cancel
Save