suanmei
5 years ago
committed by
拾邑
12 changed files with 274 additions and 12 deletions
@ -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; |
@ -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
|
|||
}, |
|||
}, |
|||
], |
|||
]; |
|||
} |
@ -0,0 +1,9 @@ |
|||
interface Command { |
|||
name: string; |
|||
icon: JSX.Element; |
|||
tooltip: string; |
|||
shortcut?: string; |
|||
handler: () => void; |
|||
} |
|||
|
|||
export type Commands = Command[][]; |
@ -0,0 +1 @@ |
|||
export * from './commands'; |
@ -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…
Reference in new issue