Compare commits

...

7 Commits

Author SHA1 Message Date
9fe7cd51a3 chore(release): 🚀 publish 2022-10-11 15:49:11 +08:00
34481de1db chore: 🔧 unify the version numbers of all packages 2022-10-11 15:45:00 +08:00
9d597a92da chore: 🔧 update build-dev script 2022-10-10 12:11:28 +08:00
40f278f064 chore: 🔧 update publish script 2022-10-10 11:25:25 +08:00
f3edbbc95d feat: expose the selection api (#2756)
* chore: 🔧 update publish script

* feat:  expose the selection api
2022-10-09 22:34:13 +08:00
50a5dc7cd8 feat: add selection plugin (#2742)
* feat:  add selection plugin

* fix: 🐛 reset selection default options
2022-10-02 14:21:56 +08:00
5aeae976cd feat: add autoResize feature 2022-09-28 15:47:43 +08:00
58 changed files with 3201 additions and 3115 deletions

View File

@ -1,5 +1,7 @@
import React from 'react'
import { Graph, Node, Edge, NodeView, Point, Angle, Interp } from '@antv/x6'
import { Graph, Node, Edge, NodeView } from '@antv/x6'
import { Point, Angle } from '@antv/x6-geometry'
import { Interp } from '@antv/x6-common'
import '../index.less'
class BallView extends NodeView {

View File

@ -12,7 +12,6 @@ export default class Example extends React.Component {
container: this.container,
width: 650,
height: 400,
grid: 1,
background: {
color: '#F2F7FA',
},

View File

@ -0,0 +1,9 @@
.full {
width: 100%;
height: 100%;
}
.x6-split-box-horizontal > .x6-split-box-resizer,
.x6-split-box-vertical > .x6-split-box-resizer {
background: #ffe58f;
}

View File

@ -1,67 +1,38 @@
import React from 'react'
import { Graph } from '@antv/x6'
import { SplitBox } from '@antv/x6-react-components'
import '@antv/x6-react-components/es/split-box/style/index.css'
import '../index.less'
import './index.less'
export default class Example extends React.Component {
private graphContainer1: HTMLDivElement
private graphContainer2: HTMLDivElement
private graphContainer3: HTMLDivElement
componentDidMount() {
const graph1 = new Graph({
new Graph({
container: this.graphContainer1,
background: {
color: '#f5f5f5',
color: '#F2F7FA',
},
grid: true,
scroller: true,
autoResize: true,
})
const rect = graph1.addNode({
x: 300,
y: 300,
width: 90,
height: 60,
})
const circle = graph1.addNode({
x: 400,
y: 400,
width: 40,
height: 40,
})
graph1.addEdge({
source: rect,
target: circle,
})
const graph2 = new Graph({
new Graph({
container: this.graphContainer2,
background: {
color: '#f5f5f5',
color: '#F2F7FA',
},
grid: true,
autoResize: true,
})
const source = graph2.addNode({
x: 40,
y: 40,
width: 80,
height: 40,
})
const target = graph2.addNode({
x: 120,
y: 100,
width: 80,
height: 40,
})
graph2.addEdge({
source,
target,
new Graph({
container: this.graphContainer3,
background: {
color: '#F2F7FA',
},
autoResize: true,
})
}
@ -73,23 +44,29 @@ export default class Example extends React.Component {
this.graphContainer2 = container
}
refContainer3 = (container: HTMLDivElement) => {
this.graphContainer3 = container
}
render() {
return (
<div style={{ width: '100%', height: '100%' }}>
<div className="x6-graph-wrap" style={{ display: 'flex' }}>
<div
ref={this.refContainer1}
style={{ flex: 1, margin: '0 32px' }}
className="x6-graph"
/>
</div>
<div className="x6-graph-wrap" style={{ display: 'flex' }}>
<div
ref={this.refContainer2}
style={{ flex: 1, margin: '0 32px' }}
className="x6-graph"
/>
</div>
<div
className="x6-graph-wrap"
style={{ width: 800, height: 800, margin: '0 auto' }}
>
<SplitBox split="horizontal">
<div className="full">
<div ref={this.refContainer1} className="x6-graph" />
</div>
<SplitBox split="vertical">
<div className="full">
<div ref={this.refContainer2} className="x6-graph" />
</div>
<div className="full">
<div ref={this.refContainer3} className="x6-graph" />
</div>
</SplitBox>
</SplitBox>
</div>
)
}

View File

@ -1,468 +1,468 @@
import React from 'react'
import { Graph } from '@antv/x6'
import { Marker } from '@antv/x6/es/registry'
import '../index.less'
// import React from 'react'
// import { Graph } from '@antv/x6'
// import { Marker } from '@antv/x6/es/registry'
// import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
// export default class Example extends React.Component {
// private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
interacting: { edgeMovable: false },
connecting: {
connectionPoint: {
name: 'boundary',
args: {
extrapolate: true,
sticky: true,
},
},
validateConnection: function () {
return false
},
},
})
// componentDidMount() {
// const graph = new Graph({
// container: this.container,
// width: 800,
// height: 600,
// interacting: { edgeMovable: false },
// connecting: {
// connectionPoint: {
// name: 'boundary',
// args: {
// extrapolate: true,
// sticky: true,
// },
// },
// validateConnection: function () {
// return false
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 20 },
target: { x: 350, y: 20 },
attrs: {
line: {
stroke: '#222138',
sourceMarker: {
name: 'classic',
fill: '#31d0c6',
stroke: 'none',
size: 20,
},
targetMarker: {
name: 'block',
fill: '#fe854f',
stroke: 'none',
size: 20,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 20 },
// target: { x: 350, y: 20 },
// attrs: {
// line: {
// stroke: '#222138',
// sourceMarker: {
// name: 'classic',
// fill: '#31d0c6',
// stroke: 'none',
// size: 20,
// },
// targetMarker: {
// name: 'block',
// fill: '#fe854f',
// stroke: 'none',
// size: 20,
// },
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 80 },
target: { x: 350, y: 80 },
attrs: {
line: {
stroke: '#fe854f',
strokeWidth: 1,
sourceMarker: 'block',
targetMarker: {
tagName: 'circle',
r: 5,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 80 },
// target: { x: 350, y: 80 },
// attrs: {
// line: {
// stroke: '#fe854f',
// strokeWidth: 1,
// sourceMarker: 'block',
// targetMarker: {
// tagName: 'circle',
// r: 5,
// },
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 400 },
target: { x: 280, y: 400 },
attrs: {
line: {
stroke: '#fe854f',
strokeWidth: 1,
sourceMarker: 'block',
targetMarker: {
name: 'block',
width: 12,
height: 6,
open: true,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 400 },
// target: { x: 280, y: 400 },
// attrs: {
// line: {
// stroke: '#fe854f',
// strokeWidth: 1,
// sourceMarker: 'block',
// targetMarker: {
// name: 'block',
// width: 12,
// height: 6,
// open: true,
// },
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 430 },
target: { x: 280, y: 430 },
attrs: {
line: {
stroke: '#fe854f',
strokeWidth: 1,
sourceMarker: 'diamond',
targetMarker: {
name: 'diamond',
width: 12,
height: 6,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 430 },
// target: { x: 280, y: 430 },
// attrs: {
// line: {
// stroke: '#fe854f',
// strokeWidth: 1,
// sourceMarker: 'diamond',
// targetMarker: {
// name: 'diamond',
// width: 12,
// height: 6,
// },
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 460 },
target: { x: 280, y: 460 },
attrs: {
line: {
stroke: '#fe854f',
strokeWidth: 1,
sourceMarker: 'ellipse',
targetMarker: {
name: 'ellipse',
rx: 6,
ry: 4,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 460 },
// target: { x: 280, y: 460 },
// attrs: {
// line: {
// stroke: '#fe854f',
// strokeWidth: 1,
// sourceMarker: 'ellipse',
// targetMarker: {
// name: 'ellipse',
// rx: 6,
// ry: 4,
// },
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 490 },
target: { x: 280, y: 490 },
attrs: {
line: {
stroke: '#fe854f',
strokeWidth: 1,
sourceMarker: 'circle',
targetMarker: {
name: 'circlePlus',
r: 10,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 490 },
// target: { x: 280, y: 490 },
// attrs: {
// line: {
// stroke: '#fe854f',
// strokeWidth: 1,
// sourceMarker: 'circle',
// targetMarker: {
// name: 'circlePlus',
// r: 10,
// },
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 520 },
target: { x: 280, y: 520 },
attrs: {
line: {
stroke: '#fe854f',
strokeWidth: 1,
sourceMarker: 'cross',
targetMarker: {
name: 'cross',
width: 12,
height: 8,
offset: -10,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 520 },
// target: { x: 280, y: 520 },
// attrs: {
// line: {
// stroke: '#fe854f',
// strokeWidth: 1,
// sourceMarker: 'cross',
// targetMarker: {
// name: 'cross',
// width: 12,
// height: 8,
// offset: -10,
// },
// },
// },
// })
graph.addEdge({
source: { x: 20, y: 550 },
target: { x: 280, y: 550 },
attrs: {
line: {
stroke: '#fe854f',
strokeWidth: 1,
sourceMarker: 'async',
targetMarker: {
name: 'async',
width: 12,
height: 8,
offset: -10,
open: true,
flip: true,
},
},
},
})
// graph.addEdge({
// source: { x: 20, y: 550 },
// target: { x: 280, y: 550 },
// attrs: {
// line: {
// stroke: '#fe854f',
// strokeWidth: 1,
// sourceMarker: 'async',
// targetMarker: {
// name: 'async',
// width: 12,
// height: 8,
// offset: -10,
// open: true,
// flip: true,
// },
// },
// },
// })
graph.addEdge({
source: { x: 10, y: 140 },
target: { x: 350, y: 140 },
attrs: {
line: {
stroke: '#31d0c6',
strokeWidth: 3,
strokeDasharray: '5 2',
sourceMarker: {
stroke: '#31d0c6',
fill: '#31d0c6',
d: Marker.normalize(
'M5.5,15.499,15.8,21.447,15.8,15.846,25.5,21.447,25.5,9.552,15.8,15.152,15.8,9.552z',
),
},
targetMarker: {
stroke: '#31d0c6',
fill: '#31d0c6',
name: 'path',
d: 'M4.834,4.834L4.833,4.833c-5.889,5.892-5.89,15.443,0.001,21.334s15.44,5.888,21.33-0.002c5.891-5.891,5.893-15.44,0.002-21.33C20.275-1.056,10.725-1.056,4.834,4.834zM25.459,5.542c0.833,0.836,1.523,1.757,2.104,2.726l-4.08,4.08c-0.418-1.062-1.053-2.06-1.912-2.918c-0.859-0.859-1.857-1.494-2.92-1.913l4.08-4.08C23.7,4.018,24.622,4.709,25.459,5.542zM10.139,20.862c-2.958-2.968-2.959-7.758-0.001-10.725c2.966-2.957,7.756-2.957,10.725,0c2.954,2.965,2.955,7.757-0.001,10.724C17.896,23.819,13.104,23.817,10.139,20.862zM5.542,25.459c-0.833-0.837-1.524-1.759-2.105-2.728l4.081-4.081c0.418,1.063,1.055,2.06,1.914,2.919c0.858,0.859,1.855,1.494,2.917,1.913l-4.081,4.081C7.299,26.982,6.379,26.292,5.542,25.459zM8.268,3.435l4.082,4.082C11.288,7.935,10.29,8.571,9.43,9.43c-0.858,0.859-1.494,1.855-1.912,2.918L3.436,8.267c0.58-0.969,1.271-1.89,2.105-2.727C6.377,4.707,7.299,4.016,8.268,3.435zM22.732,27.563l-4.082-4.082c1.062-0.418,2.061-1.053,2.919-1.912c0.859-0.859,1.495-1.857,1.913-2.92l4.082,4.082c-0.58,0.969-1.271,1.891-2.105,2.728C24.623,26.292,23.701,26.983,22.732,27.563z',
offsetX: 10,
},
},
},
})
// graph.addEdge({
// source: { x: 10, y: 140 },
// target: { x: 350, y: 140 },
// attrs: {
// line: {
// stroke: '#31d0c6',
// strokeWidth: 3,
// strokeDasharray: '5 2',
// sourceMarker: {
// stroke: '#31d0c6',
// fill: '#31d0c6',
// d: Marker.normalize(
// 'M5.5,15.499,15.8,21.447,15.8,15.846,25.5,21.447,25.5,9.552,15.8,15.152,15.8,9.552z',
// ),
// },
// targetMarker: {
// stroke: '#31d0c6',
// fill: '#31d0c6',
// name: 'path',
// d: 'M4.834,4.834L4.833,4.833c-5.889,5.892-5.89,15.443,0.001,21.334s15.44,5.888,21.33-0.002c5.891-5.891,5.893-15.44,0.002-21.33C20.275-1.056,10.725-1.056,4.834,4.834zM25.459,5.542c0.833,0.836,1.523,1.757,2.104,2.726l-4.08,4.08c-0.418-1.062-1.053-2.06-1.912-2.918c-0.859-0.859-1.857-1.494-2.92-1.913l4.08-4.08C23.7,4.018,24.622,4.709,25.459,5.542zM10.139,20.862c-2.958-2.968-2.959-7.758-0.001-10.725c2.966-2.957,7.756-2.957,10.725,0c2.954,2.965,2.955,7.757-0.001,10.724C17.896,23.819,13.104,23.817,10.139,20.862zM5.542,25.459c-0.833-0.837-1.524-1.759-2.105-2.728l4.081-4.081c0.418,1.063,1.055,2.06,1.914,2.919c0.858,0.859,1.855,1.494,2.917,1.913l-4.081,4.081C7.299,26.982,6.379,26.292,5.542,25.459zM8.268,3.435l4.082,4.082C11.288,7.935,10.29,8.571,9.43,9.43c-0.858,0.859-1.494,1.855-1.912,2.918L3.436,8.267c0.58-0.969,1.271-1.89,2.105-2.727C6.377,4.707,7.299,4.016,8.268,3.435zM22.732,27.563l-4.082-4.082c1.062-0.418,2.061-1.053,2.919-1.912c0.859-0.859,1.495-1.857,1.913-2.92l4.082,4.082c-0.58,0.969-1.271,1.891-2.105,2.728C24.623,26.292,23.701,26.983,22.732,27.563z',
// offsetX: 10,
// },
// },
// },
// })
graph.addEdge({
source: { x: 400, y: 20 },
target: { x: 740, y: 20 },
vertices: [
{ x: 400, y: 60 },
{ x: 550, y: 60 },
{ x: 550, y: 20 },
],
attrs: {
line: {
stroke: '#3c4260',
strokeWidth: 2,
sourceMarker: {
fill: '#4b4a67',
stroke: '#4b4a67',
d: Marker.normalize(
'M5.5,15.499,15.8,21.447,15.8,15.846,25.5,21.447,25.5,9.552,15.8,15.152,15.8,9.552z',
),
},
targetMarker: {
fill: '#4b4a67',
stroke: '#4b4a67',
d: Marker.normalize(
'M5.5,15.499,15.8,21.447,15.8,15.846,25.5,21.447,25.5,9.552,15.8,15.152,15.8,9.552z',
),
},
vertexMarker: {
tagName: 'circle',
r: 4,
strokeWidth: 2,
fill: 'white',
},
},
},
})
// graph.addEdge({
// source: { x: 400, y: 20 },
// target: { x: 740, y: 20 },
// vertices: [
// { x: 400, y: 60 },
// { x: 550, y: 60 },
// { x: 550, y: 20 },
// ],
// attrs: {
// line: {
// stroke: '#3c4260',
// strokeWidth: 2,
// sourceMarker: {
// fill: '#4b4a67',
// stroke: '#4b4a67',
// d: Marker.normalize(
// 'M5.5,15.499,15.8,21.447,15.8,15.846,25.5,21.447,25.5,9.552,15.8,15.152,15.8,9.552z',
// ),
// },
// targetMarker: {
// fill: '#4b4a67',
// stroke: '#4b4a67',
// d: Marker.normalize(
// 'M5.5,15.499,15.8,21.447,15.8,15.846,25.5,21.447,25.5,9.552,15.8,15.152,15.8,9.552z',
// ),
// },
// vertexMarker: {
// tagName: 'circle',
// r: 4,
// strokeWidth: 2,
// fill: 'white',
// },
// },
// },
// })
graph.addEdge({
source: { x: 440, y: 100 },
target: { x: 740, y: 100 },
vertices: [
{ x: 400, y: 140 },
{ x: 550, y: 100 },
{ x: 600, y: 140 },
],
smooth: true,
attrs: {
line: {
stroke: '#7c68fc',
strokeWidth: 3,
sourceMarker: {
stroke: '#7c68fc',
fill: '#7c68fc',
d: Marker.normalize(
'M24.316,5.318,9.833,13.682,9.833,5.5,5.5,5.5,5.5,25.5,9.833,25.5,9.833,17.318,24.316,25.682z',
),
},
targetMarker: {
stroke: '#feb663',
fill: '#feb663',
d: Marker.normalize(
'M14.615,4.928c0.487-0.986,1.284-0.986,1.771,0l2.249,4.554c0.486,0.986,1.775,1.923,2.864,2.081l5.024,0.73c1.089,0.158,1.335,0.916,0.547,1.684l-3.636,3.544c-0.788,0.769-1.28,2.283-1.095,3.368l0.859,5.004c0.186,1.085-0.459,1.553-1.433,1.041l-4.495-2.363c-0.974-0.512-2.567-0.512-3.541,0l-4.495,2.363c-0.974,0.512-1.618,0.044-1.432-1.041l0.858-5.004c0.186-1.085-0.307-2.6-1.094-3.368L3.93,13.977c-0.788-0.768-0.542-1.525,0.547-1.684l5.026-0.73c1.088-0.158,2.377-1.095,2.864-2.081L14.615,4.928z',
),
},
},
},
})
// graph.addEdge({
// source: { x: 440, y: 100 },
// target: { x: 740, y: 100 },
// vertices: [
// { x: 400, y: 140 },
// { x: 550, y: 100 },
// { x: 600, y: 140 },
// ],
// smooth: true,
// attrs: {
// line: {
// stroke: '#7c68fc',
// strokeWidth: 3,
// sourceMarker: {
// stroke: '#7c68fc',
// fill: '#7c68fc',
// d: Marker.normalize(
// 'M24.316,5.318,9.833,13.682,9.833,5.5,5.5,5.5,5.5,25.5,9.833,25.5,9.833,17.318,24.316,25.682z',
// ),
// },
// targetMarker: {
// stroke: '#feb663',
// fill: '#feb663',
// d: Marker.normalize(
// 'M14.615,4.928c0.487-0.986,1.284-0.986,1.771,0l2.249,4.554c0.486,0.986,1.775,1.923,2.864,2.081l5.024,0.73c1.089,0.158,1.335,0.916,0.547,1.684l-3.636,3.544c-0.788,0.769-1.28,2.283-1.095,3.368l0.859,5.004c0.186,1.085-0.459,1.553-1.433,1.041l-4.495-2.363c-0.974-0.512-2.567-0.512-3.541,0l-4.495,2.363c-0.974,0.512-1.618,0.044-1.432-1.041l0.858-5.004c0.186-1.085-0.307-2.6-1.094-3.368L3.93,13.977c-0.788-0.768-0.542-1.525,0.547-1.684l5.026-0.73c1.088-0.158,2.377-1.095,2.864-2.081L14.615,4.928z',
// ),
// },
// },
// },
// })
graph.addEdge({
shape: 'double-edge',
source: { x: 10, y: 200 },
target: { x: 350, y: 200 },
attrs: {
line: {
stroke: '#7c68fc',
},
},
labels: [
{
attrs: { text: { text: 'Label' } },
position: {
offset: 15,
distance: 0.5,
},
},
],
})
// graph.addEdge({
// shape: 'double-edge',
// source: { x: 10, y: 200 },
// target: { x: 350, y: 200 },
// attrs: {
// line: {
// stroke: '#7c68fc',
// },
// },
// labels: [
// {
// attrs: { text: { text: 'Label' } },
// position: {
// offset: 15,
// distance: 0.5,
// },
// },
// ],
// })
graph.addEdge({
source: { x: 400, y: 200 },
target: { x: 740, y: 200 },
connector: { name: 'smooth' },
attrs: {
line: {
targetMarker: {
d: 'M 0 -5 L -10 0 L 0 5 Z',
},
},
},
labels: [
{
markup: [
{
tagName: 'rect',
selector: 'labelBody',
},
{
tagName: 'text',
selector: 'labelText',
},
],
attrs: {
labelText: {
text: 'First',
fill: '#7c68fc',
fontFamily: 'sans-serif',
textAnchor: 'middle',
textVerticalAnchor: 'middle',
},
labelBody: {
ref: 'labelText',
refX: -5,
refY: -5,
refWidth: '100%',
refHeight: '100%',
refWidth2: 10,
refHeight2: 10,
stroke: '#7c68fc',
fill: 'white',
strokeWidth: 2,
rx: 5,
ry: 5,
},
},
position: {
distance: 0.3,
options: {
keepGradient: true,
ensureLegibility: true,
},
},
},
{
markup: [
{
tagName: 'ellipse',
selector: 'labelBody',
},
{
tagName: 'text',
selector: 'labelText',
},
],
attrs: {
labelText: {
text: 'Second',
fill: '#31d0c6',
fontFamily: 'sans-serif',
textAnchor: 'middle',
textVerticalAnchor: 'middle',
},
labelBody: {
ref: 'labelText',
refRx: '70%',
refRy: '80%',
stroke: '#31d0c6',
fill: 'white',
strokeWidth: 2,
},
},
position: {
distance: 0.7,
angle: 45,
},
},
],
})
// graph.addEdge({
// source: { x: 400, y: 200 },
// target: { x: 740, y: 200 },
// connector: { name: 'smooth' },
// attrs: {
// line: {
// targetMarker: {
// d: 'M 0 -5 L -10 0 L 0 5 Z',
// },
// },
// },
// labels: [
// {
// markup: [
// {
// tagName: 'rect',
// selector: 'labelBody',
// },
// {
// tagName: 'text',
// selector: 'labelText',
// },
// ],
// attrs: {
// labelText: {
// text: 'First',
// fill: '#7c68fc',
// fontFamily: 'sans-serif',
// textAnchor: 'middle',
// textVerticalAnchor: 'middle',
// },
// labelBody: {
// ref: 'labelText',
// refX: -5,
// refY: -5,
// refWidth: '100%',
// refHeight: '100%',
// refWidth2: 10,
// refHeight2: 10,
// stroke: '#7c68fc',
// fill: 'white',
// strokeWidth: 2,
// rx: 5,
// ry: 5,
// },
// },
// position: {
// distance: 0.3,
// options: {
// keepGradient: true,
// ensureLegibility: true,
// },
// },
// },
// {
// markup: [
// {
// tagName: 'ellipse',
// selector: 'labelBody',
// },
// {
// tagName: 'text',
// selector: 'labelText',
// },
// ],
// attrs: {
// labelText: {
// text: 'Second',
// fill: '#31d0c6',
// fontFamily: 'sans-serif',
// textAnchor: 'middle',
// textVerticalAnchor: 'middle',
// },
// labelBody: {
// ref: 'labelText',
// refRx: '70%',
// refRy: '80%',
// stroke: '#31d0c6',
// fill: 'white',
// strokeWidth: 2,
// },
// },
// position: {
// distance: 0.7,
// angle: 45,
// },
// },
// ],
// })
graph.addEdge({
shape: 'shadow-edge',
source: { x: 10, y: 280 },
target: { x: 440, y: 280 },
vertices: [
{ x: 150, y: 350 },
{ x: 300, y: 280 },
],
connector: { name: 'smooth' },
markup: [
{
tagName: 'path',
selector: 'shadow',
attrs: {
fill: 'none',
},
},
{
tagName: 'path',
selector: 'line',
attrs: {
fill: 'none',
},
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
line: {
stroke: '#3c4260',
},
label: {
textPath: {
selector: 'line',
startOffset: '50%',
},
textAnchor: 'middle',
textVerticalAnchor: 'middle',
text: 'Label Along Path',
fill: '#f6f6f6',
fontSize: 15,
fontWeight: 'bold',
fontFamily: 'fantasy',
},
},
})
// graph.addEdge({
// shape: 'shadow-edge',
// source: { x: 10, y: 280 },
// target: { x: 440, y: 280 },
// vertices: [
// { x: 150, y: 350 },
// { x: 300, y: 280 },
// ],
// connector: { name: 'smooth' },
// markup: [
// {
// tagName: 'path',
// selector: 'shadow',
// attrs: {
// fill: 'none',
// },
// },
// {
// tagName: 'path',
// selector: 'line',
// attrs: {
// fill: 'none',
// },
// },
// {
// tagName: 'text',
// selector: 'label',
// },
// ],
// attrs: {
// line: {
// stroke: '#3c4260',
// },
// label: {
// textPath: {
// selector: 'line',
// startOffset: '50%',
// },
// textAnchor: 'middle',
// textVerticalAnchor: 'middle',
// text: 'Label Along Path',
// fill: '#f6f6f6',
// fontSize: 15,
// fontWeight: 'bold',
// fontFamily: 'fantasy',
// },
// },
// })
// Custom Edge
// -----------
// // Custom Edge
// // -----------
const node1 = graph.addNode({
shape: 'path',
x: 500,
y: 450,
width: 100,
height: 100,
attrs: {
body: {
fill: '#31d0c6',
refD: 'M 0 20 10 20 10 30 30 30 30 0 40 0 40 40 0 40 z',
},
},
})
// const node1 = graph.addNode({
// shape: 'path',
// x: 500,
// y: 450,
// width: 100,
// height: 100,
// attrs: {
// body: {
// fill: '#31d0c6',
// refD: 'M 0 20 10 20 10 30 30 30 30 0 40 0 40 40 0 40 z',
// },
// },
// })
graph.addEdge({
source: { x: 300, y: 400 },
target: node1,
attrs: {
line: {
sourceMarker: {
d: 'M 0 0 15 0',
stroke: 'white',
strokeWidth: 3,
},
},
},
})
}
// graph.addEdge({
// source: { x: 300, y: 400 },
// target: node1,
// attrs: {
// line: {
// sourceMarker: {
// d: 'M 0 0 15 0',
// stroke: 'white',
// strokeWidth: 3,
// },
// },
// },
// })
// }
refContainer = (container: HTMLDivElement) => {
this.container = container
}
// refContainer = (container: HTMLDivElement) => {
// this.container = container
// }
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}
// render() {
// return (
// <div className="x6-graph-wrap">
// <div ref={this.refContainer} className="x6-graph" />
// </div>
// )
// }
// }

View File

@ -1,75 +1,75 @@
import React from 'react'
import { Graph, Point } from '@antv/x6'
import { Router } from '@antv/x6/es/registry/router'
import '../index.less'
// import React from 'react'
// import { Graph, Point } from '@antv/x6'
// import { Router } from '@antv/x6/es/registry/router'
// import '../index.less'
Router.registry.register(
'random',
(vertices, args, view) => {
const BOUNCES = args.bounces || 20
const points = vertices.map((p) => Point.create(p))
// Router.registry.register(
// 'random',
// (vertices, args, view) => {
// const BOUNCES = args.bounces || 20
// const points = vertices.map((p) => Point.create(p))
for (var i = 0; i < BOUNCES; i++) {
const sourceCorner = view.sourceBBox.getCenter()
const targetCorner = view.targetBBox.getCenter()
const randomPoint = Point.random(
sourceCorner.x,
targetCorner.x,
sourceCorner.y,
targetCorner.y,
)
points.push(randomPoint)
}
// for (var i = 0; i < BOUNCES; i++) {
// const sourceCorner = view.sourceBBox.getCenter()
// const targetCorner = view.targetBBox.getCenter()
// const randomPoint = Point.random(
// sourceCorner.x,
// targetCorner.x,
// sourceCorner.y,
// targetCorner.y,
// )
// points.push(randomPoint)
// }
return points
},
true,
)
// return points
// },
// true,
// )
export default class Example extends React.Component {
private container: HTMLDivElement
// export default class Example extends React.Component {
// private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 1000,
height: 600,
grid: 10,
})
// componentDidMount() {
// const graph = new Graph({
// container: this.container,
// width: 1000,
// height: 600,
// grid: 10,
// })
const source = graph.addNode({
x: 50,
y: 50,
width: 120,
height: 80,
attrs: { label: { text: 'Source' } },
})
// const source = graph.addNode({
// x: 50,
// y: 50,
// width: 120,
// height: 80,
// attrs: { label: { text: 'Source' } },
// })
const target = graph.addNode(
source.clone().translate(600, 400).attr('label/text', 'Target'),
)
// const target = graph.addNode(
// source.clone().translate(600, 400).attr('label/text', 'Target'),
// )
graph.addEdge({
source,
target,
router: {
name: 'random',
args: {
bounces: 10,
},
},
})
}
// graph.addEdge({
// source,
// target,
// router: {
// name: 'random',
// args: {
// bounces: 10,
// },
// },
// })
// }
refContainer = (container: HTMLDivElement) => {
this.container = container
}
// refContainer = (container: HTMLDivElement) => {
// this.container = container
// }
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}
// render() {
// return (
// <div className="x6-graph-wrap">
// <div ref={this.refContainer} className="x6-graph" />
// </div>
// )
// }
// }

View File

@ -1,298 +1,298 @@
import { Rect, Edge } from '@antv/x6/es/shape/standard'
// import { Rect, Edge } from '@antv/x6/es/shape/standard'
export class Event extends Rect {
static create(label: string) {
return new Event({
attrs: {
label: {
text: label,
},
},
})
}
}
// export class Event extends Rect {
// static create(label: string) {
// return new Event({
// attrs: {
// label: {
// text: label,
// },
// },
// })
// }
// }
Event.config({
zIndex: 3,
attrs: {
root: {
pointerEvents: 'bounding-box',
},
body: {
strokeWidth: 2,
fillOpacity: 0.2,
},
label: {
textWrap: {
height: -20,
width: -20,
ellipsis: true,
},
refX: '50%',
refY: '50%',
fontSize: 16,
fontFamily: 'sans-serif',
fill: '#333333',
textAnchor: 'middle',
textVerticalAnchor: 'middle',
},
},
})
// Event.config({
// zIndex: 3,
// attrs: {
// root: {
// pointerEvents: 'bounding-box',
// },
// body: {
// strokeWidth: 2,
// fillOpacity: 0.2,
// },
// label: {
// textWrap: {
// height: -20,
// width: -20,
// ellipsis: true,
// },
// refX: '50%',
// refY: '50%',
// fontSize: 16,
// fontFamily: 'sans-serif',
// fill: '#333333',
// textAnchor: 'middle',
// textVerticalAnchor: 'middle',
// },
// },
// })
export class IntermediateEvent extends Event {
static create(label: string, type?: string) {
return new IntermediateEvent({
attrs: {
label: {
text: label,
},
gate: {
gateType: type,
},
},
})
}
gateTypes = {
or: 'M -20 0 C -20 -15 -10 -30 0 -30 C 10 -30 20 -15 20 0 C 10 -6 -10 -6 -20 0',
xor: 'M -20 0 C -20 -15 -10 -30 0 -30 C 10 -30 20 -15 20 0 C 10 -6 -10 -6 -20 0 M -20 0 0 -30 M 0 -30 20 0',
and: 'M -20 0 C -20 -25 -10 -30 0 -30 C 10 -30 20 -25 20 0 Z',
priority_and:
'M -20 0 C -20 -25 -10 -30 0 -30 C 10 -30 20 -25 20 0 Z M -20 0 0 -30 20 0',
inhibit: 'M -10 0 -20 -15 -10 -30 10 -30 20 -15 10 0 Z',
transfer: 'M -20 0 20 0 0 -30 z',
}
// export class IntermediateEvent extends Event {
// static create(label: string, type?: string) {
// return new IntermediateEvent({
// attrs: {
// label: {
// text: label,
// },
// gate: {
// gateType: type,
// },
// },
// })
// }
// gateTypes = {
// or: 'M -20 0 C -20 -15 -10 -30 0 -30 C 10 -30 20 -15 20 0 C 10 -6 -10 -6 -20 0',
// xor: 'M -20 0 C -20 -15 -10 -30 0 -30 C 10 -30 20 -15 20 0 C 10 -6 -10 -6 -20 0 M -20 0 0 -30 M 0 -30 20 0',
// and: 'M -20 0 C -20 -25 -10 -30 0 -30 C 10 -30 20 -25 20 0 Z',
// priority_and:
// 'M -20 0 C -20 -25 -10 -30 0 -30 C 10 -30 20 -25 20 0 Z M -20 0 0 -30 20 0',
// inhibit: 'M -10 0 -20 -15 -10 -30 10 -30 20 -15 10 0 Z',
// transfer: 'M -20 0 20 0 0 -30 z',
// }
gate(): string
gate(type: string): this
gate(type?: string) {
if (type === undefined) {
return this.attr<string>(['gate', 'gateType'])
}
// gate(): string
// gate(type: string): this
// gate(type?: string) {
// if (type === undefined) {
// return this.attr<string>(['gate', 'gateType'])
// }
this.attr(['gate'], {
gateType: type,
title: type.toUpperCase() + ' Gate',
})
// this.attr(['gate'], {
// gateType: type,
// title: type.toUpperCase() + ' Gate',
// })
return this
}
}
// return this
// }
// }
IntermediateEvent.config(
{
size: {
width: 100,
height: 100,
},
markup: [
{
tagName: 'path',
selector: 'gate',
},
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
root: {
title: 'Intermediate Event',
},
body: {
refWidth: '100%',
refHeight: -40,
stroke: '#3c4260',
fill: '#3c4260',
},
gate: {
event: 'element:gate:click',
gateType: 'xor',
stroke: '#7c68fc',
fill: '#7c68fc',
fillOpacity: 0.2,
strokeWidth: 2,
refX: '50%',
refY: '100%',
fillRule: 'nonzero',
cursor: 'pointer',
},
label: {
textWrap: {
height: -40,
width: -10,
},
refY2: -20,
},
},
},
{
gateType: {
set(type: string) {
var data = this.cell.gateTypes[type]
return { d: data ? data + ' M 0 -30 0 -40' : 'M 0 0 0 0' }
},
},
},
)
// IntermediateEvent.config(
// {
// size: {
// width: 100,
// height: 100,
// },
// markup: [
// {
// tagName: 'path',
// selector: 'gate',
// },
// {
// tagName: 'rect',
// selector: 'body',
// },
// {
// tagName: 'text',
// selector: 'label',
// },
// ],
// attrs: {
// root: {
// title: 'Intermediate Event',
// },
// body: {
// refWidth: '100%',
// refHeight: -40,
// stroke: '#3c4260',
// fill: '#3c4260',
// },
// gate: {
// event: 'element:gate:click',
// gateType: 'xor',
// stroke: '#7c68fc',
// fill: '#7c68fc',
// fillOpacity: 0.2,
// strokeWidth: 2,
// refX: '50%',
// refY: '100%',
// fillRule: 'nonzero',
// cursor: 'pointer',
// },
// label: {
// textWrap: {
// height: -40,
// width: -10,
// },
// refY2: -20,
// },
// },
// },
// {
// gateType: {
// set(type: string) {
// var data = this.cell.gateTypes[type]
// return { d: data ? data + ' M 0 -30 0 -40' : 'M 0 0 0 0' }
// },
// },
// },
// )
export class ExternalEvent extends Event {}
// export class ExternalEvent extends Event {}
ExternalEvent.config({
size: {
width: 80,
height: 100,
},
markup: [
{
tagName: 'path',
selector: 'body',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
root: {
title: 'External Event',
},
body: {
refD: 'M 0 0 10 -10 20 0 20 40 0 40 Z',
stroke: '#fe854f',
fill: '#fe854f',
},
},
})
// ExternalEvent.config({
// size: {
// width: 80,
// height: 100,
// },
// markup: [
// {
// tagName: 'path',
// selector: 'body',
// },
// {
// tagName: 'text',
// selector: 'label',
// },
// ],
// attrs: {
// root: {
// title: 'External Event',
// },
// body: {
// refD: 'M 0 0 10 -10 20 0 20 40 0 40 Z',
// stroke: '#fe854f',
// fill: '#fe854f',
// },
// },
// })
export class UndevelopedEvent extends Event {}
UndevelopedEvent.config({
size: {
width: 140,
height: 80,
},
markup: [
{
tagName: 'path',
selector: 'body',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
root: {
title: 'Undeveloped Event',
},
body: {
refD: 'M -1 0 0 1 1 0 0 -1 Z',
stroke: '#feb663',
fill: '#feb663',
},
},
})
// export class UndevelopedEvent extends Event {}
// UndevelopedEvent.config({
// size: {
// width: 140,
// height: 80,
// },
// markup: [
// {
// tagName: 'path',
// selector: 'body',
// },
// {
// tagName: 'text',
// selector: 'label',
// },
// ],
// attrs: {
// root: {
// title: 'Undeveloped Event',
// },
// body: {
// refD: 'M -1 0 0 1 1 0 0 -1 Z',
// stroke: '#feb663',
// fill: '#feb663',
// },
// },
// })
export class BasicEvent extends Event {}
BasicEvent.config({
zIndex: 3,
size: {
width: 80,
height: 80,
},
markup: [
{
tagName: 'circle',
selector: 'body',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
root: {
title: 'Basic Event',
},
body: {
refCx: '50%',
refCy: '50%',
refR: '50%',
stroke: '#30d0c6',
fill: '#30d0c6',
},
},
})
// export class BasicEvent extends Event {}
// BasicEvent.config({
// zIndex: 3,
// size: {
// width: 80,
// height: 80,
// },
// markup: [
// {
// tagName: 'circle',
// selector: 'body',
// },
// {
// tagName: 'text',
// selector: 'label',
// },
// ],
// attrs: {
// root: {
// title: 'Basic Event',
// },
// body: {
// refCx: '50%',
// refCy: '50%',
// refR: '50%',
// stroke: '#30d0c6',
// fill: '#30d0c6',
// },
// },
// })
export class ConditioningEvent extends Event {}
ConditioningEvent.config({
zIndex: 2,
size: {
width: 140,
height: 80,
},
markup: [
{
tagName: 'ellipse',
selector: 'body',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
root: {
title: 'Conditioning Event',
},
body: {
refCx: '50%',
refCy: '50%',
refRx: '50%',
refRy: '50%',
stroke: '#7c68fc',
fill: '#7c68fc',
fillOpacity: 0.2,
},
},
})
// export class ConditioningEvent extends Event {}
// ConditioningEvent.config({
// zIndex: 2,
// size: {
// width: 140,
// height: 80,
// },
// markup: [
// {
// tagName: 'ellipse',
// selector: 'body',
// },
// {
// tagName: 'text',
// selector: 'label',
// },
// ],
// attrs: {
// root: {
// title: 'Conditioning Event',
// },
// body: {
// refCx: '50%',
// refCy: '50%',
// refRx: '50%',
// refRy: '50%',
// stroke: '#7c68fc',
// fill: '#7c68fc',
// fillOpacity: 0.2,
// },
// },
// })
export class Connector extends Edge {
static create(event1: Event, event2: Event) {
return new Connector({
zIndex: 1,
source: {
cell: event1.id,
selector: event1 instanceof IntermediateEvent ? 'gate' : 'body',
},
target: {
cell: event2.id,
selector: 'body',
},
})
}
}
// export class Connector extends Edge {
// static create(event1: Event, event2: Event) {
// return new Connector({
// zIndex: 1,
// source: {
// cell: event1.id,
// selector: event1 instanceof IntermediateEvent ? 'gate' : 'body',
// },
// target: {
// cell: event2.id,
// selector: 'body',
// },
// })
// }
// }
Connector.config({
attrs: {
line: {
connection: true,
stroke: '#333333',
strokeWidth: 2,
strokeLinejoin: 'round',
},
},
markup: [
{
tagName: 'path',
selector: 'line',
attrs: {
fill: 'none',
'pointer-events': 'none',
},
},
],
})
// Connector.config({
// attrs: {
// line: {
// connection: true,
// stroke: '#333333',
// strokeWidth: 2,
// strokeLinejoin: 'round',
// },
// },
// markup: [
// {
// tagName: 'path',
// selector: 'line',
// attrs: {
// fill: 'none',
// 'pointer-events': 'none',
// },
// },
// ],
// })

View File

@ -1,140 +1,140 @@
import React from 'react'
import { Node, Vector, Graph, Point, Line, Polyline } from '@antv/x6'
import { Connector } from '@antv/x6/es/registry/connector'
import '../index.less'
// import React from 'react'
// import { Node, Vector, Graph, Point, Line, Polyline } from '@antv/x6'
// import { Connector } from '@antv/x6/es/registry/connector'
// import '../index.less'
function random(max: number, min: number) {
return Math.floor(Math.random() * (max - min)) + min
}
// function random(max: number, min: number) {
// return Math.floor(Math.random() * (max - min)) + min
// }
export default class Example extends React.Component {
private container: HTMLDivElement
// export default class Example extends React.Component {
// private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: 1,
translating: {
restrict: {
x: 50,
y: 50,
width: 700,
height: 500,
},
},
})
// componentDidMount() {
// const graph = new Graph({
// container: this.container,
// width: 800,
// height: 600,
// grid: 1,
// translating: {
// restrict: {
// x: 50,
// y: 50,
// width: 700,
// height: 500,
// },
// },
// })
function createCircle(x: number, y: number, group: 'inner' | 'outer') {
const node = graph.addNode({
shape: 'circle',
size: { width: 20, height: 20 },
position: { x: x, y: y },
group: group,
attrs: {
body: {
strokeWidth: 3,
fill: group === 'inner' ? '#af9bff' : '#31d0c6',
stroke: group === 'inner' ? '#7c68fc' : '#009d93',
},
},
})
// function createCircle(x: number, y: number, group: 'inner' | 'outer') {
// const node = graph.addNode({
// shape: 'circle',
// size: { width: 20, height: 20 },
// position: { x: x, y: y },
// group: group,
// attrs: {
// body: {
// strokeWidth: 3,
// fill: group === 'inner' ? '#af9bff' : '#31d0c6',
// stroke: group === 'inner' ? '#7c68fc' : '#009d93',
// },
// },
// })
node.on('change:position', updateBoundaries)
}
// node.on('change:position', updateBoundaries)
// }
function createBoundary(color: string) {
var boundary = Vector.create('path').attr({
fill: color,
'fill-opacity': 0.2,
stroke: color,
'stroke-width': 3,
})
// function createBoundary(color: string) {
// var boundary = Vector.create('path').attr({
// fill: color,
// 'fill-opacity': 0.2,
// stroke: color,
// 'stroke-width': 3,
// })
Vector.create(graph.view.stage).prepend(boundary)
// Vector.create(graph.view.stage).prepend(boundary)
return boundary
}
// return boundary
// }
function updateBoundaries() {
var padding = 10
// function updateBoundaries() {
// var padding = 10
var innerPoints = getPointsByGroup('inner', padding)
var outerPoints = getPointsByGroup('outer', padding)
// var innerPoints = getPointsByGroup('inner', padding)
// var outerPoints = getPointsByGroup('outer', padding)
var innerHullPoints = convexHullAlgorithm(innerPoints)
var innerBoundaryPoints = getPaddedPoints(innerHullPoints, padding)
var outerHullPoints = convexHullAlgorithm(
outerPoints.concat(innerBoundaryPoints),
)
// var innerHullPoints = convexHullAlgorithm(innerPoints)
// var innerBoundaryPoints = getPaddedPoints(innerHullPoints, padding)
// var outerHullPoints = convexHullAlgorithm(
// outerPoints.concat(innerBoundaryPoints),
// )
innerBoundary.attr('d', createData(innerHullPoints))
outerBoundary.attr('d', createData(outerHullPoints))
}
// innerBoundary.attr('d', createData(innerHullPoints))
// outerBoundary.attr('d', createData(outerHullPoints))
// }
function getPointsByGroup(group: 'inner' | 'outer', padding: number) {
var node = graph.model.getNodes().filter((node) => {
return node.getProp('group') === group
})
// function getPointsByGroup(group: 'inner' | 'outer', padding: number) {
// var node = graph.model.getNodes().filter((node) => {
// return node.getProp('group') === group
// })
return node.reduce<Point[]>((memo, el) => {
return memo.concat(getNodeCornerPoints(el, padding))
}, [])
}
// return node.reduce<Point[]>((memo, el) => {
// return memo.concat(getNodeCornerPoints(el, padding))
// }, [])
// }
function getNodeCornerPoints(node: Node, padding: number = 0) {
var bbox = node.getBBox().inflate(padding)
return [bbox.origin, bbox.bottomLeft, bbox.corner, bbox.topRight]
}
// function getNodeCornerPoints(node: Node, padding: number = 0) {
// var bbox = node.getBBox().inflate(padding)
// return [bbox.origin, bbox.bottomLeft, bbox.corner, bbox.topRight]
// }
function getPaddedPoints(points: Point[], padding: number = 0) {
return points.reduce<Point[]>((memo, point) => {
memo.push(
point.clone().translate(padding, padding),
point.clone().translate(-padding, padding),
point.clone().translate(padding, -padding),
point.clone().translate(-padding, -padding),
)
return memo
}, [])
}
// function getPaddedPoints(points: Point[], padding: number = 0) {
// return points.reduce<Point[]>((memo, point) => {
// memo.push(
// point.clone().translate(padding, padding),
// point.clone().translate(-padding, padding),
// point.clone().translate(padding, -padding),
// point.clone().translate(-padding, -padding),
// )
// return memo
// }, [])
// }
function createData(points: Point[], radius?: number) {
var origin = new Line(points[0], points[points.length - 1]).getCenter()
return Connector.presets.rounded.call(this, origin, origin, points, {
radius: radius || 30,
})
}
// function createData(points: Point[], radius?: number) {
// var origin = new Line(points[0], points[points.length - 1]).getCenter()
// return Connector.presets.rounded.call(this, origin, origin, points, {
// radius: radius || 30,
// })
// }
function convexHullAlgorithm(points: Point[]) {
return new Polyline(points).toHull().points
}
// function convexHullAlgorithm(points: Point[]) {
// return new Polyline(points).toHull().points
// }
// bootstrap
// ---------
Array.from({ length: 10 }).forEach((_, i) => {
var x = random(100, 700)
var y = random(100, 500)
createCircle(x, y, i % 3 === 0 ? 'inner' : 'outer')
})
// // bootstrap
// // ---------
// Array.from({ length: 10 }).forEach((_, i) => {
// var x = random(100, 700)
// var y = random(100, 500)
// createCircle(x, y, i % 3 === 0 ? 'inner' : 'outer')
// })
// create boundaries around elements
var innerBoundary = createBoundary('#fe854f')
var outerBoundary = createBoundary('#feb663')
// // create boundaries around elements
// var innerBoundary = createBoundary('#fe854f')
// var outerBoundary = createBoundary('#feb663')
updateBoundaries()
}
// updateBoundaries()
// }
refContainer = (container: HTMLDivElement) => {
this.container = container
}
// refContainer = (container: HTMLDivElement) => {
// this.container = container
// }
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}
// render() {
// return (
// <div className="x6-graph-wrap">
// <div ref={this.refContainer} className="x6-graph" />
// </div>
// )
// }
// }

View File

@ -1,166 +0,0 @@
import React from 'react'
import { Graph } from '@antv/x6'
import { Stencil } from '@antv/x6/es/addon/stencil'
import { Rect, Circle } from '@antv/x6/es/shape/basic'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
private stencilContainer: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 800,
snapline: {
enabled: true,
sharp: true,
},
grid: {
visible: true,
},
history: true,
scroller: {
enabled: true,
width: 600,
height: 400,
pageVisible: true,
pageBreak: false,
pannable: true,
},
})
graph.centerContent()
graph.addNode({
x: 130,
y: 30,
width: 100,
height: 40,
attrs: {
label: {
text: 'rect',
fill: '#6a6c8a',
},
body: {
stroke: '#31d0c6',
strokeWidth: 2,
},
},
})
const stencil = new Stencil({
target: graph,
width: 200,
height: 300,
search: true,
collapsable: true,
grid: 1,
groups: [
{
name: 'group1',
},
{
name: 'group2',
},
],
})
this.stencilContainer.appendChild(stencil.container)
var r = new Rect({
position: { x: 10, y: 10 },
size: { width: 70, height: 40 },
attrs: {
rect: { fill: '#31D0C6', stroke: '#4B4A67', 'stroke-width': 8 },
text: { text: 'rect', fill: 'white' },
},
})
var c = new Circle({
position: { x: 100, y: 10 },
size: { width: 70, height: 40 },
attrs: {
circle: { fill: '#FE854F', 'stroke-width': 8, stroke: '#4B4A67' },
text: { text: 'ellipse', fill: 'white' },
},
})
var c2 = new Circle({
position: { x: 10, y: 70 },
size: { width: 70, height: 40 },
attrs: {
circle: { fill: '#4B4A67', 'stroke-width': 8, stroke: '#FE854F' },
text: { text: 'ellipse', fill: 'white' },
},
})
var r2 = new Rect({
position: { x: 100, y: 70 },
size: { width: 70, height: 40 },
attrs: {
rect: { fill: '#4B4A67', stroke: '#31D0C6', 'stroke-width': 8 },
text: { text: 'rect', fill: 'white' },
},
})
var r3 = new Rect({
position: { x: 10, y: 130 },
size: { width: 70, height: 40 },
attrs: {
rect: { fill: '#31D0C6', stroke: '#4B4A67', 'stroke-width': 8 },
text: { text: 'rect', fill: 'white' },
},
})
var c3 = new Circle({
position: { x: 100, y: 130 },
size: { width: 70, height: 40 },
attrs: {
circle: { fill: '#FE854F', 'stroke-width': 8, stroke: '#4B4A67' },
text: { text: 'ellipse', fill: 'white' },
},
})
stencil.load([r, c, c2, r2.clone()], 'group1')
stencil.load([c2.clone(), r2, r3, c3], 'group2')
graph.once('node:added', ({ node }) => {
console.log(node)
setTimeout(() => {
graph.undo()
setTimeout(() => {
graph.redo()
}, 2000)
}, 2000)
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
refStencil = (container: HTMLDivElement) => {
this.stencilContainer = container
}
render() {
return (
<div className="x6-graph-wrap">
<h1>Default Settings</h1>
<div
ref={this.refStencil}
style={{
position: 'absolute',
left: 32,
top: 40,
width: 200,
height: 300,
}}
/>
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,179 +0,0 @@
import React from 'react'
import { Graph, Shape } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 400,
grid: true,
connecting: {
snap: true,
allowBlank: false,
allowMulti: true,
highlight: true,
router: { name: 'manhattan' },
connector: { name: 'normal' },
connectionPoint: 'boundary',
},
})
Shape.Rect.config({
width: 100,
height: 40,
ports: {
items: [
{ group: 'left', id: '4' },
{ group: 'right', id: '2' },
{ group: 'top', id: '1' },
{ group: 'bottom', id: '3' },
],
groups: {
left: {
position: { name: 'left' },
attrs: {
portBody: {
magnet: 'active',
r: 4,
// cy: -1,
fill: 'lightblue',
stroke: 'black',
opacity: 1,
},
},
z: 0,
},
right: {
position: { name: 'right' },
attrs: {
portBody: {
magnet: 'active',
r: 4,
// cy: -1,
fill: 'lightblue',
stroke: 'black',
opacity: 1,
},
},
z: 0,
},
top: {
position: { name: 'top' },
attrs: {
portBody: {
magnet: 'active',
r: 4,
// cy: -1,
fill: 'lightblue',
stroke: 'black',
opacity: 1,
},
},
z: 0,
},
bottom: {
position: { name: 'bottom' },
attrs: {
portBody: {
magnet: 'active',
r: 4,
// cy: -1,
fill: 'lightblue',
stroke: 'black',
opacity: 1,
},
},
z: 0,
},
},
},
portMarkup: [
{
tagName: 'circle',
selector: 'portBody',
},
],
})
graph.fromJSON({
edges: [
{
source: {
cell: 'start',
port: '2',
},
target: {
cell: 'create',
port: '2',
},
attrs: {
line: {
targetMarker: {
name: 'classic',
offset: 0,
},
},
},
},
{
source: {
cell: 'create',
port: '1',
},
target: {
cell: 'end',
port: '1',
},
attrs: {
line: {
targetMarker: {
name: 'classic',
offset: 0,
},
},
},
},
],
nodes: [
{
id: 'start',
label: 'start',
type: 'start',
x: 100,
y: 100,
},
{
id: 'create',
label: 'userTask',
type: 'userTask',
x: 300,
y: 300,
},
{
id: 'end',
label: 'end',
type: 'end',
x: 170,
y: 200,
},
],
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,256 +0,0 @@
import React from 'react'
import { Button } from 'antd'
import { Graph, Edge } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component<
Example.Props,
Example.State
> {
state: Example.State = {
canRedo: false,
canUndo: false,
}
private container: HTMLDivElement
private graph: Graph
componentDidMount() {
const graph = (this.graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
panning: true,
history: {
enabled: true,
beforeAddCommand(event, args: any) {
if (args.options.ignoreHistory) {
return false
}
},
},
connecting: {
allowBlank: false,
allowNode: false,
connector: {
name: 'smooth',
},
createEdge() {
return Edge.create({
attrs: {
line: {
strokeDasharray: '5 5',
},
},
})
},
},
}))
graph.history.on('change', () => {
this.setState({
canRedo: graph.canRedo(),
canUndo: graph.canUndo(),
})
})
graph.on('edge:connected', ({ edge }) => {
edge.attr('line/strokeDasharray', null, { ignoreHistory: true })
})
graph.addNode({
x: 100,
y: 80,
width: 160,
height: 80,
label: 'hello',
ports: {
groups: {
top: {
position: 'top',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
right: {
position: 'right',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
bottom: {
position: 'bottom',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
left: {
position: 'left',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
},
items: [
{
id: 'top',
group: 'top',
},
{
id: 'right',
group: 'right',
},
{
id: 'bottom',
group: 'bottom',
},
{
id: 'left',
group: 'left',
},
],
},
})
graph.addNode({
x: 400,
y: 320,
width: 160,
height: 80,
label: 'world',
ports: {
groups: {
top: {
position: 'top',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
right: {
position: 'right',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
bottom: {
position: 'bottom',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
left: {
position: 'left',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
},
items: [
{
id: 'top',
group: 'top',
},
{
id: 'right',
group: 'right',
},
{
id: 'bottom',
group: 'bottom',
},
{
id: 'left',
group: 'left',
},
],
},
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
onUndo = () => {
this.graph.undo()
}
onRedo = () => {
this.graph.redo()
}
render() {
return (
<div className="x6-graph-wrap">
<div className="x6-graph-tools">
<Button onClick={this.onUndo} disabled={!this.state.canUndo}>
Undo
</Button>
<Button onClick={this.onRedo} disabled={!this.state.canRedo}>
Redo
</Button>
</div>
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}
// eslint-disable-next-line
export namespace Example {
export interface Props {}
export interface State {
canUndo: boolean
canRedo: boolean
}
}

View File

@ -1,185 +0,0 @@
import React from 'react'
import { Button } from 'antd'
import { Graph } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component<
Example.Props,
Example.State
> {
state: Example.State = {
canRedo: false,
canUndo: false,
}
private graph: Graph
private graphContainer: HTMLDivElement
private minimapContainer: HTMLDivElement
componentDidMount() {
const graph = (this.graph = new Graph({
container: this.graphContainer,
width: 800,
height: 600,
grid: true,
history: {
enabled: true,
beforeAddCommand(event, options) {
// 鼠标移入和移除时触发 添加 和 删除 工具,不应该添加到历时记录中
if (
event === 'cell:change:*' &&
options != null &&
options.key === 'tools'
) {
return false
}
if (event === 'cell:removed') {
const cell = options && options.cell
if (cell) {
cell.removeTools()
}
}
},
},
scroller: {
enabled: true,
pannable: true,
},
minimap: {
enabled: true,
container: this.minimapContainer,
width: 300,
height: 200,
padding: 10,
graphOptions: {
async: true,
createCellView(cell) {
if (cell.isEdge()) {
return null
}
},
},
},
}))
graph.on('cell:mouseenter', function ({ cell }) {
if (cell.isNode()) {
cell.addTools([
{
name: 'boundary',
args: {
attrs: {
fill: '#7c68fc',
stroke: '#333',
'stroke-width': 1,
'fill-opacity': 0.2,
},
},
},
{
name: 'button-remove',
args: {
x: 0,
y: 0,
offset: { x: 10, y: 10 },
},
},
])
} else {
cell.addTools(['vertices', 'segments'])
}
})
graph.on('cell:mouseleave', ({ cell }) => {
cell.removeTools()
})
graph.history.on('change', () => {
this.setState({
canRedo: graph.canRedo(),
canUndo: graph.canUndo(),
})
})
graph.on('node:click', function ({ node }) {
node.attr('body/stroke', 'orange')
})
const rect1 = graph.addNode({
x: 100,
y: 80,
width: 100,
height: 40,
label: 'hello',
})
const rect2 = graph.addNode({
x: 400,
y: 320,
width: 100,
height: 40,
label: 'world',
})
graph.addEdge({
source: rect1,
target: rect2,
})
}
refContainer = (container: HTMLDivElement) => {
this.graphContainer = container
}
refMinimap = (container: HTMLDivElement) => {
this.minimapContainer = container
}
onUndo = () => {
this.graph.undo()
}
onRedo = () => {
this.graph.redo()
}
render() {
return (
<div className="x6-graph-wrap">
<h1>Scroller</h1>
<div className="x6-graph-tools">
<Button onClick={this.onUndo} disabled={!this.state.canUndo}>
Undo
</Button>
<Button onClick={this.onRedo} disabled={!this.state.canRedo}>
Redo
</Button>
</div>
<div
ref={this.refMinimap}
style={{
position: 'absolute',
right: '50%',
top: 40,
marginRight: -720,
width: 300,
height: 200,
boxShadow: '0 0 10px 1px #e9e9e9',
}}
/>
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}
// eslint-disable-next-line
export namespace Example {
export interface Props {}
export interface State {
canUndo: boolean
canRedo: boolean
}
}

View File

@ -1,161 +0,0 @@
import React from 'react'
import ReactDom from 'react-dom'
import { Dropdown, Menu } from 'antd'
import { Graph, ToolsView, EdgeView } from '@antv/x6'
import '../index.less'
class ContextMenuTool extends ToolsView.ToolItem<
EdgeView,
ContextMenuToolOptions
> {
private knob: HTMLDivElement
render() {
super.render()
this.knob = ToolsView.createElement('div', false) as HTMLDivElement
this.knob.style.position = 'absolute'
this.container.appendChild(this.knob)
this.updatePosition(this.options)
setTimeout(() => {
this.toggleContextMenu(true)
})
return this
}
private toggleContextMenu(visible: boolean) {
ReactDom.unmountComponentAtNode(this.knob)
document.removeEventListener('mousedown', this.onMouseDown)
if (visible) {
ReactDom.render(
<Dropdown
visible={true}
trigger={['click']}
overlay={this.options.menu}
>
<a href="#" />
</Dropdown>,
this.knob,
() => {
document.addEventListener('mousedown', this.onMouseDown)
},
)
}
}
private updatePosition(pos?: { x: number; y: number }) {
const style = this.knob.style
if (pos) {
style.left = `${pos.x}px`
style.top = `${pos.y}px`
} else {
style.left = '-1000px'
style.top = '-1000px'
}
}
private onMouseDown = (e: MouseEvent) => {
console.log('')
setTimeout(() => {
this.updatePosition()
this.toggleContextMenu(false)
if (this.options.onHide) {
this.options.onHide.call(this)
}
}, 100)
}
}
ContextMenuTool.config({
tagName: 'div',
isSVGElement: false,
})
export interface ContextMenuToolOptions extends ToolsView.ToolItem.Options {
x: number
y: number
menu?: Menu | (() => Menu)
onHide?: (this: ContextMenuTool) => void
}
Graph.registerEdgeTool('contextmenu', ContextMenuTool, true)
Graph.registerNodeTool('contextmenu', ContextMenuTool, true)
const onMenuClick = (e: any) => {
console.log('menu click ', e)
}
const menu = () => (
<Menu onClick={onMenuClick}>
<Menu.Item key="1">1st menu item</Menu.Item>
<Menu.Item key="2">2nd menu item</Menu.Item>
<Menu.Item key="3">
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
3rd menu item
</a>
</Menu.Item>
<Menu.Item key="4">a danger item</Menu.Item>
</Menu>
)
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
panning: true,
})
const source = graph.addNode({
x: 40,
y: 40,
width: 100,
height: 40,
})
const target = graph.addNode({
x: 240,
y: 200,
width: 100,
height: 40,
})
graph.addEdge({
source,
target,
})
graph.on('cell:contextmenu', ({ cell, e }) => {
const p = graph.clientToGraph(e.clientX, e.clientY)
cell.addTools([
{
name: 'contextmenu',
args: {
menu,
x: p.x,
y: p.y,
onHide() {
this.cell.removeTools()
},
},
},
])
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,185 +0,0 @@
import React from 'react'
import { Button } from 'antd'
import { Graph, NodeView, DataUri } from '@antv/x6'
import '../index.less'
class SimpleNodeView extends NodeView {
protected renderMarkup() {
return this.renderJSONMarkup({
tagName: 'rect',
selector: 'body',
})
}
protected renderPorts() {}
update() {
super.update({
body: {
refWidth: '100%',
refHeight: '100%',
fill: '#31d0c6',
},
})
}
}
export default class Example extends React.Component {
private graph: Graph
private graphContainer: HTMLDivElement
private minimapContainer: HTMLDivElement
private scroller: any
componentDidMount() {
const graph = new Graph({
container: this.graphContainer,
width: 800,
height: 500,
resizing: true,
background: {
color: '#f5f5f5',
},
grid: {
visible: true,
},
selecting: {
enabled: true,
rubberband: true,
modifiers: 'shift',
},
scroller: {
enabled: true,
// width: 600,
// height: 400,
pageVisible: true,
pageBreak: true,
pannable: true,
autoResize: true,
// modifiers: 'shift',
},
minimap: {
enabled: true,
container: this.minimapContainer,
width: 300,
height: 200,
padding: 10,
graphOptions: {
async: true,
getCellView(cell) {
if (cell.isNode()) {
return SimpleNodeView
}
},
createCellView(cell) {
if (cell.isEdge()) {
return null
}
},
},
},
mousewheel: {
enabled: true,
// fixed: false,
modifiers: ['ctrl', 'meta'],
minScale: 0.5,
maxScale: 2,
},
})
this.scroller = graph.scroller.widget
const rect = graph.addNode({
x: 40,
y: 40,
width: 90,
height: 60,
})
rect.on('removed', () => {
console.log('rect was removed')
})
const circle = graph.addNode({
shape: 'circle',
x: 160,
y: 160,
width: 40,
height: 40,
})
graph.addEdge({
source: rect,
target: circle,
})
this.graph = graph
}
refContainer = (container: HTMLDivElement) => {
this.graphContainer = container
}
refMinimap = (container: HTMLDivElement) => {
this.minimapContainer = container
}
onResizeClick = () => {
this.graph.resizeGraph(200, 150)
}
onCenterClick = () => {
this.graph.center()
}
onCenterContentClick = () => {
this.graph.centerContent()
}
onZoomOutClick = () => {
this.scroller.zoom(-0.2)
}
onZoomInClick = () => {
this.scroller.zoom(0.2)
}
onZoomToFitClick = () => {
this.scroller.zoomToFit()
}
onDownload = () => {
this.graph.toPNG((datauri: string) => {
DataUri.downloadDataUri(datauri, 'chart.png')
})
}
render() {
return (
<div className="x6-graph-wrap">
<h1>Scroller</h1>
<div className="x6-graph-tools">
<Button onClick={this.onResizeClick}>Resize</Button>
<Button onClick={this.onCenterClick}>Center</Button>
<Button onClick={this.onCenterContentClick}>Center Content</Button>
<Button onClick={this.onZoomOutClick}>Zoom Out</Button>
<Button onClick={this.onZoomInClick}>Zoom In</Button>
<Button onClick={this.onZoomToFitClick}>Zoom To Fit</Button>
<Button onClick={this.onDownload}>Download</Button>
</div>
<div
ref={this.refMinimap}
style={{
position: 'absolute',
right: '50%',
top: 40,
marginRight: -720,
width: 300,
height: 200,
boxShadow: '0 0 10px 1px #e9e9e9',
}}
/>
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,100 +0,0 @@
import React from 'react'
import { Graph } from '@antv/x6'
import '../index.less'
Graph.registerNode(
'new-rect',
{
inherit: 'rect',
width: 160,
height: 40,
attrs: {
label: {
textAnchor: 'left',
refX: 0,
textWrap: {
width: 160,
height: 48,
ellipsis: true,
},
},
},
},
true,
)
const data = {
nodes: [
{
shape: 'new-rect',
id: 'node1',
x: 40,
y: 40,
attrs: {
label: {
text: 'hello-test-foo-bar-count-lint-jsvascriptjsvascriptjsvascript',
},
},
},
{
shape: 'new-rect',
id: 'node2',
x: 220,
y: 40,
attrs: {
label: {
text: 'testing测试测试测试thisisaveryveryveryveryveryverylongword jsvascriptjsvascriptjsvascript',
},
},
},
{
shape: 'new-rect',
id: 'node3',
x: 40,
y: 100,
attrs: {
label: {
text: '文字文字文字测试测试测试测试',
},
},
},
{
shape: 'new-rect',
id: 'node4',
x: 220,
y: 100,
attrs: {
label: {
text: 'asdfghjklasdfghjklasdfghjkl',
},
},
},
],
}
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 1000,
height: 800,
grid: true,
})
graph.fromJSON(data)
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,95 +0,0 @@
import React from 'react'
import { Button } from 'antd'
import { Graph } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component<
Example.Props,
Example.State
> {
private container: HTMLDivElement
private history: Graph.HistoryManager
state: Example.State = {
canRedo: false,
canUndo: false,
}
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
history: true,
})
const parent = graph.addNode({
x: 100,
y: 60,
width: 500,
height: 140,
label: 'Parent Node',
})
this.history = graph.history
this.history.on('change', () => {
this.setState({
canRedo: this.history.canRedo(),
canUndo: this.history.canUndo(),
})
})
graph.batchUpdate(() => {
const child = graph.addNode({
x: 160,
y: 100,
width: 100,
height: 40,
label: 'Drag Me',
})
parent.addChild(child)
})
}
onUndo = () => {
this.history.undo()
}
onRedo = () => {
this.history.redo()
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<h1>Default Settings</h1>
<div className="x6-graph-tools">
<Button.Group>
<Button onClick={this.onUndo} disabled={!this.state.canUndo}>
Undo
</Button>
<Button onClick={this.onRedo} disabled={!this.state.canRedo}>
Redo
</Button>
</Button.Group>
</div>
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}
// eslint-disable-next-line
export namespace Example {
export interface Props {}
export interface State {
canUndo: boolean
canRedo: boolean
}
}

View File

@ -1,81 +0,0 @@
import React from 'react'
import { Graph } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 400,
grid: true,
})
graph.addEdge({
source: { x: 300, y: 240 },
target: { x: 460, y: 240 },
attrs: {
line: {
strokeWidth: 8,
// stroke: '#13C2C1',
stroke: {
type: 'linearGradient',
stops: [
{ offset: '0%', color: '#13C2C1' },
{ offset: '100%', color: '#3366FF' },
],
},
fill: 'none',
targetMarker: {
name: 'block',
size: 15,
fill: '#6ED7D8',
offset: 0,
},
},
},
tools: ['target-arrowhead'],
})
graph.addEdge({
source: { x: 240, y: 40 },
target: { x: 40, y: 160 },
connector: 'smooth',
attrs: {
line: {
strokeWidth: 8,
// stroke: '#13C2C1',
stroke: {
type: 'linearGradient',
stops: [
{ offset: '0%', color: '#13C2C1' },
{ offset: '100%', color: '#3366FF' },
],
},
fill: 'none',
targetMarker: {
name: 'block',
size: 15,
fill: '#6ED7D8',
offset: 0,
},
},
},
tools: ['target-arrowhead'],
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,58 +0,0 @@
import React from 'react'
import { Graph } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 400,
grid: true,
})
graph.addEdge({
source: { x: 100, y: 100 },
target: { x: 400, y: 100 },
vertices: [
[160, 160],
[340, 160],
],
attrs: {
line: {
strokeWidth: 8,
// stroke: '#13C2C1',
stroke: {
type: 'linearGradient',
stops: [
{ offset: '0%', color: '#13C2C1' },
{ offset: '100%', color: '#3366FF' },
],
},
fill: 'none',
targetMarker: {
name: 'block',
size: 15,
fill: '#6ED7D8',
offset: 0,
},
},
},
tools: ['button-remove', 'vertices'],
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,61 +0,0 @@
import React from 'react'
import { Graph } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
rotating: true,
resizing: {
enabled: true,
restricted: true,
},
translating: {
restrict: -20,
},
scroller: {
enabled: true,
pannable: true,
autoResize: false,
pageVisible: true,
autoResizeOptions: {
border: 20,
},
},
})
graph.addNode({
x: 100,
y: 80,
width: 80,
height: 40,
angle: 30,
})
graph.addNode({
shape: 'ellipse',
x: 240,
y: 200,
width: 80,
height: 40,
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,44 +0,0 @@
import React from 'react'
import { Graph } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 400,
grid: true,
async: true,
})
graph.addNode({
x: 120,
y: 80,
width: 100,
height: 40,
label: 'rect',
zIndex: 10,
})
graph.addEdge({
source: { x: 10, y: 10 },
target: { x: 300, y: 200 },
zIndex: 1,
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,249 +0,0 @@
import React from 'react'
import { Graph, Edge } from '@antv/x6'
import '../index.less'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 1000,
height: 800,
grid: true,
panning: true,
connecting: {
allowBlank: false,
allowNode: false,
// sourceAnchor: 'midSide',
// targetAnchor: 'midSide',
router: {
name: 'er',
},
connector: {
name: 'rounded',
args: {
radius: 50,
},
},
createEdge({ sourceMagnet }) {
const map = {
top: 'B',
bottom: 'T',
left: 'R',
right: 'L',
}
const group = sourceMagnet.getAttribute(
'port-group',
) as keyof typeof map
return Edge.create({
router: {
name: 'er',
args: {
direction: group ? map[group] : undefined,
},
},
attrs: {
line: {
strokeDasharray: '5 5',
},
},
})
},
},
})
graph.on('edge:connected', ({ edge }) => {
graph.batchUpdate(() => {
const { port: sourcePort, ...source } =
edge.getSource() as Edge.TerminalCellData
const { port: targetPort, ...target } =
edge.getTarget() as Edge.TerminalCellData
edge.removeProp('source')
edge.removeProp('target')
edge.removeProp('router')
edge.attr('line/strokeDasharray', null)
edge.prop({
source,
target,
})
})
})
const rect1 = graph.addNode({
x: 100,
y: 80,
width: 268,
height: 100,
label: 'hello',
ports: {
groups: {
top: {
position: 'top',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
right: {
position: 'right',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
bottom: {
position: 'bottom',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
left: {
position: 'left',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
},
items: [
{
id: 'top',
group: 'top',
},
{
id: 'right',
group: 'right',
},
{
id: 'bottom',
group: 'bottom',
},
{
id: 'left',
group: 'left',
},
],
},
})
const rect2 = graph.addNode({
x: 400,
y: 320,
width: 268,
height: 100,
label: 'world',
ports: {
groups: {
top: {
position: 'top',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
right: {
position: 'right',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
bottom: {
position: 'bottom',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
left: {
position: 'left',
attrs: {
circle: {
r: 6,
magnet: true,
stroke: '#31d0c6',
strokeWidth: 2,
fill: '#fff',
},
},
},
},
items: [
{
id: 'top',
group: 'top',
},
{
id: 'right',
group: 'right',
},
{
id: 'bottom',
group: 'bottom',
},
{
id: 'left',
group: 'left',
},
],
},
})
graph.addEdge({
source: rect1,
target: rect2,
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,5 +1,7 @@
import React from 'react'
import { Graph, Node, NodeView, Point, Angle, Dom, Vector } from '@antv/x6'
import { Graph, Node, NodeView } from '@antv/x6'
import { Dom, Vector } from '@antv/x6-common'
import { Point, Angle } from '@antv/x6-geometry'
import '../index.less'
class ConveyorNode extends Node {

View File

@ -1,6 +1,7 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Graph, Dom, Shape, Node } from '@antv/x6'
import { Graph, Shape, Node } from '@antv/x6'
import { Dom } from '@antv/x6-common'
import { Tooltip } from 'antd'
import classnames from 'classnames'
import '@antv/x6-react-shape'

View File

@ -1,5 +1,6 @@
import React from 'react'
import { Graph, Color } from '@antv/x6'
import { Graph } from '@antv/x6'
import { Color } from '@antv/x6-common'
import '@antv/x6-react-shape'
import '../index.less'
import './ports.less'

View File

@ -1,5 +1,7 @@
import React from 'react'
import { Graph } from '@antv/x6'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Selection } from '@antv/x6-plugin-selection'
import '../index.less'
export default class Example extends React.Component {
@ -11,30 +13,25 @@ export default class Example extends React.Component {
width: 800,
height: 600,
grid: true,
keyboard: {
enabled: true,
global: true,
},
// resizing: {
// enabled: true,
// },
// rotating: {
// enabled: true,
// },
selecting: {
enabled: true,
rubberband: true,
multiple: true,
strict: true,
showNodeSelectionBox: true,
selectCellOnMoved: false,
useCellGeometry: true,
filter(cell) {
return cell !== a
},
// content: '123',
})
const keyboard = new Keyboard({
enabled: true,
})
const selection = new Selection({
enabled: true,
rubberband: true,
multiple: true,
strict: true,
showNodeSelectionBox: true,
selectCellOnMoved: false,
useCellGeometry: true,
filter(cell) {
return cell !== a
},
})
graph.use(keyboard)
graph.use(selection)
const a = graph.addNode({
x: 50,
@ -64,75 +61,12 @@ export default class Example extends React.Component {
graph.addEdge({ source: a, target: b })
graph.addEdge({ source: b, target: c })
// graph.toggleMultipleSelection(false)
// console.log(graph.isMultipleSelection())
// graph.on('node:selected', ({ node }) => {
// console.log(node)
// })
// graph.on('node:unselected', ({ node }) => {
// console.log(node)
// })
// graph.on('selection:changed', ({ selected, added, removed }) => {
// console.log(selected, added, removed)
// })
// graph.on('cell:selected', ({ cell }) => {
// console.log('selected', cell)
// })
// graph.on('cell:unselected', ({ cell }) => {
// console.log('unselected', cell)
// })
// graph.on('node:change:position', ({ node, options }) => {
// console.log(node, options)
// })
graph.bindKey('backspace', () => {
graph.removeCells(graph.getSelectedCells())
keyboard.bindKey('backspace', () => {
graph.removeCells(selection.getSelectedCells())
})
// graph.on('blank:mousedown', () => {
// console.log('blank:mousedown')
// })
// graph.on('blank:click', () => {
// console.log('blank:click')
// })
// graph.on('node:mousedown', args => {
// console.log('node:mousedown', args)
// })
// graph.on('node:mousemove', args => {
// console.log('node:mousemove', args)
// })
// graph.on('node:mouseup', args => {
// console.log('node:mouseup', args)
// })
// graph.on('node:click', args => {
// console.log('node:click', args)
// })
// graph.on('node:dblclick', args => {
// console.log('node:dblclick', args)
// })
// graph.on('node:contextmenu', args => {
// console.log('node:contextmenu', args)
// })
graph.select(a)
graph.select([b, c])
graph.on('cell:removed', (args) => {
console.log('cell:removed', args)
})
selection.select(a)
selection.select([b, c])
}
refContainer = (container: HTMLDivElement) => {

View File

@ -1,95 +0,0 @@
import React from 'react'
import { Graph, Markup, ObjectExt, Dom } from '@antv/x6'
import '../index.less'
Graph.registerNode('xml-node', {}, true)
const { markup, attrs } = Markup.xml2json(`
<g class="rotatable">
<g class="scalable">
<rect class="card" ref-width="100%" ref-height="100%" rx="10" ry="10" fill="#fff" stroke="#000" stroke-width="0" pointer-events="visiblePainted"/>
<image x="16" y="16" width="56" height="56" opacity="0.7"/>
</g>
<text class="rank" ref-x="0.95" ref-y="0.5" font-family="Courier New" font-size="13" text-anchor="end" text-vertical-anchor="middle"/>
<text class="name" ref-x="0.95" ref-y="0.7" font-family="Arial" font-size="14" font-weight="600" text-anchor="end"/>
<g class="btn add" ref-dx="-16" ref-y="16" event="node:add">
<circle class="add" r="10" fill="transparent" stroke="#333" stroke-width="1"/>
<text class="add" x="-5.5" y="7" font-size="20" font-weight="600" font-family="Times New Roman" stroke="#000">+</text>
</g>
<g class="btn del" ref-dx="-44" ref-y="16" event="node:delete">
<circle class="del" r="10" fill="transparent" stroke="#333" stroke-width="1"/>
<text class="del" x="-4.5" y="6" font-size="28" font-weight="600" font-family="Times New Roman" stroke="#000">-</text>
</g>
</g>
`)
const male =
'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*kUy8SrEDp6YAAAAAAAAAAAAAARQnAQ'
const female =
'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*f6hhT75YjkIAAAAAAAAAAAAAARQnAQ'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
panning: true,
})
console.log(markup, attrs)
graph.addNode({
x: 100,
y: 100,
width: 260,
height: 88,
shape: 'xml-node',
markup,
attrs: ObjectExt.merge(attrs, {
'.card': {
fill: '#31d0c6',
},
image: {
xlinkHref: Math.random() < 0.5 ? male : female,
},
'.rank': {
text: Dom.breakText('President, Ebay Global Marketplaces', {
width: 160,
height: 45,
}),
},
'.name': {
text: Dom.breakText('Devin Wenig', { width: 160, height: 45 }),
},
}),
})
graph.on('node:add', () => {
alert('add click')
})
graph.on('node:delete', () => {
alert('delete click')
})
graph.on('node:click', () => {
alert('node click')
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}

View File

@ -1,5 +1,5 @@
{
"version": "2.0.6-beta.7",
"version": "2.0.6-beta.16",
"npmClient": "yarn",
"useWorkspaces": true,
"command": {
@ -25,11 +25,5 @@
"pr(test)": ":white_check_mark: Test Case"
}
},
"packages": [
"packages/x6-common",
"packages/x6-geometry",
"packages/x6",
"packages/x6-react-shape",
"packages/x6-vue-shape"
]
"packages": ["packages/*"]
}

View File

@ -26,9 +26,8 @@
"package:inherit": "yarn package-inherit update",
"prepare": "is-ci || husky install configs/husky-config",
"precommit": "yarn lint-staged && lerna run --concurrency 1 --stream precommit",
"version": "lerna version --no-private",
"publish:latest": "lerna publish from-package --no-private --ignore-scripts",
"publish:beta": "lerna publish from-package --no-private --ignore-scripts --canary --preid beta --dist-tag=beta"
"publish:latest": "yarn build:dev && lerna publish --no-private --ignore-scripts",
"publish:beta": "yarn build:dev && lerna publish --no-private --ignore-scripts --dist-tag=beta"
},
"lint-staged": {
"**/*.{js,jsx,tsx,ts,less,md,json}": [

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-common",
"version": "2.0.6-beta.3",
"version": "2.0.6-beta.16",
"description": "Basic toolkit for x6.",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -154,9 +154,14 @@ export function contains(parent: Element, child: Element) {
)
}
export function remove(elem: Element) {
if (elem.parentNode) {
elem.parentNode.removeChild(elem)
export function remove(elem: Element | Element[] | null) {
if (elem) {
const elems = Array.isArray(elem) ? elem : [elem]
elems.forEach((item) => {
if (item.parentNode) {
item.parentNode.removeChild(item)
}
})
}
}
@ -239,3 +244,18 @@ export function isHTMLElement(elem: any): elem is HTMLElement {
)
}
}
export function children(parent: Element, className?: string) {
const matched: Element[] = []
let elem = parent.firstChild
for (; elem; elem = elem.nextSibling) {
if (elem.nodeType === 1) {
if (!className || hasClass(elem as Element, className)) {
matched.push(elem as Element)
}
}
}
return matched
}

View File

@ -19,3 +19,6 @@ export * from './transform'
// event
export * from './event'
export * from './mousewheel'
// postion
export * from './position'

View File

@ -0,0 +1,19 @@
export function offset(elem: Element) {
const rect = elem.getBoundingClientRect()
const win = elem.ownerDocument.defaultView!
return {
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset,
}
}
export function width(elem: Element) {
const rect = elem.getBoundingClientRect()
return rect.width
}
export function height(elem: Element) {
const rect = elem.getBoundingClientRect()
return rect.height
}

View File

@ -1,5 +1,5 @@
{
"version": "2.0.6-beta.2",
"version": "2.0.6-beta.16",
"name": "@antv/x6-geometry",
"description": "Geometry operations for x6.",
"main": "lib/index.js",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-keyboard",
"version": "2.0.6-beta.7",
"version": "2.0.6-beta.16",
"description": "keyboard plugin for X6.",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -3,31 +3,33 @@ import { Graph } from '@antv/x6'
import { KeyboardImpl } from './keyboard'
export class Keyboard extends Disposable {
private keyboardImpl: KeyboardImpl
public name = 'keyboard'
private keyboard: KeyboardImpl
constructor(public readonly options: KeyboardImpl.Options) {
super()
}
public init(graph: Graph) {
this.keyboard = new KeyboardImpl({
init(graph: Graph) {
this.keyboardImpl = new KeyboardImpl({
...this.options,
graph,
})
}
// #region api
isKeyboardEnabled() {
return !this.keyboard.disabled
return !this.keyboardImpl.disabled
}
enableKeyboard() {
this.keyboard.enable()
this.keyboardImpl.enable()
return this
}
disableKeyboard() {
this.keyboard.disable()
this.keyboardImpl.disable()
return this
}
@ -53,17 +55,19 @@ export class Keyboard extends Disposable {
callback: KeyboardImpl.Handler,
action?: KeyboardImpl.Action,
) {
this.keyboard.on(keys, callback, action)
this.keyboardImpl.on(keys, callback, action)
return this
}
unbindKey(keys: string | string[], action?: KeyboardImpl.Action) {
this.keyboard.off(keys, action)
this.keyboardImpl.off(keys, action)
return this
}
// #endregion
@Disposable.dispose()
dispose() {
this.keyboard.dispose()
this.keyboardImpl.dispose()
}
}

View File

@ -103,7 +103,7 @@ export class KeyboardImpl extends Disposable implements IDisablable {
}
protected isGraphEvent(e: KeyboardEvent) {
const target = (e.srcElement || e.target) as Element
const target = e.target as Element
const currentTarget = e.currentTarget as Element
if (target) {
if (

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-scroller",
"version": "2.0.6-beta.7",
"version": "2.0.6-beta.16",
"description": "scroller plugin for X6.",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -11,9 +11,9 @@ import { ScrollerImpl } from './scroller'
import { content } from './style/raw'
export class Scroller extends Disposable {
public name = 'scroller'
private graph: Graph
private scrollerImpl: ScrollerImpl
public name = 'scroller'
private get pannable() {
if (this.options) {
@ -33,6 +33,7 @@ export class Scroller extends Disposable {
public init(graph: Graph) {
this.graph = graph
CssLoader.ensure('scroller', content)
this.scrollerImpl = new ScrollerImpl({
...this.options,
graph,
@ -42,92 +43,16 @@ export class Scroller extends Disposable {
this.scrollerImpl.center()
}
private startListening() {
let eventTypes = []
const pannable = this.options.pannable
if (typeof pannable === 'object') {
eventTypes = pannable.eventTypes || []
} else {
eventTypes = ['leftMouseDown']
}
if (eventTypes.includes('leftMouseDown')) {
this.graph.on('blank:mousedown', this.preparePanning, this)
this.graph.on('node:unhandled:mousedown', this.preparePanning, this)
this.graph.on('edge:unhandled:mousedown', this.preparePanning, this)
}
if (eventTypes.includes('rightMouseDown')) {
this.onRightMouseDown = this.onRightMouseDown.bind(this)
Dom.Event.on(
this.scrollerImpl.container,
'mousedown',
this.onRightMouseDown,
)
}
}
private stopListening() {
let eventTypes = []
const pannable = this.options.pannable
if (typeof pannable === 'object') {
eventTypes = pannable.eventTypes || []
} else {
eventTypes = ['leftMouseDown']
}
if (eventTypes.includes('leftMouseDown')) {
this.graph.off('blank:mousedown', this.preparePanning, this)
this.graph.off('node:unhandled:mousedown', this.preparePanning, this)
this.graph.off('edge:unhandled:mousedown', this.preparePanning, this)
}
if (eventTypes.includes('rightMouseDown')) {
Dom.Event.off(
this.scrollerImpl.container,
'mousedown',
this.onRightMouseDown,
)
}
}
private onRightMouseDown(e: Dom.MouseDownEvent) {
if (e.button === 2 && this.allowPanning(e, true)) {
this.updateClassName(true)
this.scrollerImpl.startPanning(e)
this.scrollerImpl.once('pan:stop', () => this.updateClassName(false))
}
}
private preparePanning({ e }: { e: Dom.MouseDownEvent }) {
const allowPanning = this.allowPanning(e, true)
const selection = this.graph.getPlugin('selection') as any
const allowRubberband =
this.allowPanning(e) && selection && selection.allowRubberband(e, true)
if (allowPanning || !allowRubberband) {
this.updateClassName(true)
this.scrollerImpl.startPanning(e)
this.scrollerImpl.once('pan:stop', () => this.updateClassName(false))
}
}
private allowPanning(e: Dom.MouseDownEvent, strict?: boolean) {
return (
this.pannable && ModifierKey.isMatch(e, this.options.modifiers, strict)
)
}
private updateClassName(isPanning?: boolean) {
const container = this.scrollerImpl.container!
const pannable = Config.prefix('graph-scroller-pannable')
if (this.pannable) {
Dom.addClass(container, pannable)
container.dataset.panning = (!!isPanning).toString() // Use dataset to control scroller panning style to avoid reflow caused by changing classList
} else {
Dom.removeClass(container, pannable)
}
}
// #region api
resize(width?: number, height?: number) {
this.scrollerImpl.resize(width, height)
}
resizePage(width?: number, height?: number) {
this.scrollerImpl.updatePageSize(width, height)
}
zoom(): number
zoom(factor: number, options?: TransformManager.ZoomOptions): this
zoom(factor?: number, options?: TransformManager.ZoomOptions) {
@ -354,6 +279,94 @@ export class Scroller extends Disposable {
this.scrollerImpl.disableAutoResize()
}
autoScroll(clientX: number, clientY: number) {
this.scrollerImpl.autoScroll(clientX, clientY)
}
// #endregion
protected startListening() {
let eventTypes = []
const pannable = this.options.pannable
if (typeof pannable === 'object') {
eventTypes = pannable.eventTypes || []
} else {
eventTypes = ['leftMouseDown']
}
if (eventTypes.includes('leftMouseDown')) {
this.graph.on('blank:mousedown', this.preparePanning, this)
this.graph.on('node:unhandled:mousedown', this.preparePanning, this)
this.graph.on('edge:unhandled:mousedown', this.preparePanning, this)
}
if (eventTypes.includes('rightMouseDown')) {
this.onRightMouseDown = this.onRightMouseDown.bind(this)
Dom.Event.on(
this.scrollerImpl.container,
'mousedown',
this.onRightMouseDown,
)
}
}
protected stopListening() {
let eventTypes = []
const pannable = this.options.pannable
if (typeof pannable === 'object') {
eventTypes = pannable.eventTypes || []
} else {
eventTypes = ['leftMouseDown']
}
if (eventTypes.includes('leftMouseDown')) {
this.graph.off('blank:mousedown', this.preparePanning, this)
this.graph.off('node:unhandled:mousedown', this.preparePanning, this)
this.graph.off('edge:unhandled:mousedown', this.preparePanning, this)
}
if (eventTypes.includes('rightMouseDown')) {
Dom.Event.off(
this.scrollerImpl.container,
'mousedown',
this.onRightMouseDown,
)
}
}
protected onRightMouseDown(e: Dom.MouseDownEvent) {
if (e.button === 2 && this.allowPanning(e, true)) {
this.updateClassName(true)
this.scrollerImpl.startPanning(e)
this.scrollerImpl.once('pan:stop', () => this.updateClassName(false))
}
}
protected preparePanning({ e }: { e: Dom.MouseDownEvent }) {
const allowPanning = this.allowPanning(e, true)
const selection = this.graph.getPlugin('selection') as any
const allowRubberband =
this.allowPanning(e) && selection && selection.allowRubberband(e, true)
if (allowPanning || !allowRubberband) {
this.updateClassName(true)
this.scrollerImpl.startPanning(e)
this.scrollerImpl.once('pan:stop', () => this.updateClassName(false))
}
}
protected allowPanning(e: Dom.MouseDownEvent, strict?: boolean) {
return (
this.pannable && ModifierKey.isMatch(e, this.options.modifiers, strict)
)
}
protected updateClassName(isPanning?: boolean) {
const container = this.scrollerImpl.container!
const pannable = Config.prefix('graph-scroller-pannable')
if (this.pannable) {
Dom.addClass(container, pannable)
container.dataset.panning = (!!isPanning).toString() // Use dataset to control scroller panning style to avoid reflow caused by changing classList
} else {
Dom.removeClass(container, pannable)
}
}
@Disposable.dispose()
dispose() {
this.scrollerImpl.dispose()

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,5 @@
# `x6-plugin-selection`
> TODO: description
## Usage

View File

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

View File

@ -0,0 +1,111 @@
{
"name": "@antv/x6-plugin-selection",
"version": "2.0.6-beta.16",
"description": "selection plugin for X6.",
"main": "lib/index.js",
"module": "es/index.js",
"unpkg": "dist/x6-plugin-selection.js",
"jsdelivr": "dist/x6-plugin-selection.js",
"types": "lib/index.d.ts",
"files": [
"dist",
"es",
"lib"
],
"keywords": [
"plugin",
"selection",
"x6",
"antv"
],
"scripts": {
"clean:build": "rimraf dist es lib",
"clean:coverage": "rimraf ./test/coverage",
"clean": "run-p clean:build clean:coverage",
"lint": "eslint 'src/**/*.{js,ts}?(x)' --fix",
"build:less": "node ./scripts/style",
"build:esm": "tsc --module esnext --target es2015 --outDir ./es",
"build:cjs": "tsc --module commonjs --target es2015 --outDir ./lib",
"build:umd": "rollup -c",
"build:dev": "run-p build:less build:cjs build:esm",
"build:watch": "yarn build:esm --w",
"build:watch:esm": "yarn build:esm --w",
"build:watch:cjs": "yarn build:cjs --w",
"build": "run-p build:dev build:umd",
"prebuild": "run-s lint clean",
"coveralls": "cat ./test/coverage/lcov.info | coveralls",
"pretest": "run-p clean:coverage",
"prepare": "run-s test build",
"precommit": "lint-staged"
},
"lint-staged": {
"src/**/*.ts": [
"eslint --fix"
]
},
"inherits": [
"@antv/x6-package-json/cli.json",
"@antv/x6-package-json/eslint.json",
"@antv/x6-package-json/rollup.json"
],
"peerDependencies": {
"@antv/x6": ">=2.0.6-beta.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^20.0.0",
"@rollup/plugin-node-resolve": "^13.0.4",
"@rollup/plugin-replace": "^3.0.0",
"@rollup/plugin-typescript": "^8.2.5",
"@types/mousetrap": "^1.6.5",
"@typescript-eslint/eslint-plugin": "^4.31.0",
"@typescript-eslint/parser": "^4.31.0",
"coveralls": "^3.1.1",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-jest": "^24.4.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-react": "^7.25.1",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-unicorn": "^36.0.0",
"less": "^4.1.1",
"lint-staged": "^11.1.2",
"npm-run-all": "^4.1.5",
"postcss": "^8.3.6",
"prettier": "^2.4.0",
"pretty-quick": "^3.1.1",
"rimraf": "^3.0.2",
"rollup": "^2.56.3",
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-filesize": "^9.1.1",
"rollup-plugin-postcss": "^4.0.1",
"rollup-plugin-progress": "^1.1.2",
"rollup-plugin-terser": "^7.0.2",
"ts-node": "^10.2.1",
"tslib": "^2.3.1",
"typescript": "^4.4.3"
},
"author": {
"name": "bubkoo",
"email": "bubkoo.wy@gmail.com"
},
"contributors": [],
"license": "MIT",
"homepage": "https://github.com/antvis/x6",
"bugs": {
"url": "https://github.com/antvis/x6/issues"
},
"repository": {
"type": "git",
"url": "ssh://git@github.com/antvis/x6.git",
"directory": "packages/x6-common"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
}
}

View File

@ -0,0 +1,18 @@
import config from '../../configs/rollup-config'
export default config({
output: [
{
name: 'X6PluginSelection',
format: 'umd',
file: 'dist/x6-plugin-selection.js',
sourcemap: true,
globals: {
'@antv/x6': 'X6',
'@antv/x6-common': 'X6Common',
'@antv/x6-geometry': 'X6Geometry',
},
},
],
external: ['@antv/x6', '@antv/x6-common', '@antv/x6-geometry'],
})

View File

@ -0,0 +1,85 @@
#!/usr/bin/env node
const fs = require('fs')
const os = require('os')
const path = require('path')
const fse = require('fs-extra')
const cp = require('child_process')
const cwd = process.cwd()
const es = path.join(cwd, 'es')
const lib = path.join(cwd, 'lib')
const src = path.join(cwd, 'src')
const dist = path.join(cwd, 'dist')
function compile(source, target) {
let cmd = './node_modules/.bin/lessc'
if (os.type() === 'Windows_NT') {
cmd = path.join(cwd, './node_modules/.bin/lessc.cmd')
}
cp.execFileSync(cmd, [source, target])
}
compile(path.join(src, 'index.less'), path.join(es, 'index.css'))
compile(path.join(src, 'index.less'), path.join(lib, 'index.css'))
compile(path.join(src, 'index.less'), path.join(dist, 'scroller.css'))
function toCSSPath(source) {
const dir = path.dirname(source)
const file = `${path.basename(source, '.less')}.css`
return path.join(dir, file)
}
// Copy less files
function processLessInDir(dir) {
const stat = fs.statSync(dir)
if (stat) {
if (stat.isDirectory()) {
fs.readdir(dir, (err, files) => {
files.forEach((file) => {
processLessInDir(path.join(dir, file))
})
})
} else {
const ext = path.extname(dir)
if (ext === '.less' || ext === '.css') {
fse.copySync(dir, path.join(es, path.relative(src, dir)))
fse.copySync(dir, path.join(lib, path.relative(src, dir)))
}
if (ext === '.less') {
let source = path.join(es, path.relative(src, dir))
let target = toCSSPath(source)
compile(dir, target)
source = path.join(lib, path.relative(src, dir))
target = toCSSPath(source)
compile(dir, target)
}
}
}
}
function makeStyleModule() {
const source = path.join(dist, 'scroller.css')
const target = path.join(src, 'style/raw.ts')
const content = fs.readFileSync(source, { encoding: 'utf8' })
const prev = fs.existsSync(target)
? fs.readFileSync(target, { encoding: 'utf8' })
: null
const curr = `/* eslint-disable */
/**
* Auto generated file, do not modify it!
*/
export const content = \`${content}\`
`
if (prev !== curr) {
fs.writeFileSync(target, curr)
}
}
processLessInDir(src)
makeStyleModule()

View File

@ -0,0 +1,78 @@
@selection-prefix-cls: ~'x6-widget-selection';
.@{selection-prefix-cls} {
position: absolute;
display: none;
width: 0;
height: 0;
touch-action: none;
&-rubberband {
display: block;
overflow: visible;
opacity: 0.3;
}
&-selected {
display: block;
}
&-box {
cursor: move;
}
&-inner[data-selection-length='0'],
&-inner[data-selection-length='1'] {
display: none;
}
&-content {
position: absolute;
top: 100%;
right: -20px;
left: -20px;
margin-top: 30px;
padding: 6px;
line-height: 14px;
text-align: center;
border-radius: 6px;
&:empty {
display: none;
}
}
}
// theme
.@{selection-prefix-cls} {
&-rubberband {
background-color: #3498db;
border: 2px solid #2980b9;
}
&-box {
box-sizing: content-box !important;
margin-top: -4px;
margin-left: -4px;
padding-right: 4px;
padding-bottom: 4px;
border: 2px dashed #feb663;
box-shadow: 2px 2px 5px #d3d3d3;
}
&-inner {
box-sizing: content-box !important;
margin-top: -8px;
margin-left: -8px;
padding-right: 12px;
padding-bottom: 12px;
border: 2px solid #feb663;
box-shadow: 2px 2px 5px #d3d3d3;
}
&-content {
color: #fff;
font-size: 10px;
background-color: #6a6b8a;
}
}

View File

@ -0,0 +1,487 @@
import {
Disposable,
ModifierKey,
CssLoader,
Dom,
ObjectExt,
} from '@antv/x6-common'
import { Cell, EventArgs, Graph } from '@antv/x6'
import { SelectionImpl } from './selection'
import { content } from './style/raw'
export class Selection extends Disposable {
private graph: Graph
private selectionImpl: SelectionImpl
private readonly options: Selection.Options
private movedMap = new WeakMap<Cell, boolean>()
private unselectMap = new WeakMap<Cell, boolean>()
public name = 'selection'
private get rubberbandDisabled() {
return this.options.enabled !== true || this.options.rubberband !== true
}
public get disabled() {
return this.options.enabled !== true
}
public get length() {
return this.selectionImpl.length
}
public get cells() {
return this.selectionImpl.cells
}
constructor(options: Selection.Options) {
super()
this.options = ObjectExt.merge({}, Selection.defaultOptions, options)
}
public init(graph: Graph) {
this.graph = graph
CssLoader.ensure('scroller', content)
this.selectionImpl = new SelectionImpl({
...this.options,
graph,
})
this.startListening()
}
// #region api
isSelectionEnabled() {
return !this.disabled
}
enableSelection() {
this.enable()
return this
}
disableSelection() {
this.disable()
return this
}
toggleSelection(enabled?: boolean) {
if (enabled != null) {
if (enabled !== this.isSelectionEnabled()) {
if (enabled) {
this.enableSelection()
} else {
this.disableSelection()
}
}
} else if (this.isSelectionEnabled()) {
this.disableSelection()
} else {
this.enableSelection()
}
return this
}
isMultipleSelection() {
return this.isMultiple()
}
enableMultipleSelection() {
this.enableMultiple()
return this
}
disableMultipleSelection() {
this.disableMultiple()
return this
}
toggleMultipleSelection(multiple?: boolean) {
if (multiple != null) {
if (multiple !== this.isMultipleSelection()) {
if (multiple) {
this.enableMultipleSelection()
} else {
this.disableMultipleSelection()
}
}
} else if (this.isMultipleSelection()) {
this.disableMultipleSelection()
} else {
this.enableMultipleSelection()
}
return this
}
isSelectionMovable() {
return this.options.movable !== false
}
enableSelectionMovable() {
this.selectionImpl.options.movable = true
return this
}
disableSelectionMovable() {
this.selectionImpl.options.movable = false
return this
}
toggleSelectionMovable(movable?: boolean) {
if (movable != null) {
if (movable !== this.isSelectionMovable()) {
if (movable) {
this.enableSelectionMovable()
} else {
this.disableSelectionMovable()
}
}
} else if (this.isSelectionMovable()) {
this.disableSelectionMovable()
} else {
this.enableSelectionMovable()
}
return this
}
isRubberbandEnabled() {
return !this.rubberbandDisabled
}
enableRubberband() {
if (this.rubberbandDisabled) {
this.options.rubberband = true
}
return this
}
disableRubberband() {
if (!this.rubberbandDisabled) {
this.options.rubberband = false
}
return this
}
toggleRubberband(enabled?: boolean) {
if (enabled != null) {
if (enabled !== this.isRubberbandEnabled()) {
if (enabled) {
this.enableRubberband()
} else {
this.disableRubberband()
}
}
} else if (this.isRubberbandEnabled()) {
this.disableRubberband()
} else {
this.enableRubberband()
}
return this
}
isStrictRubberband() {
return this.selectionImpl.options.strict === true
}
enableStrictRubberband() {
this.selectionImpl.options.strict = true
return this
}
disableStrictRubberband() {
this.selectionImpl.options.strict = false
return this
}
toggleStrictRubberband(strict?: boolean) {
if (strict != null) {
if (strict !== this.isStrictRubberband()) {
if (strict) {
this.enableStrictRubberband()
} else {
this.disableStrictRubberband()
}
}
} else if (this.isStrictRubberband()) {
this.disableStrictRubberband()
} else {
this.enableStrictRubberband()
}
return this
}
setRubberbandModifiers(modifiers?: string | ModifierKey[] | null) {
this.setModifiers(modifiers)
}
setSelectionFilter(filter?: Selection.Filter) {
this.setFilter(filter)
return this
}
setSelectionDisplayContent(content?: Selection.Content) {
this.setContent(content)
return this
}
isSelectionEmpty() {
return this.isEmpty()
}
cleanSelection(options?: Selection.SetOptions) {
this.clean(options)
return this
}
resetSelection(
cells?: Cell | string | (Cell | string)[],
options?: Selection.SetOptions,
) {
this.reset(cells, options)
return this
}
getSelectedCells() {
return this.cells
}
getSelectedCellCount() {
return this.length
}
isSelected(cell: Cell | string) {
return this.selectionImpl.isSelected(cell)
}
select(
cells: Cell | string | (Cell | string)[],
options: Selection.AddOptions = {},
) {
const selected = this.getCells(cells)
if (selected.length) {
if (this.isMultiple()) {
this.selectionImpl.select(selected, options)
} else {
this.reset(selected.slice(0, 1), options)
}
}
return this
}
unselect(
cells: Cell | string | (Cell | string)[],
options: Selection.RemoveOptions = {},
) {
this.selectionImpl.unselect(this.getCells(cells), options)
return this
}
// #endregion
protected startListening() {
this.graph.on('blank:mousedown', this.onBlankMouseDown, this)
this.graph.on('blank:click', this.onBlankClick, this)
this.graph.on('cell:mousemove', this.onCellMouseMove, this)
this.graph.on('cell:mouseup', this.onCellMouseUp, this)
this.selectionImpl.on('box:mousedown', this.onBoxMouseDown, this)
}
protected stopListening() {
this.graph.off('blank:mousedown', this.onBlankMouseDown, this)
this.graph.off('blank:click', this.onBlankClick, this)
this.graph.off('cell:mousemove', this.onCellMouseMove, this)
this.graph.off('cell:mouseup', this.onCellMouseUp, this)
this.selectionImpl.off('box:mousedown', this.onBoxMouseDown, this)
}
protected onBlankMouseDown({ e }: EventArgs['blank:mousedown']) {
const allowGraphPanning = this.graph.panning.allowPanning(e, true)
const scroller = this.graph.getPlugin('scroller') as any
const allowScrollerPanning = scroller && scroller.allowPanning(e, true)
if (
this.allowRubberband(e, true) ||
(this.allowRubberband(e) && !allowScrollerPanning && !allowGraphPanning)
) {
this.startRubberband(e)
}
}
protected onBlankClick() {
this.clean()
}
protected allowRubberband(e: Dom.MouseDownEvent, strict?: boolean) {
return (
!this.rubberbandDisabled &&
ModifierKey.isMatch(e, this.options.modifiers, strict)
)
}
protected allowMultipleSelection(e: Dom.MouseDownEvent | Dom.MouseUpEvent) {
return (
this.isMultiple() &&
ModifierKey.isMatch(e, this.options.multipleSelectionModifiers)
)
}
protected onCellMouseMove({ cell }: EventArgs['cell:mousemove']) {
this.movedMap.set(cell, true)
}
protected onCellMouseUp({ e, cell }: EventArgs['cell:mouseup']) {
const options = this.options
let disabled = this.disabled
if (!disabled && this.movedMap.has(cell)) {
disabled = options.selectCellOnMoved === false
if (!disabled) {
disabled = options.selectNodeOnMoved === false && cell.isNode()
}
if (!disabled) {
disabled = options.selectEdgeOnMoved === false && cell.isEdge()
}
}
if (!disabled) {
if (!this.allowMultipleSelection(e)) {
this.reset(cell)
} else if (this.unselectMap.has(cell)) {
this.unselectMap.delete(cell)
} else if (this.isSelected(cell)) {
this.unselect(cell)
} else {
this.select(cell)
}
}
this.movedMap.delete(cell)
}
protected onBoxMouseDown({
e,
cell,
}: SelectionImpl.EventArgs['box:mousedown']) {
if (!this.disabled) {
if (this.allowMultipleSelection(e)) {
this.unselect(cell)
this.unselectMap.set(cell, true)
}
}
}
protected isEmpty() {
return this.length <= 0
}
protected getCells(cells: Cell | string | (Cell | string)[]) {
return (Array.isArray(cells) ? cells : [cells])
.map((cell) =>
typeof cell === 'string' ? this.graph.getCellById(cell) : cell,
)
.filter((cell) => cell != null)
}
protected reset(
cells?: Cell | string | (Cell | string)[],
options: Selection.SetOptions = {},
) {
this.selectionImpl.reset(cells ? this.getCells(cells) : [], options)
return this
}
protected clean(options: Selection.SetOptions = {}) {
this.selectionImpl.clean(options)
return this
}
protected enable() {
if (this.disabled) {
this.options.enabled = true
}
return this
}
protected disable() {
if (!this.disabled) {
this.options.enabled = false
}
return this
}
protected startRubberband(e: Dom.MouseDownEvent) {
if (!this.rubberbandDisabled) {
this.selectionImpl.startSelecting(e)
}
return this
}
protected isMultiple() {
return this.options.multiple !== false
}
protected enableMultiple() {
this.options.multiple = true
return this
}
protected disableMultiple() {
this.options.multiple = false
return this
}
protected setModifiers(modifiers?: string | ModifierKey[] | null) {
this.options.modifiers = modifiers
return this
}
protected setContent(content?: Selection.Content) {
this.selectionImpl.setContent(content)
return this
}
protected setFilter(filter?: Selection.Filter) {
this.selectionImpl.setFilter(filter)
return this
}
@Disposable.dispose()
dispose() {
this.stopListening()
this.selectionImpl.dispose()
}
}
export namespace Selection {
export interface Options extends SelectionImpl.CommonOptions {
enabled?: boolean
}
export type Filter = SelectionImpl.Filter
export type Content = SelectionImpl.Content
export type SetOptions = SelectionImpl.SetOptions
export type AddOptions = SelectionImpl.AddOptions
export type RemoveOptions = SelectionImpl.RemoveOptions
export const defaultOptions: Partial<SelectionImpl.Options> = {
rubberband: false,
rubberNode: true,
rubberEdge: false, // next version will set to true
pointerEvents: 'auto',
multiple: true,
multipleSelectionModifiers: ['ctrl', 'meta'],
movable: true,
strict: false,
useCellGeometry: false,
selectCellOnMoved: false,
selectNodeOnMoved: false,
selectEdgeOnMoved: false,
following: true,
content: null,
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/* eslint-disable */
/**
* Auto generated file, do not modify it!
*/
export const content = `.x6-widget-selection {
position: absolute;
display: none;
width: 0;
height: 0;
touch-action: none;
}
.x6-widget-selection-rubberband {
display: block;
overflow: visible;
opacity: 0.3;
}
.x6-widget-selection-selected {
display: block;
}
.x6-widget-selection-box {
cursor: move;
}
.x6-widget-selection-inner[data-selection-length='0'],
.x6-widget-selection-inner[data-selection-length='1'] {
display: none;
}
.x6-widget-selection-content {
position: absolute;
top: 100%;
right: -20px;
left: -20px;
margin-top: 30px;
padding: 6px;
line-height: 14px;
text-align: center;
border-radius: 6px;
}
.x6-widget-selection-content:empty {
display: none;
}
.x6-widget-selection-rubberband {
background-color: #3498db;
border: 2px solid #2980b9;
}
.x6-widget-selection-box {
box-sizing: content-box !important;
margin-top: -4px;
margin-left: -4px;
padding-right: 4px;
padding-bottom: 4px;
border: 2px dashed #feb663;
box-shadow: 2px 2px 5px #d3d3d3;
}
.x6-widget-selection-inner {
box-sizing: content-box !important;
margin-top: -8px;
margin-left: -8px;
padding-right: 12px;
padding-bottom: 12px;
border: 2px solid #feb663;
box-shadow: 2px 2px 5px #d3d3d3;
}
.x6-widget-selection-content {
color: #fff;
font-size: 10px;
background-color: #6a6b8a;
}
`

View File

@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.json"
}

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-react-components",
"version": "2.0.6-beta.2",
"version": "2.0.6-beta.16",
"description": "React components for building x6 editors",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-react-shape",
"version": "2.0.6-beta.7",
"version": "2.0.6-beta.16",
"description": "X6 shape for rendering react components.",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-vue-shape",
"version": "2.0.6-beta.7",
"version": "2.0.6-beta.16",
"description": "X6 shape for rendering vue components.",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6",
"version": "2.0.6-beta.7",
"version": "2.0.6-beta.16",
"description": "JavaScript diagramming library that uses SVG and HTML for rendering.",
"main": "lib/index.js",
"module": "es/index.js",
@ -65,8 +65,8 @@
"@antv/x6-package-json/rollup.json"
],
"dependencies": {
"@antv/x6-common": "^2.0.6-beta.3",
"@antv/x6-geometry": "^2.0.6-beta.2"
"@antv/x6-common": "^2.0.6-beta.16",
"@antv/x6-geometry": "^2.0.6-beta.16"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^20.0.0",

View File

@ -1,8 +1,8 @@
import { Basecoat, NumberExt, Dom, KeyValue } from '@antv/x6-common'
import { Point, Rectangle } from '@antv/x6-geometry'
import { Model, Collection, Cell, Node, Edge } from '../model'
import { CellView } from '../view'
import * as Registry from '../registry'
import { Base } from './base'
import { GraphView } from './view'
import { EventArgs } from './events'
import { CSSManager as Css } from './css'
@ -17,7 +17,7 @@ import { Renderer as ViewRenderer } from '../renderer'
import { DefsManager as Defs } from './defs'
import { CoordManager as Coord } from './coord'
import { HighlightManager as Highlight } from './highlight'
import { CellView } from '../view'
import { SizeManager as Size } from './size'
export class Graph extends Basecoat<EventArgs> {
private installedPlugins: Set<Graph.Plugin> = new Set()
@ -36,6 +36,7 @@ export class Graph extends Basecoat<EventArgs> {
public readonly panning: Panning
public readonly mousewheel: Wheel
public readonly virtualRender: VirtualRender
public readonly size: Size
public get container() {
return this.options.container
@ -64,6 +65,7 @@ export class Graph extends Basecoat<EventArgs> {
this.panning = new Panning(this)
this.mousewheel = new Wheel(this)
this.virtualRender = new VirtualRender(this)
this.size = new Size(this)
}
// #region model
@ -1132,20 +1134,6 @@ export class Graph extends Basecoat<EventArgs> {
// #endregion
}
export namespace Graph {
/* eslint-disable @typescript-eslint/no-unused-vars */
export import View = GraphView
export import Renderer = ViewRenderer
export import MouseWheel = Wheel
export import BaseManager = Base
export import DefsManager = Defs
export import GridManager = Grid
export import CoordManager = Coord
export import TransformManager = Transform
export import HighlightManager = Highlight
export import BackgroundManager = Background
}
export namespace Graph {
export interface Options extends GraphOptions.Manual {}
}

View File

@ -236,7 +236,7 @@ export namespace Options {
*/
restrict:
| boolean
| OptionItem<CellView, Rectangle.RectangleLike | number | null>
| OptionItem<CellView | null, Rectangle.RectangleLike | number | null>
}
export interface Embedding {

View File

@ -0,0 +1,37 @@
import { SizeSensor } from '@antv/x6-common'
import { Base } from './base'
export class SizeManager extends Base {
private getSensorTarget() {
const autoResize = this.options.autoResize
if (autoResize) {
if (typeof autoResize === 'boolean') {
return this.graph.container.parentElement
}
return autoResize as HTMLElement
}
}
protected init() {
const autoResize = this.options.autoResize
if (autoResize) {
const target = this.getSensorTarget()
if (target) {
SizeSensor.bind(target, () => {
const width = target.offsetWidth
const height = target.offsetHeight
this.resize(width, height)
})
}
}
}
resize(width?: number, height?: number) {
this.graph.transform.resize(width, height)
}
@Base.dispose()
dispose() {
SizeSensor.clear(this.graph.container)
}
}

View File

@ -18,6 +18,7 @@ wait
lerna run build --stream --scope @antv/x6-vue-shape \
--scope @antv/x6-react-shape \
--scope @antv/x6-plugin-keyboard \
--scope @antv/x6-plugin-scroller
--scope @antv/x6-plugin-scroller \
--scope @antv/x6-plugin-selection
wait

View File

@ -8,7 +8,6 @@
"build": "umi build",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
"gitHooks": {