Attributes
X6 provides a wide range of built-in attributes as well as methods for custom attributes.
Built-in Attributes
ref
Specifies a selector pointing to an element, which serves as the reference element.
graph.addNode({
...,
markup: [
{
tagName: 'rect',
selector: 'body,'
},
{
tagName: 'rect',
selector: 'custom,'
}
],
attrs: {
body: {
width: 100,
height: 50,
},
// The length and width of the custom element are half of the body
custom: {
ref: 'body',
refWidth: 0.5,
refHeight: 0.5,
}
}
})
refX
Sets the x coordinate of the element. The target x coordinate is relative to the x coordinate of the top-left corner of the element referenced by ref.
- When its value is between
[0, 1]or a percentage (e.g.,50%), it represents the relative offset of the targetxcoordinate as a percentage of the reference element’s width from the referencexcoordinate. For example,refX: 0.5means the targetxcoordinate is offset to the right by 50% of the reference width from the referencexcoordinate. - When its value is
<0or>1, it represents the absolute offset of the targetxcoordinate from the referencexcoordinate. For example,refX: 20means the targetxcoordinate is offset 20px to the right from the referencexcoordinate.
refX2
Same as refX, used when both relative and absolute offsets need to be specified simultaneously.
{
refX: '50%',
refX2: 20,
}
The above code indicates that the target x coordinate is offset 50% of the reference element’s width to the right from the reference x coordinate, plus an additional 20px.
refY
Sets the y coordinate of the element. The target y coordinate is relative to the y coordinate of the top-left corner of the element referenced by ref (reference y coordinate).
- When its value is between
[0, 1]or a percentage (e.g.,50%), it represents the relative offset of the targetycoordinate as a percentage of the reference element’s height from the referenceycoordinate. For example,refY: 0.5means the targetycoordinate is offset downward by 50% of the reference height from the referenceycoordinate. - When its value is
<0or>1, it represents the absolute offset of the targetycoordinate from the referenceycoordinate. For example,refY: 20means the targetycoordinate is offset 20px downward from the referenceycoordinate.
refY2
Same as refY, used when both relative and absolute offsets need to be specified simultaneously.
{
refY: '50%',
refY2: 20,
}
The above code indicates that the target y coordinate is offset 50% of the reference element’s height downward from the reference y coordinate, plus an additional 20px.
refDx
Sets the x coordinate of the element. The target x coordinate is relative to the x coordinate of the bottom-right corner of the element referenced by ref (reference x coordinate).
- When its value is between
[0, 1]or a percentage (e.g.,50%), it represents the relative offset of the targetxcoordinate as a percentage of the reference element’s width from the referencexcoordinate. For example,refDx: 0.5means the targetxcoordinate is offset to the right by 50% of the reference width from the referencexcoordinate. - When its value is
<0or>1, it represents the absolute offset of the targetxcoordinate from the referencexcoordinate. For example,refDx: 20means the targetxcoordinate is offset 20px to the right from the referencexcoordinate.
refDy
Sets the y coordinate of the element. The target y coordinate is relative to the y coordinate of the bottom-right corner of the element referenced by ref (reference y coordinate).
- When its value is between
[0, 1]or a percentage (e.g.,50%), it represents the relative offset of the targetycoordinate as a percentage of the reference element’s height from the referenceycoordinate. For example,refDy: 0.5means the targetycoordinate is offset downward by 50% of the reference height from the referenceycoordinate. - When its value is
<0or>1, it represents the absolute offset of the targetycoordinate from the referenceycoordinate. For example,refDy: 20means the targetycoordinate is offset 20px downward from the referenceycoordinate.
refWidth
Sets the width of the element. The width is calculated relative to the width of the element referenced by ref (reference width).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it represents the element’s width as a percentage of the reference width. For example,refWidth: 0.75means the element’s width is 75% of the reference width. - When its value is
<0or>1, it represents how much the element’s width is decreased or increased based on the reference width. For example,refWidth: 20means the element is 20px wider than the reference element.
Note
This attribute only applies to elements that support width and height, such as the <rect> element.
refWidth2
Same as refWidth, used when both absolute and relative widths need to be specified simultaneously.
{
refWidth: '75%',
refWidth2: 20,
}
The above code indicates that the target width is 75% of the reference width plus an additional 20px.
refHeight
Sets the height of the element. The height is calculated relative to the height of the element referenced by ref (reference height).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it represents the element’s height as a percentage of the reference height. For example,refHeight: 0.75means the element’s height is 75% of the reference height. - When its value is
<0or>1, it represents how much the element’s height is decreased or increased based on the reference height. For example,refHeight: 20means the element is 20px taller than the reference element.
Note
This attribute only applies to elements that support width and height, such as the <rect> element.
refHeight2
Same as refHeight, used when both absolute and relative heights need to be specified simultaneously.
{
refHeight: '75%',
refHeight2: 20,
}
The above code indicates that the target height is 75% of the reference height plus an additional 20px.
refCx
Sets the center x coordinate of the element, i.e., the native cx attribute. The target value is calculated relative to the width of the element referenced by ref (reference width).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it represents the element’scxas a percentage of the reference width. For example,refCx: 0.75means the element’s centerxcoordinate is at 75% of the reference width. - When its value is
<0or>1, it represents how much the element’scxis decreased or increased based on the reference width. For example,refCx: 20means the element’s centerxcoordinate is at the reference width plus 20px.
Note
This attribute only applies to elements that support cx and cy attributes, such as the <ellipse> element.
refCy
Sets the center y coordinate of the element, i.e., the native cy attribute. The target value is calculated relative to the height of the element referenced by ref (reference height).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it represents the element’scyas a percentage of the reference height. For example,refCy: 0.75means the element’s centerycoordinate is at 75% of the reference height. - When its value is
<0or>1, it represents how much the element’scyis decreased or increased based on the reference height. For example,refCy: 20means the element’s centerycoordinate is at the reference height plus 20px.
Note
This attribute only applies to elements that support cx and cy attributes, such as the <ellipse> element.
refRx
Sets the rx attribute of the element. The target value is calculated relative to the width of the element referenced by ref (reference width).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it represents the element’srxas a percentage of the reference width. For example,refRx: 0.75means the element’srxis 75% of the reference width. - When its value is
<0or>1, it represents how much the element’srxis decreased or increased based on the reference width. For example,refRx: 20means the element’srxis the reference width plus 20px.
Note
This attribute only applies to elements that support rx and ry attributes, such as the <rect> element.
refRy
Sets the ry attribute of the element. The target value is calculated relative to the height of the element referenced by ref (reference height).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it represents the element’sryas a percentage of the reference height. For example,refRy: 0.75means the element’sryis 75% of the reference height. - When its value is
<0or>1, it represents how much the element’sryis decreased or increased based on the reference height. For example,refRy: 20means the element’sryis the reference height plus 20px.
Note
This attribute only applies to elements that support rx and ry attributes, such as the <rect> element.
refRCircumscribed
Sets the r attribute of the element. The target value is relative to the diagonal length of the element referenced by ref (reference length).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it representsras a percentage of the reference length. For example,refRCircumscribed: 0.75meansris 75% of the reference length. - When its value is
<0or>1, it represents how muchris decreased or increased based on the reference length. For example,refRCircumscribed: 20meansris the reference length plus 20px.
Note
This attribute only applies to elements that support the r attribute, such as the <rect> element.
refRInscribed
Alias: refR
Sets the r attribute of the element. The target value is relative to the minimum of the width and height of the element referenced by ref (reference length).
- When its value is between
[0, 1]or a percentage (e.g.,75%), it representsras a percentage of the reference length. For example,refRInscribed: 0.75meansris 75% of the reference length. - When its value is
<0or>1, it represents how muchris decreased or increased based on the reference length. For example,refRInscribed: 20meansris the reference length plus 20px.
Note
This attribute only applies to elements that support the r attribute, such as the <rect> element.
refDKeepOffset
Sets the d attribute of the <path> element. It scales the original pathData to make the target <path> element the same size as the element referenced by ref, and translates the original pathData to align the starting point of the target <path> element with the starting point of the element referenced by ref.
At the same time, the offset of the provided pathData will be preserved, which means that if the top-left corner of the provided pathData is not at the coordinate origin 0, 0, this offset will be preserved when the <path> element is rendered on the canvas.
import { Graph, Node } from '@antv/x6'
const Path = Node.define({
markup: [{ tagName: 'path' }],
attrs: {
path: {
refDKeepOffset: 'M 10 10 30 10 30 30 z', // path offset is 10,10
fill: 'red',
stroke: 'black',
},
},
})
const container = document.getElementById('container')!
const graph = new Graph({
container,
width: 800,
height: 80,
grid: true,
})
const path = new Path().resize(40, 40).addTo(graph)
const view = graph.findView(path)
console.log(view.findOne('path').getAttribute('d'))
// 'M 10 10 50 10 50 50 z'
refDResetOffset
Alias: refD
Sets the d attribute of the <path> element. It scales the original pathData to make the target <path> element the same size as the element referenced by ref, and translates the original pathData to align the starting point of the target <path> element with the starting point of the element referenced by ref.
At the same time, the offset of the provided pathData will be removed, which means that if the top-left corner of the provided pathData is not at the coordinate origin 0, 0, it will also be translated to the origin, and when the <path> element is rendered on the canvas, it will be strictly aligned with the reference element.
import { Graph, Node } from '@antv/x6'
const Path = Node.define({
markup: [{ tagName: 'path' }],
attrs: {
path: {
refDResetOffset: 'M 10 10 30 10 30 30 z', // path offset is 10,10
fill: 'red',
stroke: 'black',
},
},
})
const container = document.getElementById('container')!
const graph = new Graph({
container,
width: 800,
height: 80,
grid: true,
})
const path = new Path().resize(40, 40).addTo(graph)
const view = graph.findView(path)
console.log(view.findOne('path').getAttribute('d'))
// 'M 0 0 40 0 40 40 z'
resetOffset
When the resetOffset property value is true, the point matrix will be translated so that the top-left corner of the matrix is at the origin.
path.attr({
path: {
d: 'M 10 10 20 20',
resetOffset: true, // The d attribute value after translation is "M 0 0 10 10"
},
})
refPointsKeepOffset
Sets the points attribute of <polygon> or <polyline> elements by scaling the original point matrix to make the target element the same size as the reference element specified by ref, and translating the original point matrix to align the starting coordinates of the target element with the starting coordinates of the reference element specified by ref.
At the same time, the offset of the point matrix will be preserved, which means that if the top-left corner of the point matrix is not at the coordinate origin 0, 0, this offset will be preserved when the element is rendered on the canvas.
import { Graph, Node } from '@antv/x6'
const Polygon = Node.define({
markup: [{ tagName: 'polygon' }],
attrs: {
polygon: {
refPointsKeepOffset: '10,10 30,10 30,30', // points offset is 10,10
fill: 'red',
stroke: 'black',
},
},
})
const container = document.getElementById('container')!
const graph = new Graph({
container,
width: 800,
height: 80,
grid: true,
})
const polygon = new Polygon().resize(40, 40).addTo(graph)
const view = graph.findView(polygon)
console.log(view.findOne('polygon').getAttribute('points'))
// '10,10 50,10 50,50'
refPointsResetOffset
Alias: refPoints
Sets the points attribute of <polygon> or <polyline> elements by scaling the original point matrix to make the target element the same size as the reference element specified by ref, and translating the original point matrix to align the starting coordinates of the target element with the starting coordinates of the reference element specified by ref.
At the same time, the offset of the point matrix will be removed, which means that if the top-left corner of the point matrix is not at the coordinate origin 0, 0, it will be translated to the origin simultaneously. When the <path> element is rendered on the canvas, it will be strictly aligned with the reference element.
import { Graph, Node } from '@antv/x6'
const Polygon = Node.define({
markup: [{ tagName: 'polygon' }],
attrs: {
polygon: {
refPointsResetOffset: '10,10 30,10 30,30', // points offset is 10,10
fill: 'red',
stroke: 'black',
},
},
})
const container = document.getElementById('container')!
const graph = new Graph({
container,
width: 800,
height: 80,
grid: true,
})
const polygon = new Polygon().resize(40, 40).addTo(graph)
const view = graph.findView(polygon)
console.log(view.findOne('polygon').getAttribute('points'))
// '100,0 40,0 40,40'
xAlign
The horizontal alignment of the element with its x coordinate.
'left'The left side of the target element aligns withx.'middle'The center of the target element aligns withx.'right'The right side of the target element aligns withx.
yAlign
The vertical alignment of the element with its y coordinate.
'top'The top of the target element aligns withy.'middle'The center of the target element aligns withy.'bottom'The bottom of the target element aligns withy.
import './index.less'
import { createRoot } from 'react-dom/client'
import React from 'react'
import { Graph, Cell } from '@antv/x6'
import { Settings, State } from './settings.tsx'
export default class Example extends React.Component {
private container: HTMLDivElement
private node: Cell
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 400,
height: 250,
background: {
color: '#F2F7FA',
},
})
this.node = graph.addNode({
x: 60,
y: 60,
width: 280,
height: 120,
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'path',
selector: 'hLine',
},
{
tagName: 'path',
selector: 'vLine',
},
{
tagName: 'rect',
selector: 'ref',
},
{
tagName: 'circle',
selector: 'dot',
},
{
tagName: 'text',
selector: 'label',
},
],
attrs: {
body: {
refWidth: '100%',
refHeight: '100%',
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
},
dot: {
r: 3,
fill: '#8f8f8f',
stroke: 'none',
refX: 0.5,
refY: 0.5,
},
ref: {
width: 70,
height: 30,
refX: 0.5,
refY: 0.5,
// xAlign: 'middle',
// yAlign: 'middle',
fill: '#8f8f8f',
stroke: '#8f8f8f',
},
label: {
fontSize: 14,
fill: '#333333',
fontFamily: 'Arial, helvetica, sans-serif',
},
hLine: {
refY: 0.5,
d: 'M -30 0 310 0',
stroke: '#8f8f8f',
strokeDasharray: '5 5',
},
vLine: {
refX: 0.5,
d: 'M 0 -30 0 150',
stroke: '#8f8f8f',
strokeDasharray: '5 5',
},
},
})
}
onAttrsChanged = (attrs: State) => {
this.node.attr({
ref: attrs,
hLine: { refY: attrs.refY },
vLine: { refX: attrs.refX },
} as any)
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="attrs-x-align-app">
<div className="app-left">
<Settings onChange={this.onAttrsChanged} />
</div>
<div ref={this.refContainer} className="app-content" />
</div>
)
}
}
const root = createRoot(document.getElementById('container')!)
root.render(<Example />)
window.addEventListener('pagehide', () => root.unmount(), { once: true })
.attrs-x-align-app {
display: flex;
border: 1px solid #f0f0f0;
padding: 16px 8px;
font-family: sans-serif;
.app-left {
bottom: 0;
width: 336px;
padding: 0 8px;
}
.app-content {
flex: 1;
margin-right: 8px;
margin-left: 8px;
box-shadow: 0 0 10px 1px #e9e9e9;
}
.ant-card {
box-shadow: 0 0 10px 1px #e9e9e9;
}
.ant-card-head-title {
text-align: center;
}
.ant-row {
margin: 16px 0;
text-align: left;
}
.slider-value {
display: inline-block;
margin-left: 8px;
padding: 3px 7px;
color: #333;
font-size: 12px;
line-height: 1.25;
background: #eee;
border-radius: 10px;
}
}import React from 'react'
import { Radio, Slider, Card, Row, Col } from 'antd'
export interface Props {
onChange: (state: State) => void
}
export interface State {
refX: number
refY: number
xAlign?: string
yAlign?: string
}
export class Settings extends React.Component<Props, State> {
state: State = {
refX: 0.5,
refY: 0.5,
xAlign: 'left',
yAlign: 'top',
}
notifyChange() {
this.props.onChange(this.state)
}
onRefXChanged = (refX: number) => {
this.setState({ refX }, () => {
this.notifyChange()
})
}
onRefYChanged = (refY: number) => {
this.setState({ refY }, () => {
this.notifyChange()
})
}
onXAlignChange = (e: any) => {
this.setState(
{
xAlign: e.target.value,
},
() => {
this.notifyChange()
},
)
}
onYAlignChange = (e: any) => {
this.setState(
{
yAlign: e.target.value,
},
() => {
this.notifyChange()
},
)
}
render() {
return (
<Card title="Attrs" size="small" bordered={false} style={{ width: 320 }}>
<Row align="middle">
<Col span={5}>refX</Col>
<Col span={14}>
<Slider
min={0}
max={0.99}
step={0.01}
value={this.state.refX}
onChange={this.onRefXChanged}
/>
</Col>
<Col span={1} offset={1}>
<div className="slider-value">
{(this.state.refX * 100).toFixed(0)}%
</div>
</Col>
</Row>
<Row align="middle">
<Col span={5}>refY</Col>
<Col span={14}>
<Slider
min={0}
max={0.99}
step={0.01}
value={this.state.refY}
onChange={this.onRefYChanged}
/>
</Col>
<Col span={1} offset={1}>
<div className="slider-value">
{(this.state.refY * 100).toFixed(0)}%
</div>
</Col>
</Row>
<Row align="middle">
<Col span={5}>xAlign</Col>
<Col span={19}>
<Radio.Group
onChange={this.onXAlignChange}
value={this.state.xAlign}
>
<Radio value={'left'}>Left</Radio>
<Radio value={'middle'}>Middle</Radio>
<Radio value={'right'}>Right</Radio>
</Radio.Group>
</Col>
</Row>
<Row align="middle">
<Col span={5}>yAlign</Col>
<Col span={19}>
<Radio.Group
onChange={this.onYAlignChange}
value={this.state.yAlign}
>
<Radio value={'top'}>Top</Radio>
<Radio value={'middle'}>Middle</Radio>
<Radio value={'bottom'}>Bottom</Radio>
</Radio.Group>
</Col>
</Row>
</Card>
)
}
}fill
When the provided fill attribute value is an object, it indicates using a gradient fill; otherwise, it uses a string color fill.
rect.attr('body/fill', {
type: 'linearGradient',
stops: [
{ offset: '0%', color: '#E67E22' },
{ offset: '20%', color: '#D35400' },
{ offset: '40%', color: '#E74C3C' },
{ offset: '60%', color: '#C0392B' },
{ offset: '80%', color: '#F39C12' },
],
})
filter
When the provided filter attribute value is an object, it indicates using a custom filter; otherwise, it uses the native string form (e.g., "url(#myfilter)").
rect.attr('body/filter', {
name: 'dropShadow',
args: {
dx: 2,
dy: 2,
blur: 3,
},
})
stroke
When the provided stroke attribute value is an object, it indicates using a gradient fill; otherwise, it uses a string color fill. The usage is the same as the fill attribute.
style
Applies inline CSS styles to the specified element using jQuery’s css() method.
html
Sets the innerHTML of the specified element using jQuery’s html() method.
title
Adds a <title> child element to the specified element. The <title> element does not affect the rendering result but only adds a descriptive explanation.
rect.attr('body/title', 'Description of the rectangle')
text
Only applicable to <text> elements, used to set the text content. If the provided text is a single line (does not contain newline characters '\n'), the text is directly set as the content of the <text> element; otherwise, a <tspan> element is created for each line of text and then added to the <text> element.
textWrap
Only applicable to <text> elements, used to set the text content. Unlike the text attribute, this attribute automatically adds line breaks to the text, making the provided text completely enclosed within the bounding box of the reference element.
Its attribute value is a simple object, specifying the text content through text. Optional width and height options can be provided to adjust the size of the element. When negative, it indicates reducing the corresponding width or height (equivalent to setting a padding margin for the text); when positive, it increases the corresponding width or height; when a percentage, it indicates how much percentage of the reference element’s width or height.
When the provided text exceeds the display range, the text will be automatically truncated. If the ellipsis option is set to true, an ellipsis ... will be added at the end of the truncated text.
By default, English words will be truncated. If you don’t want a complete word to be truncated, you can set breakWord: false. In this case, to display the complete word, the text may exceed the width range.
textWrap: {
text: 'lorem ipsum dolor sit amet consectetur adipiscing elit',
width: -10, // Width reduced by 10px
height: '50%', // Height is half of the reference element's height
ellipsis: true, // Automatically add ellipsis when text exceeds display range
breakWord: true, // Whether to truncate words
}
import './index.less'
import { createRoot } from 'react-dom/client'
import * as React from 'react'
import { Graph } from '@antv/x6'
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
background: {
color: '#F2F7FA',
},
})
graph.addNode({
x: 40,
y: 40,
width: 160,
height: 48,
attrs: {
body: {
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
rx: 5,
ry: 5,
},
label: {
textAnchor: 'left',
refX: 8,
text: 'hello test foo bar lint css jsvascript typescript',
textWrap: {
width: 144,
height: 40,
ellipsis: true,
},
},
},
})
graph.addNode({
x: 240,
y: 40,
width: 160,
height: 48,
attrs: {
body: {
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
rx: 5,
ry: 5,
},
label: {
textAnchor: 'left',
refX: 8,
text: 'hello test foo bar 中文字符 lint css jsvascript typescript',
textWrap: {
width: 144,
height: 40,
ellipsis: true,
},
},
},
})
graph.addNode({
x: 440,
y: 40,
width: 160,
height: 48,
attrs: {
body: {
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
rx: 5,
ry: 5,
},
label: {
textAnchor: 'left',
refX: 8,
text: 'hello-test-foo-bar-lint-css-jsvascript-typescript',
textWrap: {
width: 144,
height: 40,
ellipsis: true,
},
},
},
})
graph.addNode({
x: 40,
y: 128,
width: 160,
height: 48,
attrs: {
body: {
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
rx: 5,
ry: 5,
},
label: {
textAnchor: 'left',
refX: 8,
text: 'Thisissomeveryveryverylong word. Words will break according to usual rules.',
textWrap: {
width: 144,
height: 40,
ellipsis: true,
},
},
},
})
graph.addNode({
x: 240,
y: 128,
width: 160,
height: 48,
attrs: {
body: {
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
rx: 5,
ry: 5,
},
label: {
textAnchor: 'left',
refX: 8,
text: 'Thisissomeveryveryverylong word. Words will break according to usual rules.',
textWrap: {
width: 144,
height: 40,
ellipsis: true,
breakWord: false,
},
},
},
})
graph.addNode({
x: 440,
y: 128,
width: 160,
height: 48,
attrs: {
body: {
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
rx: 5,
ry: 5,
},
label: {
textAnchor: 'left',
refX: 8,
text: 'hello test foo bar lint css jsvascript typescript',
textWrap: {
width: 144,
height: 20,
ellipsis: true,
},
},
},
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="attrs-text-wrap-app">
<div ref={this.refContainer} className="app-content" />
</div>
)
}
}
const root = createRoot(document.getElementById('container')!)
root.render(<Example />)
window.addEventListener('pagehide', () => root.unmount(), { once: true })
.attrs-text-wrap-app {
display: flex;
width: 100%;
border: 1px solid #f0f0f0;
padding: 16px 8px;
font-family: sans-serif;
.app-content {
flex: 1;
height: 216px;
margin-right: 8px;
margin-left: 8px;
box-shadow: 0 0 10px 1px #e9e9e9;
}
}textPath
Only applicable to <text> elements, used to render text along a path.
When the provided attribute value is a string, it indicates that the text is rendered along the path represented by the string (pathData).
When the provided attribute value is an object, you can specify the rendering path of the text through the d option, or specify an SVGPathElement element in a node/edge through the selector option, supporting CSS selectors and selectors defined in Markup. You can also specify the position of the text on the path through the startOffset option, for example, 50% indicates that the text is at 50% along the path, and 20 indicates that the text is 20px offset from the start of the path.
lineHeight
Only applicable to <text> elements, used to specify the line height of the text.
textVerticalAnchor
Only applicable to <text> elements, the vertical alignment of the element with its y coordinate.
'top'The top of the target element aligns withy.'middle'The center of the target element aligns withy.'bottom'The bottom of the target element aligns withy.
import './index.less'
import { createRoot } from 'react-dom/client'
import * as React from 'react'
import { Graph, Cell } from '@antv/x6'
import { Settings, State } from './settings.tsx'
export default class Example extends React.Component {
private container: HTMLDivElement
private node: Cell
componentDidMount() {
const graph = new Graph({
container: this.container,
background: {
color: '#F2F7FA',
},
})
this.node = graph.addNode({
x: 120,
y: 80,
width: 200,
height: 80,
markup: [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'path',
selector: 'hLine',
},
{
tagName: 'path',
selector: 'vLine',
},
{
tagName: 'rect',
selector: 'bg',
},
{
tagName: 'text',
selector: 'label',
},
{
tagName: 'circle',
selector: 'dot',
},
],
attrs: {
body: {
refWidth: '100%',
refHeight: '100%',
fill: '#ffffff',
stroke: '#8f8f8f',
strokeWidth: 1,
},
dot: {
r: 2,
fill: '#8f8f8f',
stroke: 'none',
refX: 0.5,
refY: 0.5,
},
bg: {
ref: 'label',
fill: '#8f8f8f',
stroke: '#8f8f8f',
rx: 2,
ry: 2,
refWidth: 1,
refHeight: 1,
refX: 0,
refY: 0,
},
label: {
fontSize: 14,
refX: 0.5,
refY: 0.5,
textAnchor: 'start',
textVerticalAnchor: 'top',
fill: '#fff',
stroke: '#fff',
fontFamily: 'Arial, helvetica, sans-serif',
text: 'Hello World',
},
hLine: {
refY: 0.5,
d: 'M -40 0 240 0',
stroke: '#8f8f8f',
strokeDasharray: '5 5',
},
vLine: {
refX: 0.5,
d: 'M 0 -40 0 120',
stroke: '#8f8f8f',
strokeDasharray: '5 5',
},
},
})
}
onGridChanged = (attrs: State) => {
this.node.attr({
label: attrs,
hLine: { refY: attrs.refY },
vLine: { refX: attrs.refX },
} as any)
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
render() {
return (
<div className="attrs-text-anchor-app">
<div className="app-left">
<Settings onChange={this.onGridChanged} />
</div>
<div ref={this.refContainer} className="app-content" />
</div>
)
}
}
const root = createRoot(document.getElementById('container')!)
root.render(<Example />)
window.addEventListener('pagehide', () => root.unmount(), { once: true })
.attrs-text-anchor-app {
display: flex;
border: 1px solid #f0f0f0;
padding: 16px 8px;
font-family: sans-serif;
.app-left {
bottom: 0;
width: 336px;
padding: 0 8px;
}
.app-content {
flex: 1;
margin-right: 8px;
margin-left: 8px;
box-shadow: 0 0 10px 1px #e9e9e9;
}
.ant-card {
box-shadow: 0 0 10px 1px #e9e9e9;
}
.ant-card-head-title {
text-align: center;
}
.ant-row {
margin: 16px 0;
text-align: left;
}
.slider-value {
display: inline-block;
margin-left: 8px;
padding: 3px 7px;
color: #333;
font-size: 12px;
line-height: 1.25;
background: #eee;
border-radius: 10px;
}
}import React from 'react'
import { Radio, Slider, Card, Row, Col } from 'antd'
export interface Props {
onChange: (state: State) => void
}
export interface State {
refX: number
refY: number
textAnchor?: string
textVerticalAnchor?: string
}
export class Settings extends React.Component<Props, State> {
state: State = {
refX: 0.5,
refY: 0.5,
textAnchor: 'start',
textVerticalAnchor: 'top',
}
notifyChange() {
this.props.onChange(this.state)
}
onRefXChanged = (refX: number) => {
this.setState({ refX }, () => {
this.notifyChange()
})
}
onRefYChanged = (refY: number) => {
this.setState({ refY }, () => {
this.notifyChange()
})
}
onTextAnchorAlignChange = (e: any) => {
this.setState(
{
textAnchor: e.target.value,
},
() => {
this.notifyChange()
},
)
}
onTextVerticalAnchorAlignChange = (e: any) => {
this.setState(
{
textVerticalAnchor: e.target.value,
},
() => {
this.notifyChange()
},
)
}
render() {
return (
<Card title="Attrs" size="small" bordered={false} style={{ width: 320 }}>
<Row align="middle">
<Col span={5}>refX</Col>
<Col span={14}>
<Slider
min={0}
max={0.99}
step={0.01}
value={this.state.refX}
onChange={this.onRefXChanged}
/>
</Col>
<Col span={1} offset={1}>
<div className="slider-value">
{(this.state.refX * 100).toFixed(0)}%
</div>
</Col>
</Row>
<Row align="middle">
<Col span={5}>refY</Col>
<Col span={14}>
<Slider
min={0}
max={0.99}
step={0.01}
value={this.state.refY}
onChange={this.onRefYChanged}
/>
</Col>
<Col span={1} offset={1}>
<div className="slider-value">
{(this.state.refY * 100).toFixed(0)}%
</div>
</Col>
</Row>
<Row align="middle">
<Col>textAnchor</Col>
</Row>
<Row align="middle">
<Col span={19} offset={5}>
<Radio.Group
onChange={this.onTextAnchorAlignChange}
value={this.state.textAnchor}
>
<Radio value={'start'}>Start</Radio>
<Radio value={'middle'}>Middle</Radio>
<Radio value={'end'}>end</Radio>
</Radio.Group>
</Col>
</Row>
<Row align="middle">
<Col>textVerticalAnchor</Col>
</Row>
<Row align="middle">
<Col span={19} offset={5}>
<Radio.Group
onChange={this.onTextVerticalAnchorAlignChange}
value={this.state.textVerticalAnchor}
>
<Radio value={'top'}>Top</Radio>
<Radio value={'middle'}>Middle</Radio>
<Radio value={'bottom'}>Bottom</Radio>
</Radio.Group>
</Col>
</Row>
</Card>
)
}
}connection
Only applicable to the <path> element of edges. When this attribute is true, it indicates that the edge will be rendered on this element, i.e., setting the d of this element to the pathData of the edge.
edge.attr('pathSelector', {
connection: true,
stroke: 'red',
fill: 'none',
})
It also supports an object with stubs and reserve options.
-
When
reverseisfalse:- When
stubsis positive, it indicates the length of the rendered start and end portions. For example,connection: { stubs: 20 }means only the first20pxand last20pxof the connection are rendered, and the rest is not rendered. - When
stubsis negative, it indicates the length of the middle missing (not rendered) portion. For example,connection: { stubs: -20 }means there is a20pxgap in the middle of the connection that is not rendered.
- When
-
When
reverseistrue:- When
stubsis positive, it indicates the length of the start and end portions that are not rendered. For example,connection: { stubs: 20 }means the first20pxand last20pxare not rendered. - When
stubsis negative, it indicates the length of the middle portion. For example,connection: { stubs: -20 }means only the middle20pxis rendered.
- When
edge.attr('pathSelector', {
connection: { stubs: -20, reverse: true },
})
atConnectionLengthKeepGradient
Alias: atConnectionLength
Moves the specified element in the edge to the position at the specified offset and automatically rotates the element so that its direction is consistent with the slope of the edge at that position.
- When positive, it indicates the offset from the start point of the edge.
- When negative, it indicates the offset from the end point of the edge.
edge.attr('rectSelector', {
atConnectionLengthKeepGradient: 30,
// atConnectionLength: 30,
width: 10,
height: 10,
fill: 'red',
})
atConnectionLengthIgnoreGradient
Move the specified element in the edge to the position at the specified offset, ignoring the direction of the edge. This means it will not automatically rotate the element like the atConnectionLengthKeepGradient property.
- When positive, it represents the offset from the start point of the edge.
- When negative, it represents the offset from the end point of the edge.
edge.attr('rectSelector', {
atConnectionLengthIgnoreGradient: 30,
width: 10,
height: 10,
fill: 'red',
})
atConnectionRatioKeepGradient
Alias: atConnectionRatio
Moves the specified element in the edge to the specified ratio position [0, 1], and automatically rotates the element to keep its direction consistent with the slope of the edge at that position.
edge.attr('rectSelector', {
atConnectionRatioKeepGradient: 0.5,
// atConnectionRatio: 0.5,
width: 10,
height: 10,
fill: 'red',
})
atConnectionRatioIgnoreGradient
Moves the specified element in the edge to the specified ratio position [0, 1], ignoring the direction of the edge, i.e., it will not automatically rotate the element like the atConnectionRatioKeepGradient property.
edge.attr('rectSelector', {
atConnectionRatioIgnoreGradient: 0.5,
width: 10,
height: 10,
fill: 'red',
})
sourceMarker
Applicable to all <path> elements, adds an SVG element (such as a start arrow) at the start point of the path and automatically rotates the element to keep it consistent with the path direction. For more details, please refer to this tutorial.
edge.attr('connection/sourceMarker', {
tagName: 'circle',
fill: '#666',
stroke: '#333',
r: 5,
cx: 5,
})
targetMarker
Applicable to all <path> elements, adds an SVG element (such as an end arrow) at the end point of the path and automatically rotates the element to keep it consistent with the path direction. For more details, please refer to this tutorial.
Note
This element is initially rotated by 180 degrees, and then the rotation angle is automatically adjusted to be consistent with the direction of the path. For example, for a horizontal straight line, if we specify a left-pointing arrow for its start point, we can also specify the same arrow for its end point, and this arrow will automatically point to the right side (automatically rotated by 180 degrees).
vertexMarker
Applicable to all <path> elements, used in the same way as sourceMarker, adds additional elements at all vertex positions of the <path> element.
magnet
When the magnet attribute is true, it indicates that the element can be connected, i.e., it can be used as the start or end point of a connection during the connection process, similar to a connection port.
port
Specifies a port ID for elements marked as magnet. When an edge connects to this element, this ID will be saved in the source or target of the edge.
- If it’s a string, the string will be used as the port ID.
- If it’s an object, the
idproperty value of the object will be used as the port ID.
event
Customizes a click event on the specified element, and then you can add a callback for this event on the Graph.
node.attr({
// Represents a delete button, clicking it will delete the node
image: {
event: 'node:delete',
xlinkHref: 'trash.png',
width: 20,
height: 20,
},
})
// Bind event callback, delete the node when triggered
graph.on('node:delete', ({ view, e }) => {
e.stopPropagation()
view.cell.remove()
})
xlinkHref
Alias for the xlink:href attribute, for example:
node.attr({
image: {
xlinkHref: 'xxx.png',
},
})
xlinkShow
Alias for the xlink:show attribute.
xlinkType
Alias for the xlink:type attribute.
xlinkTitle
Alias for the xlink:title attribute.
xlinkArcrole
Alias for the xlink:arcrole attribute.
xmlSpace
Alias for the xml:space attribute.
xmlBase
Alias for the xml:base attribute.
xmlLang
Alias for the xml:lang attribute.
registry
We provide two methods, register and unregister, on the registry object to register and delete special attributes.
register
register(entities: { [name: string]: Definition }, force?: boolean): void
register(name: string, entity: Definition, force?: boolean): Definition
Registers custom attributes.
unregister
unregister(name: string): Definition | null
Deletes registered attributes.
At the same time, we mount the register and unregister methods as two static methods of Graph: Graph.registerAttr and Graph.unregisterAttr. It is recommended to use these two static methods to register and delete special attributes.
Definition
In the internal implementation, we convert special attributes into attributes that the browser can recognize, so theoretically, the value of special attributes can be of any type, and the definition of special attributes also supports multiple forms.
String
Defines aliases for native attributes. For example, the definition of the special attribute xlinkHref is actually defining a more easily written alias for the xlink:href attribute.
// Definition
Graph.registerAttr('xlinkHref', 'xlink:href')
// Usage
node.attr({
image: {
xlinkHref: 'xxx.png',
},
})
Before continuing to introduce attribute definitions, let’s understand the attribute qualification qualify function. Only attribute values that pass the qualification function’s judgment will be processed by special attributes. For example, the stroke attribute is only treated as a special attribute (using gradient color to fill the border) when its value is of Object type. Let’s look at the definition of the qualification function.
type QualifyFunction = (
this: CellView, // View of the node/edge
val: ComplexAttrValue, // Current attribute value
options: {
elem: Element // Element to which the current attribute is applied
attrs: ComplexAttrs // Key-value pairs of attributes applied to this element
cell: Cell // Node/edge
view: CellView // View of the node/edge
},
) => boolean // Returns true if it passes the qualification function's judgment
For example, the definition of the stroke attribute is as follows:
export const stroke: Attr.Definition = {
qualify(val) {
// Only trigger special attribute processing logic when the attribute value is an object.
return ObjectExt.isPlainObject(val)
},
set(stroke, { view }) {
return `url(#${view.graph.defineGradient(stroke as any)})`
},
}
set
Sets the attribute definition, suitable for most scenarios.
export interface SetDefinition {
qualify?: QualifyFunction // Qualification function
set: (
this: CellView, // View of the node/edge
val: ComplexAttrValue, // Current attribute value
options: {
refBBox: Rectangle // Bounding box of the reference element, or a rectangle representing the position and size of the node when there is no reference element
elem: Element // Element to which the current attribute is applied
attrs: ComplexAttrs // Key-value pairs of attributes applied to this element
cell: Cell // Node/edge
view: CellView // View of the node/edge
},
) => SimpleAttrValue | SimpleAttrs | void
}
When the set method returns a string or number, it means to use the return value as the value of the special attribute. This approach is usually used to extend the definition of native attributes, such as the stroke and fill attributes that support gradient color filling.
// stroke attribute definition
export const stroke: Attr.SetDefinition = {
qualify: ObjectExt.isPlainObject,
set(stroke, { view }) {
// Returns a string, the return value is used as the attribute value of the stroke attribute.
return `url(#${view.graph.defineGradient(stroke as any)})`
},
}
// Using the stroke attribute
node.attr({
rect: {
stroke: {...},
},
})
When the set method returns a simple object, this object is applied to the corresponding element as attribute key-value pairs, such as the sourceMarker and targetMarker attributes.
export const sourceMarker: Attr.SetDefinition = {
qualify: ObjectExt.isPlainObject,
set(marker: string | JSONObject, { view, attrs }) {
// Returns a simple object, the return value is applied to the corresponding element as attribute key-value pairs.
return {
'marker-start': createMarker(marker, view, attrs),
}
},
}
When the set method doesn’t have a return value, it indicates that the property assignment is completed within the method itself, such as the html attribute.
export const html: Attr.Definition = {
set(html, { view, elem }) {
// No return value, property assignment is completed within the method
view.$(elem).html(`${html}`)
},
}
offset
Offset property definition.
export interface OffsetDefinition {
qualify?: QualifyFunction // Qualification function
offset: (
this: CellView, // View of the node/edge
val: ComplexAttrValue, // Current attribute value
options: {
refBBox: Rectangle // Bounding box of the reference element, if no reference element, use the rectangle represented by the node's position and size
elem: Element // Element to which the current attribute is applied
attrs: ComplexAttrs // Key-value pairs of attributes applied to the element
cell: Cell // Node/edge
view: CellView // View of the node/edge
},
) => Point.PointLike // Returns absolute offset
}
Returns a Point.PointLike object representing absolute offsets in x and y directions, like the xAlign attribute.
export const xAlign: Attr.OffsetDefinition = {
offset(alignment, { refBBox }) {
...
// Returns the absolute offset on the x-axis
return { x, y: 0 }
},
}
position
Position attribute definition.
export interface PositionDefinition {
qualify?: QualifyFunction // Qualification function
offset: (
this: CellView, // View of the node/edge
val: ComplexAttrValue, // Current attribute value
options: {
refBBox: Rectangle // Bounding box of the reference element, if no reference element, use the rectangle represented by the node's position and size
elem: Element // Element to which the current attribute is applied
attrs: ComplexAttrs // Key-value pairs of attributes applied to the element
cell: Cell // Node/edge
view: CellView // View of the node/edge
},
) => Point.PointLike // Returns absolute positioning coordinates
}
Returns absolute positioning coordinates relative to the node, like the refX and refDx attributes.
export const refX: Attr.PositionDefinition = {
position(val, { refBBox }) {
...
// Returns the absolute positioning on the x-axis
return { x, y: 0 }
},
}