docs: add editable node and edge demo (#572)

This commit is contained in:
vector
2021-01-22 10:19:34 +08:00
committed by GitHub
parent 10e9e7edee
commit 15f3394591
4 changed files with 180 additions and 136 deletions

View File

@ -9,7 +9,7 @@
"screenshot": "https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*FgY8TJWw1TQAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "create.ts",
"filename": "create.tsx",
"title": {
"zh": "手动创建连线",
"en": "Create Edge Manually"

View File

@ -1,131 +0,0 @@
import React from 'react'
import ReactDom from 'react-dom'
import { Dropdown, Menu, message } from 'antd'
import { Graph } from '@antv/x6'
class Example extends React.Component {
private container: HTMLDivElement
private contextMenuAnchor: HTMLSpanElement
componentDidMount() {
const graph = new Graph({
container: this.container,
grid: true,
width: 780,
height: 520,
})
const source = graph.addNode({
x: 180,
y: 60,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
strokeWidth: 1,
},
},
})
const target = graph.addNode({
x: 320,
y: 250,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
strokeWidth: 1,
},
},
})
graph.addEdge({
source,
target,
attrs: {
line: {
stroke: '#a0a0a0',
strokeWidth: 1,
},
},
})
graph.on('cell:contextmenu', ({ e }) => {
const { x, y } = graph.clientToLocal(e.clientX, e.clientY)
this.contextMenuAnchor.style.display = 'inline-block'
this.contextMenuAnchor.style.left = `${x}px`
this.contextMenuAnchor.style.top = `${y}px`
const clickEvent = document.createEvent('HTMLEvents')
clickEvent.initEvent('click', true, true)
this.contextMenuAnchor.dispatchEvent(clickEvent)
})
}
renderContextMenu() {
return (
<Menu onClick={(e) => message.info(`select ${e.key}`)}>
<Menu.Item key={0}>Menu Item 0</Menu.Item>
<Menu.Item key={1}>Menu Item 1</Menu.Item>
<Menu.Item key={2}>Menu Item 2</Menu.Item>
<Menu.Item key={3}>Menu Item 3</Menu.Item>
<Menu.Item key={4}>Menu Item 4</Menu.Item>
</Menu>
)
}
handleContextMenuVisibleChange = (visible: boolean) => {
if (!visible) {
this.contextMenuAnchor.style.display = 'none'
}
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
refContextMenuAnchor = (anchor: HTMLSpanElement) => {
this.contextMenuAnchor = anchor
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} />
<Dropdown
overlay={this.renderContextMenu()}
trigger={['click']}
onVisibleChange={this.handleContextMenuVisibleChange}
>
<span
ref={this.refContextMenuAnchor}
className="context-menu-anchor"
/>
</Dropdown>
</div>
)
}
}
ReactDom.render(<Example />, document.getElementById('container'))
// 我们用 insert-css 协助demo演示
// 实际项目中只要将下面样式添加到样式文件中
insertCss(`
.x6-graph-wrap {
position: relative;
}
.context-menu-anchor {
position: absolute;
left: 0;
top: 0;
display: none;
cursor: default;
font-size: 1px;
width: 1px;
height: 1px;
}
`)

View File

@ -0,0 +1,175 @@
import { Graph, ToolsView, EdgeView, Point } from '@antv/x6'
import '../index.less'
class EditableCellTool extends ToolsView.ToolItem<
EdgeView,
EditableCellToolOptions
> {
private editorContent: HTMLDivElement
render() {
super.render()
const cell = this.cell
let x = 0
let y = 0
let width = 0
let height = 0
if (cell.isNode()) {
const position = cell.position()
const size = cell.size()
x = position.x
y = position.y
width = size.width
height = size.height
} else {
x = this.options.x - 40
y = this.options.y - 20
width = 80
height = 40
}
const editorParent = ToolsView.createElement('div', false) as HTMLDivElement
editorParent.style.position = 'absolute'
editorParent.style.left = `${x}px`
editorParent.style.top = `${y}px`
editorParent.style.width = `${width}px`
editorParent.style.height = `${height}px`
editorParent.style.display = 'flex'
editorParent.style.alignItems = 'center'
editorParent.style.textAlign = 'center'
this.editorContent = ToolsView.createElement('div', false) as HTMLDivElement
this.editorContent.contentEditable = 'true'
this.editorContent.style.width = '100%'
this.editorContent.style.outline = 'none'
this.editorContent.style.backgroundColor = cell.isEdge() ? '#fff' : ''
this.editorContent.style.border = cell.isEdge() ? '1px solid #ccc' : 'none'
editorParent.appendChild(this.editorContent)
this.container.appendChild(editorParent)
this.init()
return this
}
init = () => {
const cell = this.cell
if (cell.isNode()) {
const value = cell.attr('text/text') as string
if (value) {
this.editorContent.innerHTML = value
cell.attr('text/text', '')
}
}
setTimeout(() => {
this.editorContent.focus()
})
document.addEventListener('mousedown', this.onMouseDown)
}
onMouseDown = (e: MouseEvent) => {
if (e.target !== this.editorContent) {
const cell = this.cell
const value = this.editorContent.innerHTML
cell.removeTools()
if (cell.isNode()) {
cell.attr('text/text', value)
} else if (cell.isEdge()) {
cell.appendLabel({
attrs: {
text: {
text: value,
}
},
position: {
distance: this.getDistance(),
}
})
}
document.removeEventListener('mousedown', this.onMouseDown)
}
}
getDistance() {
const cell = this.cell
if (cell.isEdge()) {
const targetPoint = cell.getTargetPoint()
const cross = cell.getSourceNode()!.getBBox().intersectsWithLineFromCenterToPoint(targetPoint)!
const p = new Point(this.options.x, this.options.y)
return p.distance(cross)
}
return 0
}
}
EditableCellTool.config({
tagName: 'div',
isSVGElement: false,
})
export interface EditableCellToolOptions extends ToolsView.ToolItem.Options {
x: number
y: number
}
Graph.registerEdgeTool('editableCell', EditableCellTool, true)
Graph.registerNodeTool('editableCell', EditableCellTool, true)
const container = document.getElementById('container')
const graph = new Graph({
container: container,
grid: true,
})
const source = graph.addNode({
x: 180,
y: 60,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
strokeWidth: 1,
},
},
})
const target = graph.addNode({
x: 320,
y: 250,
width: 100,
height: 40,
attrs: {
body: {
fill: '#f5f5f5',
stroke: '#d9d9d9',
strokeWidth: 1,
},
},
})
graph.addEdge({
source,
target,
attrs: {
line: {
stroke: '#a0a0a0',
strokeWidth: 1,
},
},
})
graph.on('cell:dblclick', ({ cell, e }) => {
const p = graph.clientToGraph(e.clientX, e.clientY)
cell.addTools([
{
name: 'editableCell',
args: {
x: p.x,
y: p.y,
},
},
])
})

View File

@ -25,12 +25,12 @@
"screenshot": "https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*9jEGTak16UEAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "contextmenu.tsx",
"filename": "editable.ts",
"title": {
"zh": "右键菜单",
"en": "Context Menu"
"zh": "文本编辑",
"en": "Text Editor"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*cBHESINBs3MAAAAAAAAAAAAAARQnAQ"
"screenshot": "https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*XYwVTYkKcpwAAAAAAAAAAAAAARQnAQ"
}
]
}