Skip to content

Commit

Permalink
docs: add demos for port layout
Browse files Browse the repository at this point in the history
  • Loading branch information
NewByVector committed Jun 26, 2023
1 parent fb084c2 commit 96fd489
Show file tree
Hide file tree
Showing 31 changed files with 2,417 additions and 52 deletions.
2 changes: 1 addition & 1 deletion sites/x6-sites/docs/api/registry/attr.zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 属性
order: 11
order: 13
redirect_from:
- /zh/docs
- /zh/docs/api
Expand Down
2 changes: 1 addition & 1 deletion sites/x6-sites/docs/api/registry/filter.zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 滤镜
order: 12
order: 15
redirect_from:
- /zh/docs
- /zh/docs/api
Expand Down
2 changes: 1 addition & 1 deletion sites/x6-sites/docs/api/registry/highlighter.zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 高亮器
order: 11
order: 14
redirect_from:
- /zh/docs
- /zh/docs/api
Expand Down
2 changes: 1 addition & 1 deletion sites/x6-sites/docs/api/registry/port-label-layout.zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: PortLabelLayout
order: 14
order: 12
redirect_from:
- /zh/docs
- /zh/docs/api
Expand Down
58 changes: 10 additions & 48 deletions sites/x6-sites/docs/api/registry/port-layout.zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: PortLayout
order: 13
title: 连接桩布局
order: 11
redirect_from:
- /zh/docs
- /zh/docs/api
Expand Down Expand Up @@ -51,9 +51,7 @@ graph.addNode(

下面我们一起来看看如何使用内置的连接桩布局算法,以及如何自定并注册自定义布局算法。

## presets

`Registry.PortLayout.presets` 命名空间下提供了以下几个内置的布局算法。
## 内置布局

### absolute

Expand Down Expand Up @@ -100,7 +98,7 @@ graph.addNode({
})
```

<!-- <iframe src="/demos/api/registry/port-layout/absolute"></iframe> -->
<code id="port-layout-absolute" src="@/src/api/port-layout/absolute/index.tsx"></code>

### left, right, top, bottom

Expand Down Expand Up @@ -145,7 +143,7 @@ graph.addNode({
})
```

<!-- <iframe src="/demos/api/registry/port-layout/side"></iframe> -->
<code id="port-layout-side" src="@/src/api/port-layout/side/index.tsx"></code>

### line

Expand Down Expand Up @@ -200,7 +198,7 @@ graph.addNode({
})
```

<!-- <iframe src="/demos/api/registry/port-layout/line/"></iframe> -->
<code id="port-layout-line" src="@/src/api/port-layout/line/index.tsx"></code>

### ellipse

Expand Down Expand Up @@ -257,7 +255,7 @@ Array.from({ length: 10 }).forEach((_, index) => {
})
```

<!-- <iframe src="/demos/api/registry/port-layout/ellipse"></iframe> -->
<code id="port-layout-ellipse" src="@/src/api/port-layout/ellipse/index.tsx"></code>

### ellipseSpread

Expand Down Expand Up @@ -312,9 +310,9 @@ Array.from({ length: 36 }).forEach(function (_, index) {
})
```

<!-- <iframe src="/demos/api/registry/port-layout/ellipse-spread"></iframe> -->
<code id="port-layout-ellipse-spread" src="@/src/api/port-layout/ellipse-spread/index.tsx"></code>

## registry
## 自定义连接桩布局

连接桩布局算法是一个函数具有如下签名的函数,返回每个连接桩相对于节点的相对位置。例如,某节点在画布的位置是 `{ x: 30, y: 40 }`,如果返回的某个连接桩的位置是 `{ x: 2, y: 4 }`,那么该连接桩渲染到画布后的位置是 `{ x: 32, y: 44 }`

Expand Down Expand Up @@ -351,47 +349,11 @@ function sin(portsPositionArgs, elemBBox) {

布局算法实现后,需要注册到系统,注册后就可以像内置布局算法那样来使用。

### register

```ts
register(entities: { [name: string]: Definition }, force?: boolean): void
register(name: string, entity: Definition, force?: boolean): Definition
```

注册自定义布局算法。

### unregister

```ts
unregister(name: string): Definition | null
```

删除注册的自定义布局算法。

实际上,我们将 `registry``register``unregister` 方法分别挂载为 `Graph` 的两个静态方法 `Graph.registerPortLayout``Graph.unregisterPortLayout`,所以我们定义的正弦布局可以像下面这样注册到系统:

```ts
Graph.registerPortLayout('sin', sin)
```

或者:

```ts
Graph.registerPortLayout('sin', (portsPositionArgs, elemBBox) => {
return portsPositionArgs.map((_, index) => {
const step = -Math.PI / 8
const y = Math.sin(index * step) * 50
return {
position: {
x: index * 12,
y: y + elemBBox.height,
},
angle: 0,
}
})
})
```

注册以后,我们就可以像内置布局算法那样来使用:

```ts
Expand Down Expand Up @@ -429,4 +391,4 @@ Array.from({ length: 24 }).forEach(() => {
})
```

<!-- <iframe src="/demos/api/registry/port-layout/sin"></iframe> -->
<code id="port-layout-sin" src="@/src/api/port-layout/sin/index.tsx"></code>
42 changes: 42 additions & 0 deletions sites/x6-sites/src/api/port-label-layout/inside-outside/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.port-label-inside-outside-app {
display: flex;
padding: 0;
padding: 16px 8px;
font-family: sans-serif;

.app-side {
bottom: 0;
padding: 0 8px;
}

.app-content {
flex: 1;
margin-right: 8px;
margin-left: 8px;
box-shadow: 0 0 10px 1px #e9e9e9;
}

.ant-card {
box-shadow: 0 0 10px 1px #e9e9e9;
}

.ant-card-head-title {
text-align: center;
}

.ant-row {
margin: 16px 0;
text-align: left;
}

.slider-value {
display: inline-block;
margin-left: 8px;
padding: 3px 7px;
color: #333;
font-size: 12px;
line-height: 1.25;
background: #eee;
border-radius: 10px;
}
}
98 changes: 98 additions & 0 deletions sites/x6-sites/src/api/port-label-layout/inside-outside/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React from 'react'
import { Graph, Node } from '@antv/x6'
import { Settings, State } from './settings'
import './index.less'

export default class Example extends React.Component {
private container: HTMLDivElement
private node: Node

componentDidMount() {
const graph = new Graph({
container: this.container,
background: {
color: '#F2F7FA',
},
})

this.node = graph.addNode({
shape: 'ellipse',
x: 70,
y: 85,
width: 260,
height: 100,
attrs: {
label: {
text: 'outside',
fill: '#888',
fontSize: 12,
},
body: {
stroke: '#8f8f8f',
strokeWidth: 1,
fill: '#fff',
rx: 6,
ry: 6,
},
},
ports: {
groups: {
a: {
position: {
name: 'ellipseSpread',
args: {
compensateRotate: true,
},
},
label: {
position: {
name: 'outside',
},
},
attrs: {
circle: {
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
r: 10,
magnet: true,
},
text: {
fill: '#6a6c8a',
fontSize: 12,
},
},
},
},
},
})

Array.from({ length: 10 }).forEach((_, index) => {
this.node.addPort({ attrs: { text: { text: `P ${index}` } }, group: 'a' })
})
}

onAttrsChanged = ({ position, offset }: State) => {
this.node.prop('ports/groups/a/label/position', {
name: position,
args: { offset },
})

this.node.attr('label/text', position)
}

refContainer = (container: HTMLDivElement) => {
this.container = container
}

render() {
return (
<div className="port-label-inside-outside-app">
<div className="app-side">
<Settings onChange={this.onAttrsChanged} />
</div>
<div className="app-content" ref={this.refContainer} />
</div>
)
}
}
103 changes: 103 additions & 0 deletions sites/x6-sites/src/api/port-label-layout/inside-outside/settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React from 'react'
import { Radio, Slider, Card, Row, Col } from 'antd'

export interface Props {
onChange: (state: State) => void
}

export interface State {
position: string
offset: number
}

export class Settings extends React.Component<Props, State> {
state: State = {
position: 'outside',
offset: 15,
}

notifyChange() {
this.props.onChange(this.state)
}

onOffsetChanged = (offset: number) => {
this.setState({ offset }, () => {
this.notifyChange()
})
}

onPositionChange = (e: any) => {
this.setState(
{
position: e.target.value,
},
() => {
this.notifyChange()
},
)
}

render() {
const radioStyle = {
display: 'block',
height: '36px',
lineHeight: '36px',
}

return (
<Card
title="Port Label Position"
size="small"
bordered={false}
style={{ width: 240 }}
>
<Row
align="middle"
justify="center"
style={{
borderBottom: '1px solid #f0f0f0',
paddingBottom: 16,
marginBottom: 16,
}}
>
<Col>
<Radio.Group
value={this.state.position}
onChange={this.onPositionChange}
>
<Radio style={radioStyle} value={'inside'}>
inside
</Radio>
<Radio style={radioStyle} value={'outside'}>
outside
</Radio>
<Radio style={radioStyle} value={'insideOriented'}>
insideOriented
</Radio>
<Radio style={radioStyle} value={'outsideOriented'}>
outsideOriented
</Radio>
</Radio.Group>
</Col>
</Row>
<Row align="middle">
<Col span={5} style={{ textAlign: 'right', paddingRight: 16 }}>
offset
</Col>
<Col span={14}>
<Slider
min={-30}
max={30}
step={1}
value={this.state.offset}
onChange={this.onOffsetChanged}
/>
</Col>
<Col span={1} offset={1}>
<div className="slider-value">{this.state.offset}</div>
</Col>
</Row>
</Card>
)
}
}
Loading

0 comments on commit 96fd489

Please sign in to comment.