Cell

阅读时间约 40 分钟

Cell 是 NodeEdge 的基类,包含节点和边的通用属性和方法定义,如属性样式、可见性、业务数据等,并且在实例化、样式定制、默认选项、自定义选项等方面具有相同的行为。

constructor

new Cell(metadata?: Cell.Metadata)

其中 Cell.Metadata 包含节点和边的通用选项,详细配置如下表:

选项类型默认值必选描述
idstring节点/边的唯一标识,推荐使用具备业务意义的 ID,默认使用自动生成的 UUID。
markupMarkup节点/边的 SVG/HTML 片段。
attrsAttr.CellAttrs节点/边属性样式。
shapestring渲染节点/边的图形。节点对应的默认值为 'rect',边对应的默认值为 'edge'
viewstring渲染节点/边的视图。
zIndexnumber节点/边在画布中的层级,默认根据节点/边添加顺序自动确定。
visiblebooleantrue节点/边是否可见。
parentstring父节点。
childrenstring[]子节点/边。
toolsToolItem | ToolItem[] | Tools工具选项。
dataany节点/边关联的业务数据。

id

id 是节点/边的唯一标识,推荐使用具备业务意义的 ID,默认使用自动生成的 UUID。

markup

markup 指定了渲染节点/边时使用的 SVG/HTML 片段,使用 JSON 格式描述。例如内置节点 Shape.Rectmarkup 定义如下:

{
  markup: [
    {
      tagName: 'rect',
      selector: 'body',
    }, 
    {
      tagName: 'text',
      selector: 'label',
    },
  ],
}

表示该节点内部包含 <rect><text> 两个 SVG 元素,渲染到页面之后,节点对应的 SVG 元素看起来像下面这样。

<g data-cell-id="c2e1dd06-15c6-43a4-987a-712a664b8f85" class="x6-cell x6-node" transform="translate(40,40)">
  <rect fill="#fff" stroke="#000" stroke-width="2" fill-opacity="0.5" width="100" height="40"></rect>
  <text font-size="14" xml:space="preserve" fill="#333" text-anchor="middle" font-family="Arial, helvetica, sans-serif" transform="matrix(1,0,0,1,50,20)">
    <tspan dy="0.3em" class="v-line">rect</tspan>
  </text>
</g>

通过上面的介绍,我们大致了解了 Markup 的结构,下面我们将详细介绍 Markup 定义。

interface Markup {
  tagName: string
  ns?: string
  selector?: string
  groupSelector?: string | string[]
  attrs?: { [key: string]: string | number }
  style?: { [key: string]: string | number }
  className?: string | string[]
  textContent?: string
  children?: Markup[]
}
选项类型默认值必选描述
tagNamestringSVG/HTML 元素标签名。
nsstring"http://www.w3.org/2000/svg"SVG/HTML 元素命名空间。
selectorstring-该元素的选择器(唯一),通过选择器来定位该元素或为该元素指定属性样式。
groupSelectorstring-该元素的群组选择器,可以同时为该群组对应的多个元素指定样式。
attrsAttr.SimpleAttrs-该元素的默认属性键值对。
styleJQuery.PlainObject<string | number>-该元素的行内样式键值对。
classNamestring-该元素的 CSS 样式名。
textContentstring-该元素的文本内容。
childrenMarkup[]-嵌套的子元素。

tagName

通过 tagName 指定需要创建哪种 SVG/HTML 元素。

ns

该元素的命名空间。需要与 tagName 指定的的元素类型对应,默认使用 SVG 元素命名空间 "http://www.w3.org/2000/svg"

  • SVG 元素命名空间为 "http://www.w3.org/2000/svg"
  • HTML 元素的命名空间为 "http://www.w3.org/1999/xhtml"

selector

该元素的唯一选择器,通过选择器为该元素指定属性样式。例如,为内置节点 Shape.Rect 指定 <rect><text> 元素的属性样式:

const rect = new Shape.Rect({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  attrs: {
    // 指定 rect 元素的样式
    body: { 
      stroke: '#000', // 边框颜色
      fill: '#fff',   // 填充颜色
    },
    // 指定 text 元素的样式
    label: { 
      text: 'rect', // 文字
      fill: '#333', // 文字颜色
    },
  },
})

groupSelector

该元素的群组选择器,通过群组选择器可以为该群组关联的多个元素指定样式。例如,下面 Markup 中两个 <rect> 具备相同的 groupSelector'group1'

{
  markup: [
    {
      tagName: 'rect',
      selector: 'body',
      groupSelector: 'group1',
    }, 
    {
      tagName: 'rect',
      selector: 'wrap',
      groupSelector: 'group1',
    }, 
    {
      tagName: 'text',
      selector: 'label',
    },
  ],
}

创建节点时,我们可以像下面这样来指定群组样式:

new SomeNode({
  attrs: { 
    group1: {
      fill: '#2ECC71',
    },
  },
})

attrs

该元素的默认属性键值对,通常用于定义那些不变的通用属性,这些默认属性也可以在实例化节点时被覆盖。需要注意的是 markup 中的 attrs 属性只支持原生的 SVG 属性,也就是说 X6 的自定义属性在这里不可用。

例如,我们为内置节点 Shape.Rect<rect><text> 元素指定了如下默认属性:

{
  markup: [
    {
      tagName: 'rect',
      selector: 'body',
      attrs: {
        fill: '#fff',
        stroke: '#000',
        strokeWidth: 2,
      }
    }, 
    {
      tagName: 'text',
      selector: 'label',
      attrs: {
        fill: '#333',
        textAnchor: 'middle',
        textVerticalAnchor: 'middle',
      }
    },
  ],
}

style

该元素的行内样式键值对。

className

该元素的 CSS 样式名。

textContent

该元素的文本内容。

children

嵌套的子元素。

attrs

属性选项 attrs 是一个复杂对象,该对象的 Key 是节点 Markup 定义中元素的选择器(selector),对应的值是应用到该 SVG 元素的 SVG 属性值(如 fillstroke),如果你对 SVG 属性还不熟悉,可以参考 MDN 提供的填充和边框入门教程。

例如,内置节点 Shape.Rect 的 Markup 定义了 'body'(代表 <rect> 元素) 和 'label'(代表 <text> 元素) 两个选择器,我们可以像下面这样为该节点中的元素指定属性样式:

const rect = new Shape.Rect({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  attrs: { 
    body: {
      fill: '#2ECC71',
      stroke: '#000',
    },
    label: {
      text: 'rect',
      fill: '#333',
      fontSize: 13,
    },
  },
})

节点渲染到画布后的 DOM 结构看起来像下面这样:

<g data-cell-id="3ee1452c-6d75-478d-af22-88e03c6d513b" class="x6-cell x6-node" transform="translate(40,40)">
  <rect fill="#2ECC71" stroke="#000" stroke-width="2" width="100" height="40"></rect>
  <text font-size="13" xml:space="preserve" fill="#333" text-anchor="middle" font-family="Arial, helvetica, sans-serif" transform="matrix(1,0,0,1,50,20)">
    <tspan dy="0.3em" class="v-line">
      rect
    </tspan>
  </text>
</g>

另外,我们还可以使用 CSS 选择器来指定节点样式,这样我们就不用记住预定义的选择器名称,只需要根据渲染后的 DOM 结构来定义样式即可。使用 CSS 选择器时需要注意,指定的 CSS 选择器可能选中多个元素,这时对应的属性样式将同时应用到多个元素上。

const rect = new Shape.Rect({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  attrs: { 
    rect: { // 使用 rect 这个 css 选择器替代预定义的 body 选择器
      fill: '#2ECC71',
      stroke: '#000',
    },
    text: { // 使用 text 这个 css 选择器替代预定义的 label 选择器
      text: 'rect',
      fill: '#333',
      fontSize: 13,
    },
  },
})

值得一提的是,支持使用小驼峰(camelCase)格式的属性名,如 'fontSize',这就避免了 'font-size' 这种属性名作为对象 Key 时需要加引号的麻烦。

除了标准的 SVG 属性,我们在 X6 中还定义了一系列特殊属性,详情请参考如何使用特殊属性如何自定义属性。另外,我们还可以使用 CSS 来定制样式,节点和边渲染到画布后分别有 'x6-node''x6-edge' 两个样式名,默认的样式定义参考这里。例如,我们可以像下面这样来指定节点中 <rect> 元素的样式:

.x6-node rect {
  fill: #2ECC71;
  stroke: #000;
}

创建节点/边后,我们可以调用实例上的 attr() 方法来修改节点属性样式。看下面代码,通过 / 分割的路径修改样式,label 选择器对应到 <text> 元素,text 则是该元素的属性名,'hello' 是新的属性值。

rect.attr('label/text', 'hello')

// 等同于
rect.attr('label', {
  text: 'hello'
})

// 等同于
rect.attr({
  label: {
    text: 'hello'
  }
})

当传入的属性值为 null 时可以移除该属性。

rect.attr('label/text', null)

shape

节点/边的图形,图形类似 MVC 模式中的 Model,决定了节点/边的结构化数据。该选项通常在使用 graph.addNodegraph.addEdge 两个方法添加节点和边时使用。

const rect = graph.addNode({
  shape: 'rect',
  x: 100,
  y: 200,
  width: 80,
  height: 40,
  label: 'rect', 
})

const circle = graph.addNode({
  shape: 'circle',
  x: 280,
  y: 200,
  width: 60,
  height: 60,
  label: 'circle', 
})

const edge = graph.addEdge({
  shape: 'edge',
  source: rect,
  target: circle,
})

在 X6 内部实现中,我们通过 shape 指定的图形找到对应的构造函数来初始化节点/边,并将其添加到画布。

该选项的默认值为:

  • graph.addNode 方法中 shape 的默认值为 'rect'
  • graph.addEdge 方法中 shape 的默认值为 'edge'

同时,我们在 X6 中内置了一系列节点和边。

内置节点构造函数与 shape 名称对应关系如下表。

构造函数shape 名称描述
Shape.Rectrect矩形。
Shape.Circlecircle圆形。
Shape.Ellipseellipse椭圆。
Shape.Polygonpolygon多边形。
Shape.Polylinepolyline多段线。
Shape.Pathpath路径。
Shape.Imageimage图片。
Shape.HTMLhtmlHTML 节点,使用 foreignObject 渲染 HTML 片段。
Shape.TextBlocktext-block文本节点,使用 foreignObject 渲染文本。
Shape.BorderedImageimage-bordered带边框的图片。
Shape.EmbeddedImageimage-embedded内嵌入矩形的图片。
Shape.InscribedImageimage-inscribed内嵌入椭圆的图片。
Shape.Cylindercylinder圆柱。

内置边构造函数与 shape 名称对应关系如下表。

构造函数shape 名称描述
Shape.Edgeedge边。
Shape.DoubleEdgedouble-edge双线边。
Shape.ShadowEdgeshadow-edge阴影边。

除了使用 X6 的内置节点/边,我们还可以注册自定义节点/边并使用他们,想了解更多请参考自定义节点自定义边教程。

view

指定渲染节点/边所使用的视图,视图的概念与 MVC 模式中的 View 一致。

zIndex

节点/边在画布中的层级,默认根据节点/边添加顺序自动确定。节点/边渲染到画布后可以通过 cell.getZIndex()cell.setZIndex(z: number) 来获取或设置 zIndex 的值,也可以调用 cell.toFront()cell.toBack() 来将其移到最顶层或最底层。

visible

节点/边是否可见,默认可见。

parent

父节点 ID。

children

子节点/边的 ID 数组。

tools

节点/边的小工具。小工具可以增强节点/边的交互能力,我们分别为节点和边提供了以下内置工具:

节点

  • button 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。
  • button-remove 在指定的位置处,渲染一个删除按钮,点击时删除对应的节点。
  • boundary 根据节点的包围盒渲染一个包围节点的矩形。注意,该工具仅仅渲染一个矩形,不带任何交互。

  • vertices 路径点工具,在路径点位置渲染一个小圆点,拖动小圆点修改路径点位置,双击小圆点删除路径点,在边上单击添加路径点。
  • segments 线段工具。在边的每条线段的中心渲染一个工具条,可以拖动工具条调整线段两端的路径点的位置。
  • boundary 根据边的包围盒渲染一个包围边的矩形。注意,该工具仅仅渲染一个矩形,不带任何交互。
  • button 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。
  • button-remove 在指定的位置处,渲染一个删除按钮,点击时删除对应的边。
  • source-arrowhead-和-target-arrowhead 在边的起点或终点渲染一个图形(默认是箭头),拖动该图形来修改边的起点或终点。

可以指定单个工具:

graph.addNode({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  tools: 'button-remove' // or { name: 'button-remove' }
})

同时,可以像下面这样指定工具的参数选项:

graph.addNode({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  tools: { 
    name: 'button-remove',
    args: {
      x: 10, // 按钮的 x 坐标,相对于节点的左上角
      y: 10, // 按钮的 y 坐标,相对于节点的左上角
    },
  },
})

也可以同时指定多个小工具:

graph.addNode({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  tools: [
    'button-remove',
    {
      name: 'boundary',
      args: {
        padding: 5,
      },
    },
  ],
})

另外,还可以为工具集指定一个名称,后续可以通过 cell.hasTools(name) 方法来判断节点/边中是否包含指定名称的工具集。

graph.addNode({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  tools: {
    name: 'onhover', // 工具集名称
    items: [         // 通过 items 来指定包含哪些小工具
      'button-remove',
      {
        name: 'boundary',
      },
    ],
  },
})

data

与节点/边关联的业务数据。例如,我们在实际使用时通常会将某些业务数据存在节点/边的 data 上。

const rect = new Shape.Rect({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  data: { 
    bizID: 125,
    date: '20200630',
    price: 89.00,
  }
})

prototype

通用

get model

获取节点/边所属的 Model,当节点/边被添加到画布时将自动确定。

const rect = new Shape.Rect({
  x: 30,
  y: 30,
  width: 100,
  height: 40,
})

// 刚刚创建的节点 model 为空。
console.log(rect.model) // undefined

graph.addNode(rect)

// 节点添加到画布后自动为其指定对应的 Model。
console.log(rect.model) // Model 实例

get shape

获取节点/边的图形,返回注册到 X6 的图形的名称。图形与 MVC 模式中 Model 的概念一致,决定了节点/边的结构化数据。

if (node.shape === 'rect') {
  // do something if the node is a 'rect' node.
}

get view

获取节点/边的视图,返回注册到 X6 的视图的名称。视图与 MVC 模式中 View 的概念一致,决定了节点/边的渲染和更新逻辑。

if (node.view === 'rect') {
  // do something if the node is a 'rect' view.
}

isNode()

isNode(): boolean

检测实例是不是 Node 实例,如果是 Node 实例则返回 true,否则返回 false。所有继承自 Node 的节点都返回 true

if (cell.isNode()) {
  // do something if the cell is a node.
}

isEdge()

isEdge(): boolean

检测实例是不是 Edge 实例,如果是 Edge 实例则返回 true,否则返回 false。所有继承自 Edge 的边都返回 true

if (cell.isEdge()) {
  // do something if the cell is an edge.
}

toJSON(...)

toJSON(options?: Cell.ToJSONOptions): Object

将节点/边的结构化数据转换为 JSON 数据,以便做持久化存储(通常我们通过调用 graph.toJSON 来导出整个画布的数据)。

参数

选项类型默认值必选描述
options.diffbooleanfalse是否返回与默认值相比具有差异的那些数据。

返回值

  • options.difffalse 时,返回完整数据。
  • options.difftrue 时,返回差异数据。

clone(...)

clone(options?: Cell.CloneOptions): Cell | Node | Edge | { [id:string]: Node | Edge }

克隆节点/边。

参数

选项类型默认值必选描述
options.deepbooleanfalse是否克隆子孙节点和边,默认为 false 表示只克隆自身。

返回值

  • options.deepfalse 时,返回通克隆创建的新节点/边。
  • options.deeptrue 时,返回一个对象,对象的 Key 是被克隆节点/边的 ID,对象的 Value 是克隆出来的节点/边。

on(...)

on(name: string, handler: Events.Handler, context?: any): this

监听事件。

参数

选项类型默认值必选描述
namestring事件名称。
handlerEvents.Handler回调函数。
contextany回调函数的调用上下文。

once(...)

once(name: string, handler: Events.Handler, context?: any): this

监听一次事件,当事件被触发后自动删除该监听。

参数

选项类型默认值必选描述
namestring事件名称。
handlerEvents.Handler回调函数。
contextany回调函数的调用上下文。

off(...)

/**
 * 删除所有事件监听。
 */
off(): this

/**
 * 删除指定 name 的所有事件监听。
 */
off(name: string): this

/**
 * 删除指定 handler 对应的事件监听。
 */
off(name: null, handler: Events.Handler): this

/**
 * 删除指定 name 和 handler 的事件监听。
 */
off(name: string, handler: Events.Handler, context?: any): this

删除事件监听。

trigger(...)

trigger(name: string, ...args?: any[]): boolean | Promise<boolean>

触发事件。

参数

选项类型默认值必选描述
namestring事件名称。
...argsany[]传给回调函数的参数。

返回值

  • 当回调函数都是同步函数时,只要某个回调函数返回 false 时就返回 false,否则返回 true
  • 当回调函数中存在异步函数时,按照同步回调的判断逻辑,返回 Promise<boolean>

dispose()

dispose(): void

销毁并从父节点中移除节点/边。

标签结构 markup

指定了渲染节点/边时使用的 SVG/HTML 结构,使用 JSON 格式描述,通常在定义节点/边时通过 config 方法将其设置为所有实例共享。当修改 markup 时,将触发 'change:markup' 事件和画布重绘。

get markup

获取 markup

const markup = cell.markup

set markup

设置 markup,并触发 'change:markup' 事件和画布重绘。

cell.markup = markup

getMarkup()

getMarkup(): Markup

获取 markup

const markup = cell.getMarkup()

setMarkup(...)

setMarkup(markup: Markup, options?: Cell.SetOptions): this

设置 markup

默认情况触发 'change:markup' 事件和画布重绘,当 options.silenttrue 时不触发 'change:markup' 事件和画布重绘。

参数

名称类型必选默认值描述
markupMarkup
options.silentbooleanfalsetrue 时不触发 'change:markup' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,设置 markup 时,触发 'change:markup' 事件和画布重绘:

cell.setMarkup(markup)

options.silenttrue 时,不触发 'change:markup' 事件和画布重绘:

cell.setMarkup(markup, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.setMarkup(markup, { otherKey: 'otherValue', ... })

removeMarkup(...)

removeMarkup(options?: Cell.SetOptions): this

删除 markup

默认情况触发 'change:markup' 事件和画布重绘,当 options.silenttrue 时不触发 'change:markup' 事件和画布重绘。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:markup' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,删除 markup 时,触发 'change:markup' 事件和画布重绘:

cell.removeMarkup()

options.silenttrue 时,不触发 'change:markup' 事件和画布重绘:

cell.removeMarkup({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.removeMarkup({ otherKey: 'otherValue', ... })

元素属性 attrs

属性 attrs 是一个复杂对象,当修改 attrs 时,将触发 'change:attrs' 事件和画布重绘。

get attrs

获取属性。

const atts = cell.attrs

set attrs

设置属性,并触发 'change:attrs' 事件和画布重绘。

cell.atts = attrs

getAttrs()

getAttrs(): Attr.CellAttrs

获取属性。

const atts = cell.getAttrs()

setAttrs(...)

setAttrs(attrs: Attr.CellAttrs, options?: Cell.SetAttrOptions): this

设置属性,默认情况触发 'change:attrs' 事件和画布重绘。

参数

名称类型必选默认值描述
attrsAttr.CellAttrs | null | undefined
options.overwritebooleanfalsetrue 时替换现有属性,否则根据 options.deep 选项进行深度或浅度 merge。
options.deepbooleantrueoptions.overwritefalse 时有效, 为 true 时进行深度 merge,否则进行浅 merge。
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,指定的属性将与旧属性进行深度 merge

console.log(cell.getAttrs())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

cell.setAttrs({
  body: { fill: '#f5f5f5' },
  label: { text: 'My Label' },
})

console.log(cell.getAttrs())
// {
//   body: { fill: '#f5f5f5' },
//   label: { fill: '#333333', text: 'My Label' },
// }

options.deepfalse 时,进行浅 merge:

console.log(cell.getAttrs())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

cell.setAttrs(
  { label: { text: 'My Label' } }, 
  { deep: false },
)

console.log(cell.getAttrs())
// {
//   body: { fill: '#ffffff' },
//   label: { text: 'My Label' },
// }

options.overwritetrue 时,直接替换旧属性:

console.log(cell.getAttrs())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

cell.setAttrs(
  { label: { text: 'My Label' } }, 
  { overwrite: true },
)

console.log(cell.getAttrs())
// {
//   label: { text: 'My Label' },
// }

options.silent 为 true 时不触发 'change:attrs' 事件和画布重绘。

cell.setAttrs(myAttrs, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用。

cell.setAttrs(myAttrs, { otherKey: 'otherValue', ... })

replaceAttrs(...)

replaceAttrs(attrs: Attr.CellAttrs, options: Cell.SetOptions = {}): this

用给定的属性替换原有属性,相当于调用 setAttrs(attrs, { ...options, overwrite: true })

参数

名称类型必选默认值描述
attrsAttr.CellAttrs | null | undefined
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

updateAttrs(...)

updateAttrs(attrs: Attr.CellAttrs, options: Cell.SetOptions = {}): this

使用浅 merge 更新属性,相当于调用 setAttrs(attrs, { ...options, deep: false })

参数

名称类型必选默认值描述
attrsAttr.CellAttrs | null | undefined
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

removeAttrs(...)

removeAttrs(options?: Cell.SetOptions): this

删除属性。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,删除 attrs 时,触发 'change:attrs' 事件和画布重绘:

cell.removeAttrs()

options.silenttrue 时,不触发 'change:attrs' 事件和画布重绘:

cell.removeAttrs({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.removeAttrs({ otherKey: 'otherValue', ... })

getAttrByPath(...)

getAttrByPath<T>(path?: string | string[]): T

根据属性路径获取属性值。

参数

名称类型必选默认值描述
pathstring | string[]属性路径。
pathstring 类型时,路径是以 '\' 分割的字符串。
pathstring[] 类型时,路径是属性对象路径上的 Key 构成的数组。

用法

某节点的属性值如下:

console.log(cell.getAttrs())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

当路径为空时返回全部属性:

console.log(cell.getAttrByPath())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

通过字符串路径获取属性值:

console.log(cell.getAttrByPath('body'))
// { fill: '#ffffff' }

console.log(cell.getAttrByPath('body/fill'))
// '#ffffff'

console.log(cell.getAttrByPath('unkonwn'))
// undefined

console.log(cell.getAttrByPath('body/unkonwn'))
// undefined

通过属性对象的 Key 数组构成的路径获取属性值:

console.log(cell.getAttrByPath(['body']))
// { fill: '#ffffff' }

console.log(cell.getAttrByPath(['body', 'fill']))
// '#ffffff'

console.log(cell.getAttrByPath(['unkonwn']))
// undefined

console.log(cell.getAttrByPath(['body', 'unkonwn']))
// undefined

setAttrByPath(...)

setAttrByPath(path: string | string[], value: Attr.ComplexAttrValue, options?: Cell.SetOptions): this

根据属性路径设置属性值。

参数

名称类型必选默认值描述
pathstring | string[]属性路径。
pathstring 类型时,路径是以 '\' 分割的字符串。
pathstring[] 类型时,路径是属性对象路径上的 Key 构成的数组。
valueAttr.ComplexAttrValue新属性值。
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

某节点的初始属性值如下:

console.log(cell.getAttrs())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

通过字符串路径获取属性值:

cell.setAttrByPath('body', { stroke: '#000000' }) // 替换 body 属性值
console.log(cell.getAttrs())
// {
//   body: { stroke: '#000000' },
//   label: { fill: '#333333' },
// }

cell.setAttrByPath('body/fill', '#f5f5f5') // 设置 body.fill 属性值
console.log(cell.getAttrs())
// {
//   body: { stroke: '#000000', fill: '#f5f5f5' },
//   label: { fill: '#333333' },
// }

或者通过属性对象的 Key 数组构成的路径获取属性值:

cell.setAttrByPath(['body'], { stroke: '#000000' }) // 替换 body 属性值
console.log(cell.getAttrs())
// {
//   body: { stroke: '#000000' },
//   label: { fill: '#333333' },
// }

cell.setAttrByPath(['body', 'fill'], '#f5f5f5') // 设置 body.fill 属性值
console.log(cell.getAttrs())
// {
//   body: { stroke: '#000000', fill: '#f5f5f5' },
//   label: { fill: '#333333' },
// }

options.silent 为 true 时不触发 'change:attrs' 事件和画布重绘。

cell.setAttrByPath('body', { stroke: '#000000' }, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用。

cell.setAttrByPath('body', { stroke: '#000000' }, { otherKey: 'otherValue', ... })

removeAttrByPath(...)

removeAttrByPath(path: string | string[], options?: Cell.SetOption ): this

删除指定路径的属性值。

参数

名称类型必选默认值描述
pathstring | string[]属性路径。
pathstring 类型时,路径是以 '\' 分割的字符串。
pathstring[] 类型时,路径是属性对象路径上的 Key 构成的数组。
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

某节点的初始属性值如下:

console.log(cell.getAttrs())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

通过字符串路径删除属性值:

cell.removeAttrByPath('body/fill')
console.log(cell.getAttrs())
// {
//   body: { },
//   label: { fill: '#333333' },
// }

cell.removeAttrByPath('body')
console.log(cell.getAttrs())
// {
//   label: { fill: '#333333' },
// }

或者通过属性对象的 Key 数组构成的路径删除属性值:

cell.removeAttrByPath(['body', 'fill'])
console.log(cell.getAttrs())
// {
//   body: { },
//   label: { fill: '#333333' },
// }

cell.removeAttrByPath(['body'])
console.log(cell.getAttrs())
// {
//   label: { fill: '#333333' },
// }

options.silenttrue 时,不触发 'change:attrs' 事件和画布重绘:

cell.removeAttrByPath('body/fill', { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.removeAttrByPath('body/fill', { otherKey: 'otherValue', ... })

attr(...)

/**
 * 获取属性。
 */
attr(): Cell.CellAttrs

/**
 * 获取指定路径上的属性值。
 */
attr<T>(path: string | string[]): T

/**
 * 设置指定路径上的属性值。
 */
attr(path: string | string[], value: Attr.ComplexAttrValue | null, options?: Cell.SetOptions): this

/**
 * 设置属性值,传入的属性与旧属性进行深度 merge。
 */
attr(attrs: Attr.CellAttrs, options?: Cell.SetOptions): this

该方法是 getAttrByPathsetAttrByPathsetAttrs 三个方法的整合,提供了上面四种函数签名,是一个非常实用的方法。

用法

获取全部属性值:

console.log(cell.attr())
// {
//   body: { fill: '#ffffff' },
//   label: { fill: '#333333' },
// }

获取指定路径上的属性值:

console.log(cell.attr('body/fill'))
// '#ffffff' 

设置指定路径上的属性值:

cell.attr('body/fill', '#f5f5f5')
console.log(cell.attr())
// {
//   body: { fill: '#f5f5f5' },
//   label: { fill: '#333333' },
// }

通过属性对象设置属性值,与就属性对象进行深度 merge

cell.attr({
  body: { stroke: '#000000' },
  label: { fill: 'blue', text: 'my lable' },
})
console.log(cell.attr())
// {
//   body: { fill: '#f5f5f5', stroke: '#000000' },
//   label: { fill: 'blue', text: 'my lable' },
// }

层级 zIndex

zIndex 是节点/边在画布中的层级,默认根据节点/边添加顺序自动确定。当修改 zIndex 时,将触发 'change:zIndex' 事件和画布重绘。

get zIndex

获取 zIndex

const z = cell.zIndex

set zIndex

设置 zIndex,触发 'change:zIndex' 事件和画布重绘。

cell.zIndex = 2

getZIndex()

getZIndex(): number

获取 zIndex

const z = cell.getZIndex()

setZIndex(...)

setZIndex(zIndex: number, options?: Cell.SetOptions): this

设置 zIndex

默认情况触发 'change:zIndex' 事件和画布重绘,当 options.silenttrue 时不触发 'change:zIndex' 事件和画布重绘。

参数

名称类型必选默认值描述
zIndexnumber
options.silentbooleanfalsetrue 时不触发 'change:zIndex' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,设置 zIndex 时,触发 'change:zIndex' 事件和画布重绘:

cell.setZIndex(2)

options.silenttrue 时,不触发 'change:zIndex' 事件和画布重绘:

cell.setZIndex(2, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.setZIndex(2, { otherKey: 'otherValue', ... })

removeZIndex(...)

removeZIndex(options?: Cell.SetOptions): this

删除 zIndex

默认情况触发 'change:zIndex' 事件和画布重绘,当 options.silenttrue 时不触发 'change:zIndex' 事件和画布重绘。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:zIndex' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,删除 zIndex 时,触发 'change:zIndex' 事件和画布重绘:

cell.removeZIndex()

options.silenttrue 时,不触发 'change:zIndex' 事件和画布重绘:

cell.removeZIndex({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.removeZIndex({ otherKey: 'otherValue', ... })

toFront(...)

toFront(options?: Cell.ToFrontOptions): this

将节点/边移到最顶层。

参数

名称类型必选默认值描述
options.deepbooleanfalsetrue 时同时更新所有子节点/边的层级。
options.silentbooleanfalsetrue 时不触发 'change:zIndex' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,更新 zIndex 时,触发 'change:zIndex' 事件和画布重绘:

cell.toFront()

options.deeptrue 时,同时更新所有子节点/边的层级。:

cell.toFront({ deep: true })

options.silenttrue 时,不触发 'change:zIndex' 事件和画布重绘:

cell.toFront({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.toFront({ otherKey: 'otherValue', ... })

toBack(...)

toBack(options?: Cell.ToBackOptions): this

将节点/边移到最底层。

参数

名称类型必选默认值描述
options.deepbooleanfalsetrue 时同时更新所有子节点/边的层级。
options.silentbooleanfalsetrue 时不触发 'change:zIndex' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,更新 zIndex 时,触发 'change:zIndex' 事件和画布重绘:

cell.toBack()

options.deeptrue 时,同时更新所有子节点/边的层级。:

cell.toBack({ deep: true })

options.silenttrue 时,不触发 'change:zIndex' 事件和画布重绘:

cell.toBack({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.toBack({ otherKey: 'otherValue', ... })

可见性 Visible

get visible

返回节点/边是否可见。

if (cell.visible) {
  // do something
}

set visible

设置节点/边是否可见,并触发 'change:visible' 事件和画布重绘。

show(...)

show(options?: Cell.SetOptions): this

显示节点/边。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:visible' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,显示节点/边时,触发 'change:visible' 事件和画布重绘:

cell.show()

options.silenttrue 时,不触发 'change:markup' 事件和画布重绘:

cell.show({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.show({ otherKey: 'otherValue', ... })

hide(...)

hide(options?: Cell.SetOptions): this

隐藏节点/边。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:visible' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,隐藏节点/边时,触发 'change:visible' 事件和画布重绘:

cell.hide()

options.silenttrue 时,不触发 'change:visible' 事件和画布重绘:

cell.hide({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.hide({ otherKey: 'otherValue', ... })

isVisible()

isVisible(): boolean

返回节点/边是否可见。

if (cell.isVisible()) {
  // do something
}

setVisible(...)

setVisible(visible: boolean, options?: Cell.SetOptions): this

设置节点/边的可见性。

默认情况触发 'change:visible' 事件和画布重绘,当 options.silenttrue 时不触发 'change:visible' 事件和画布重绘。

参数

名称类型必选默认值描述
visibleboolean
options.silentbooleanfalsetrue 时不触发 'change:visible' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,改变节点/边的可见性时,触发 'change:visible' 事件和画布重绘:

cell.setVisible(false)

options.silenttrue 时,不触发 'change:visible' 事件和画布重绘:

cell.setVisible(false, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.setVisible(false, { otherKey: 'otherValue', ... })

toggleVisible(...)

toggleVisible(options?: Cell.SetOptions): this

切换节点/边的可见性。

默认情况触发 'change:visible' 事件和画布重绘,当 options.silenttrue 时不触发 'change:visible' 事件和画布重绘。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:visible' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,切换节点/边的可见性时,触发 'change:visible' 事件和画布重绘:

cell.toggleVisible()

options.silenttrue 时,不触发 'change:visible' 事件和画布重绘:

cell.toggleVisible({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.toggleVisible({ otherKey: 'otherValue', ... })

业务数据 Data

与节点/边关联的业务数据。例如,我们在实际使用时通常会将某些业务数据存在节点/边的 data 上。

const rect = new Shape.Rect({
  x: 40,
  y: 40,
  width: 100,
  height: 40,
  data: { 
    bizID: 125,
    date: '20200630',
    price: 89.00,
  }
})

get data

获取关联的数据。

set data

设置关联的数据,并触发 'change:data' 事件和画布重绘。

getData()

getData(): any

获取关联的数据。

setData(...)

setData(data: any, options?: Cell.SetDataOptions): this

设置关联的业务数据。

默认情况触发 'change:data' 事件和画布重绘,当 options.silenttrue 时不触发 'change:data' 事件和画布重绘。

参数

名称类型必选默认值描述
dataany
options.overwritebooleanfalsetrue 时替换现有值,否则根据 options.deep 选项进行深度或浅度 merge。
options.deepbooleantrueoptions.overwritefalse 时有效, 为 true 时进行深度 merge,否则进行浅 merge。
options.silentbooleanfalsetrue 时不触发 'change:data' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

默认与原数据进行深度 merge,并触发 'change:data' 事件和画布重绘:

cell.setData(data)

options.overwritetrue 时,替换旧数据:

cell.setData(data, { overwrite: true })

options.deepfalse 时,与原数据进行浅 merge:

cell.setData(data, { overwrite: true })

options.silenttrue 时,不触发 'change:data' 事件和画布重绘:

cell.setData(data, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.setData(data, { otherKey: 'otherValue', ... })

replaceData(...)

replaceData(data: any, options: Cell.SetOptions = {}): this

用指定的数据替换原数据,相当于调用 setData(data, { ...options, overwrite: true })

参数

名称类型必选默认值描述
dataany
options.silentbooleanfalsetrue 时不触发 'change:data' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

updateData(...)

updateData(data: any, options: Cell.SetOptions = {}): this

通过浅 merge 来更新数据,相当于调用 setData(data, { ...options, deep: false })

参数

名称类型必选默认值描述
dataany
options.silentbooleanfalsetrue 时不触发 'change:data' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

removeData(...)

removeData(options: Cell.SetOptions): this

删除数据。

默认情况触发 'change:data' 事件和画布重绘,当 options.silenttrue 时不触发 'change:data' 事件和画布重绘。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:data' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,删除 data 时,触发 'change:data' 事件和画布重绘:

cell.removeData()

options.silenttrue 时,不触发 'change:data' 事件和画布重绘:

cell.removeData({ silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.removeData({ otherKey: 'otherValue', ... })

父子关系 Parent/Children

get parent

获取父节点。

getParent()

getParent(): Cell | null

获取父节点。

返回值

当父节点存在是返回父节点,否则返回 null

setParent(...)

setParent(parent: Cell | null, options?: Cell.SetOptions): this

设置父节点。

参数

名称类型必选默认值描述
parentCell | null父节点或 null,当 parentnull 时删除父节点。
options.silentbooleanfalsetrue 时不触发 'change:parent' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,当 parent 发生改变时,触发 'change:parent' 事件和画布重绘:

cell.setParent(parent)

parent 为空时删除父节点:

cell.setParent(null)

options.silenttrue 时,不触发 'change:parent' 事件和画布重绘:

cell.setParent(parent, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.setParent(parent, { otherKey: 'otherValue', ... })

getParentId()

getParentId(): string | undefined

获取父节点的 ID。

返回值

当父节点存在是返回父节点的 ID,否则返回 undefined

hasParent()

hasParent(): boolean

检查节点/边是否有父节点。

用法

if (cell.hasParent()) {
  // do something
}

get children

获取所有子节点/边。

getChildren()

getChildren(): Cell[] | null

获取所有子节点/边。

setChildren()

setChildren(children: Cell[] | null, options?: Cell.SetOptions) 

设置子节点/边。

参数

名称类型必选默认值描述
childrenCell[] | null子节点/边数组或 null,当 childrennull 时清空子节点/边。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况,当 children 发生改变时,触发 'change:children' 事件和画布重绘:

cell.setChildren(children)

childrennull 时清空子节点/边:

cell.setChildren(null)

options.silenttrue 时,不触发 'change:children' 事件和画布重绘:

cell.setChildren(children, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

cell.setChildren(children, { otherKey: 'otherValue', ... })

isParentOf(...)

isParentOf(child: Cell | null): boolean

返回当前节点是否是指定 Cell 的父节点。

参数

名称类型必选默认值描述
childCell | null

isChildOf(...)

isChildOf(parent: Cell | null): boolean

返回当前节点/边是否是指定节点的的子节点/边。

参数

名称类型必选默认值描述
parentCell | null

eachChild(...)

eachChild(iterator: (child: Cell, index: number, children: Cell[]) => void, context?: any): this

参数

名称类型必选默认值描述
iterator(child: Cell, index: number, children: Cell[]) => void迭代器函数。
contextany迭代器函数的执行上下文。

遍历子节点。

filterChild(...)

filterChild(iterator: (child: Cell, index: number, children: Cell[]) => boolean, context?: any): Cell[]

过滤子节点。

参数

名称类型必选默认值描述
iterator(child: Cell, index: number, children: Cell[]) => boolean过滤器函数。
contextany过滤器函数的执行上下文。

返回值

返回满足过滤条件的子节点/边,或者空数组。

getChildCount()

getChildCount(): number

获取子节点/边的数量。

返回值

返回子节点/边的数量,当没有子节点/边时返回 0

getChildIndex(...)

getChildIndex(child: Cell): number

获取子节点/边的索引。

参数

名称类型必选默认值描述
childCell

返回值

返回子节点/边的索引,当子节点不存在时返回 -1

getChildAt(...)

getChildAt(index: number): Cell | null

获取指定索引位置的子节点/边。

参数

名称类型必选默认值描述
indexnumber索引位置。

返回值

返回指定索引位置的子节点,当该节点不存在子节点/边、索引越界、子节点不存在时返回 null

getAncestors(...)

getAncestors(options?: { deep?: boolean }): Cell[]

获取所有祖先节点。

参数

名称类型必选默认值描述
options.deepbooleantrue默认递归获取所有祖先节点,设置为 false 时只返回当前节点/边的父节点。

返回值

返回祖先节点数组。

getDescendants(...)

getDescendants(options?: Cell.GetDescendantsOptions): Cell[]

获取所有子孙节点。

参数

名称类型必选默认值描述
options.deepbooleantrue默认递归获取所有子孙节点,设置为 false 时只返回当前节点孩子节点/边。
options.breadthFirstbooleanfalse默认使用深度优先算法,设置为 true 时使用广度优先搜索算法。

返回值

返回子孙节点/边的数组。

isDescendantOf(...)

isDescendantOf(ancestor: Cell | null, options?: { deep?: boolean }): boolean

返回当前节点/边是否是指定节点的子孙节点/边。

参数

名称类型必选默认值描述
ancestorCell | null指定节点。
options.deepbooleantrue默认递归判断指定节点的所有子孙节点/边,设置为 false 时只判断孩子节点/边。

isAncestorOf(...)

isAncestorOf(descendant: Cell | null, options?: { deep?: boolean }): boolean

返回当前节点是否是指定节点/边的祖先节点。

参数

名称类型必选默认值描述
descendantCell | null指定节点/边。
options.deepbooleantrue默认递归判断指定节点的所有子孙节点/边,设置为 false 时只判断孩子节点/边。

getCommonAncestor(...)

getCommonAncestor(...cells: (Cell | null | undefined)[]): Cell | null

参数

名称类型必选默认值描述
...cells(Cell | null | undefined)[]指定节点/边。

获取给定节点/边的共同祖先节点。

返回值

返回找到的共同祖先节点,否则没有共同祖先节点时返回 null

addTo(...)

addTo(model: Model, options?: Cell.SetOptions): this
addTo(graph: Graph, options?: Cell.SetOptions): this
addTo(parent: Cell, options?: Cell.SetOptions): this

将当前节点/边添加到画布或指定的父节点。

insertTo(...)

insertTo(parent: Cell, index?: number, options?: Cell.SetOptions): this

将当前节点/边插入到指定父节点的指定位置。

参数

名称类型必选默认值描述
parentCell父节点。
indexnumber要插入的索引位置,缺省时插入到末尾。
options.silentbooleanfalsetrue 时不触发 'change:parent' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

addChild(...)

addChild(child: Cell, options?: Cell.SetOptions): this

将指定的节点/边添加到当前节点的子节点的末尾。

参数

名称类型必选默认值描述
childCell指定的节点/边。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

insertChild(...)

insertChild(child: Cell, index?: number, options?: Cell.SetOptions): this

将指定的节点/边添加到当前节点的子节点的指定位置。

参数

名称类型必选默认值描述
childCell指定的节点/边。
indexnumber要插入的索引位置,缺省时插入到末尾。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

embed(...)

embed(child: Cell, options?: Cell.SetOptions): this

将指定的节点/边嵌入到当前节点,即将指定的节点/边插入到当前节点的末尾。

参数

名称类型必选默认值描述
childCell指定的节点/边。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

unembed(...)

unembed(child: Cell, options?: Cell.SetOptions): this

将指定的节点/边从当前节点中移除。

参数

名称类型必选默认值描述
childCell指定的节点/边。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

removeFromParent(...)

removeFromParent(options?: Cell.RemoveOptions): this

将当前节点从父节点中移除。

参数

名称类型必选默认值描述
options.deepbooleantrue默认递归移除所有子节点/边,设置为 false 时只移除当前节点/边。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

removeChild(...)

removeChild(child: Cell, options?: Cell.RemoveOptions): Cell | null

移除指定的子节点/边。

参数

名称类型必选默认值描述
childCell指定的节点/边。
options.deepbooleantrue默认递归移除所有子节点/边,设置为 false 时只移除当前节点/边。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

返回值

返回被移除的节点/边。

removeChildAt(...)

removeChildAt(index: number, options?: Cell.RemoveOptions): Cell | null

移除指定索引位置的子节点/边。

名称类型必选默认值描述
indexnumber指定的索引位置。
options.deepbooleantrue默认递归移除所有子节点/边,设置为 false 时只移除当前节点/边。
options.silentbooleanfalsetrue 时不触发 'change:children' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

返回值

返回被移除的节点/边。

remove(...)

remove(options?: Cell.RemoveOptions): this

先将当前节点/边从父节点,然后将其从画布中移除。

节点和边的属性 Properties

上面介绍的 markupattrszIndexdata 等基础选项,以及节点的 sizepositionangleports 等选项,还有边的 sourcetargetlabels 等选项,还有创建节点/边时提供的那些额外的键值对,我们都称为属性(Property)。

const rect = new Shape.Rect({
  x: 30,
  y: 30,
  width: 100,
  height: 40,
  attrs: {...},
  data: {...},
  zIndex: 10,
  sale: {...},
  product: {
    id: '1234',
    name: 'apple',
    price: 3.99,
  },
})

例如,上面代码中的 attrsdatazIndex 都是标准的属性,其中 xy 是一对自定义选项,节点初始化时被转换为了 position 属性,同样 widthheight 也是一对自定义选项,节点初始化时被转换为了 size 属性,最后剩余的 saleproduct 两个对象是非标准的属性。

上面介绍了一些标准属性以及操作(get/set)这些标准属性的方法,下面再介绍几个比较通用的方法,这些方法对标准和非标准属性都适用。

getProp(...)

getProp<T>(key: string, defaultValue?: T): T

获取指定的属性值。

参数

名称类型必选默认值描述
keystring属性名称。
defaultValueTundefined默认值,当指定的属性不存在时返回该默认值。

用法

// 获取标准属性
const zIndex = rect.getProp<number>('zIndex')
const position = rect.getProp<{x: number; y: number}>('position')

// 获取非标准属性
const product = rect.getProp('product')

setProp(...)

/**
 * 设置指定的属性
 */
setProp(key: string, value: any, options?: Cell.SetOptions): this
/**
 * 批量设置属性,提供的属性与原属性进行深度 merge
 */
setProp(props: Partial<Properties>, options?: Cell.SetOptions): this

设置属性。

默认情况触发对应的 'change:xxx' 事件和画布重绘,当 options.silenttrue 时不触发 'change:xxx' 事件和画布重绘。

参数

名称类型必选默认值描述
keystring属性名称。
valueany属性值。
propsPartial属性键值对,将与现有属性进行深度 merge
options.silentbooleanfalsetrue 时不触发 'change:markup' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

设置单个属性:

rect.setProp('size', { width: 100, height: 30 })
rect.setProp('zIndex', 10)

通过键值对设置多个属性,提供的键值对将与现有属性进行深度 merge

rect.setProp({
  size: {
    width: 100, 
    height: 30, 
  },
  zIndex: 10,
})

options.silenttrue 时,不触发对应的 'change:xxx' 事件和画布重绘:

rect.setProp('zIndex', 10, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

rect.setProp('zIndex', 10, { otherKey: 'otherValue', ... })

removeProp(...)

removeProp(path: string | string[], options?: Cell.SetOptions): this

删除指定路径的属性。

默认情况触发对应的 'change:xxx' 事件和画布重绘,当 options.silenttrue 时不触发 'change:xxx' 事件和画布重绘。

参数

名称类型必选默认值描述
pathstring | string[]属性路径。
options.silentbooleanfalsetrue 时不触发 'change:markup' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

删除单个属性:

rect.removeProp('zIndex')

删除指定路径的属性:

rect.removeProp('product/id')
// 或
rect.removeProp(['product', 'id'])

options.silenttrue 时,不触发对应的 'change:xxx' 事件和画布重绘:

rect.removeProp('zIndex', { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

rect.removeProp('zIndex', { otherKey: 'otherValue', ... })

getPropByPath(...)

getPropByPath<T>(path: string | string[]): T

获取指定路径的属性值。

参数

名称类型必选默认值描述
pathstring | string[]属性路径。
pathstring 类型时,路径是以 '\' 分割的字符串。
pathstring[] 类型时,路径是属性对象路径上的 Key 构成的数组。

用法

rect.getPropByPath('zIndex')
// 或
rect.getPropByPath(['zIndex'])

rect.getPropByPath('product/id')
// 或
rect.getPropByPath(['product', 'id'])

setPropByPath(...)

setPropByPath(path: string | string[], value: any, options?: Cell.SetByPathOptions): this

根据属性路径设置属性值。

默认情况触发对应的 'change:xxx' 事件和画布重绘,当 options.silenttrue 时不触发 'change:xxx' 事件和画布重绘。

名称类型必选默认值描述
pathstring | string[]属性路径。
pathstring 类型时,路径是以 '\' 分割的字符串。
pathstring[] 类型时,路径是属性对象路径上的 Key 构成的数组。
valueany属性值。
options.rewritebooleanfalse默认与现路径上的现有属性进行深度 merge,设置为 true 时直接替换路径上的属性值。
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况触发对应的 'change:xxx' 事件和画布重绘:

rect.setPropByPath('zIndex', 10)
// 或
rect.setPropByPath(['zIndex'], 10)

rect.setPropByPath('product/price', 5.99)
// 或
rect.setPropByPath(['product', 'price'], 5.99)

options.silenttrue 时不触发 'change:xxx' 事件和画布重绘:

rect.setPropByPath('zIndex', 10, { silent: true })
// 或
rect.setPropByPath(['zIndex'], 10, { silent: true })

rect.setPropByPath('product/price', 5.99, { silent: true })
// 或
rect.setPropByPath(['product', 'price'], 5.99, { silent: true })

默认与现路径上的现有属性进行深度 merge,当 options.rewrite 设置为 true 时直接替换路径上的属性值:

rect.setPropByPath(
  ['product'], 
  { id: '234', name: 'banana', price: 2.99 }, 
  { rewrite: true },
)

在选项中支持其他自定义键值对,可以在事件回调用使用:

rect.setPropByPath('zIndex', 10, { otherKey: 'otherValue', ... })

removePropByPath(...)

removePropByPath(path: string | string[], options?: Cell.SetOptions): this

删除指定路径的属性值。

参数

名称类型必选默认值描述
pathstring | string[]属性路径。
pathstring 类型时,路径是以 '\' 分割的字符串。
pathstring[] 类型时,路径是属性对象路径上的 Key 构成的数组。
options.silentbooleanfalsetrue 时不触发 'change:attrs' 事件和画布重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

用法

默认情况触发对应的 'change:xxx' 事件和画布重绘:

rect.removePropByPath('zIndex')
// 或
rect.removePropByPath(['zIndex'])

rect.removePropByPath('product/price')
// 或
rect.removePropByPath(['product', 'price'])

options.silenttrue 时不触发 'change:xxx' 事件和画布重绘:

rect.removePropByPath('zIndex', { silent: true })
// 或
rect.removePropByPath(['zIndex'], { silent: true })

rect.removePropByPath('product/price', { silent: true })
// 或
rect.removePropByPath(['product', 'price'], { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

rect.removePropByPath('zIndex', { otherKey: 'otherValue', ... })

prop(...)

/**
 * 获取所有属性。
 */
prop(): Properties

/**
 * 获取指定路径的属性值。
 */
prop<T>(path: string | string[]): T

/**
 * 设置指定路径的属性值,与路径上的现有属性进行深度 merge。
 */
prop(path: string | string[], value: any, options?: Cell.SetOptions): this


/**
 * 设置属性,与现有属性进行深度 merge。
 */
prop(props: Partial<Properties>, options?: Cell.SetOptions): this

该方法是 getPropsetPropgetPropByPathsetPropByPathremovePropByPath 几个方法的整合,提供了上面四种函数签名,是一个非常实用的方法。

用法

获取属性:

rect.prop()
rect.prop('zIndex')
rect.prop('product/price')

设置属性:

rect.prop('zIndex', 10)
rect.prop('product/price', 5.99)
rect.prop({
  product: {
    id: '234',
    name: 'banana',
    price: 3.99,
  },
})

options.silenttrue 时不触发 'change:xxx' 事件和画布重绘:

rect.prop('zIndex', 10, { silent: true })
// 或
rect.prop(['zIndex'], 10, { silent: true })

rect.prop('product/price', 5.99, { silent: true })
// 或
rect.prop(['product', 'price'], 5.99, { silent: true })

在选项中支持其他自定义键值对,可以在事件回调用使用:

rect.prop('zIndex', 10, { otherKey: 'otherValue', ... })

hasChanged(...)

hasChanged(key: string | undefined | null): boolean

返回指定的属性或所有属性是否已经改变。

参数

名称类型必选默认值描述
keystring | undefined | null属性名。缺省时表示检查所有属性。

用法

if (rect.hasChanged()) {
  // do something
}

if (rect.hasChanged('zIndex')) {
  // do something
}

previous(...)

previous<T>(name: string): T | undefined

当指定的属性发生改变后,获取改变前的属性值。

名称类型必选默认值描述
keystring属性名。

用法

if (rect.hasChanged('zIndex')) {
  const old = rect.previous('zIndex')
  // do something
}

工具集 Tools

addTools(...)

addTools(
  items: Cell.ToolItem | Cell.ToolItem[],
  options?: Cell.AddToolOptions,
): this
addTools(
  items: Cell.ToolItem | Cell.ToolItem[],
  name: string,
  options?: Cell.AddToolOptions,
): this

添加小工具。

参数

名称类型必选默认值描述
itemsCell.ToolItem | Cell.ToolItem[]NodeToolEdgeTool 中定义的小工具。
namestringnull定义该组工具的别称,可以作为hasTools(name)的参数
options.resetbooleanfalse是否清空工具集,默认向工具集追加小工具。
options.localbooleanfalse工具是否渲染到节点/边的容器中,默认为 false,所有工具会渲染在 x6-graph-svg-decorator 下面,只有在 options.resettrue 为时生效
options.silentbooleanfalsetrue 时不触发 'change:tools' 事件和小工具重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

getTools()

getTools(): Cell.Tools | null

获取工具集。

removeTools(...)

removeTools(options?: Cell.SetOptions): this

删除所有工具。

参数

名称类型必选默认值描述
options.silentbooleanfalsetrue 时不触发 'change:tools' 事件和小工具重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

hasTool(name: string): boolean

hasTool(name: string): boolean

是否包含指定名称的工具。

removeTool(...)

removeTool(name: string, options?: Cell.SetOptions): this
removeTool(index: number, options?: Cell.SetOptions): this

删除指定名称的工具。

参数

名称类型必选默认值描述
nameOrIndexstring | number工具名称或索引。
options.silentbooleanfalsetrue 时不触发 'change:tools' 事件和小工具重绘。
options...othersobject其他自定义键值对,可以在事件回调中使用。

动画 Transition

transition(...)

transition(
  path: string | string[],
  target: Animation.TargetValue,
  options: Animation.StartOptions = {},
  delim: string = '/',
): () => void

将指定路径 path 上对应的属性值通过平滑动画的形式过渡到 target 指定的目标值,并返回 stop 方法,调用该方法时立即停止该动画。

参数

名称类型必选默认值描述
pathstring | string[]路径。
targetany目标属性值。
options.delaynumber10动画延迟多久后开始,单位毫秒。
options.durationnumber100动画时长,单位毫秒。
options.timingTiming.Names | (t: number) => number定时函数。
options.interp<T>(from: T, to: T) => (time: number) => T插值函数。
options.start(args: Animation.CallbackArgs) => void动画开始执行时的回调函数。
options.progress(args: Animation.ProgressArgs) => void动画执行过程中的回调函数。
options.complete(args: Animation.CallbackArgs) => void动画执行完成时的回调函数。
options.stop(args: Animation.CallbackArgs) => void动画被停止时的回调函数。
options.finish(args: Animation.CallbackArgs) => void动画执行完成或被停止时的回调函数。
options.jumpedToEndbooleanfalse手动停止动画时,是否立即将动画完成。
delimstring'/'字符串路径分隔符。

我们在 Timing 命名空间中提供了一些定时函数。可以使用内置的定时函数名,或提供一个具有 (t: number) => number 签名的函数。内置的定时函数如下:

  • linear
  • quad
  • cubic
  • inout
  • exponential
  • bounce
  • easeInSine
  • easeOutSine
  • easeInOutSine
  • easeInQuad
  • easeOutQuad
  • easeInOutQuad
  • easeInCubic
  • easeOutCubic
  • easeInOutCubic
  • easeInQuart
  • easeOutQuart
  • easeInOutQuart
  • easeInQuint
  • easeOutQuint
  • easeInOutQuint
  • easeInExpo
  • easeOutExpo
  • easeInOutExpo
  • easeInCirc
  • easeOutCirc
  • easeInOutCirc
  • easeInBack
  • easeOutBack
  • easeInOutBack
  • easeInElastic
  • easeOutElastic
  • easeInOutElastic
  • easeInBounce
  • easeOutBounce
  • easeInOutBounce

我们在 Interp 命名空间上内置了一些插值函数,通常我们可以通过路径上的属性值来自动确定使用哪种插值函数。内置的插值函数如下:

  • number - 数字插值函数。
  • object - { [key: string]: number } 对象插值函数。
  • unit - 数字+单位字符串插值函数,如 10px。支持的单位有:px, em, cm, mm, in, pt, pc, %
  • color - 16 进制颜色插值函数。

用法

import { Timing, Interp } from '@antv/x6'

rect.transition('attrs/label/font-size', '1em', { 
  interp: Interp.unit,
  timing: 'bounce', // Timing.bounce
});

stopTransition(...)

stopTransition(
  path: string | string[],
  options?: Animation.StopOptions<T>,
  delim: string = '/',
): this

停止与指定路径 path 对应的动画。

参数

名称类型必选默认值描述
pathstring | string[]路径。
options.jumpedToEndbooleanfalse手动停止动画时,是否立即将动画完成。
options.complete(args: Animation.CallbackArgs) => void动画执行完成时的回调函数。
options.stop(args: Animation.CallbackArgs) => void动画被停止时的回调函数。
options.finish(args: Animation.CallbackArgs) => void动画执行完成或被停止时的回调函数。
delimstring'/'字符串路径分隔符。

用法

rect.stopTransition('attrs/label/font-size')

getTransitions()

getTransitions(): string[]

获取所有活跃的动画,返回活跃动画的路径。

用法

// 停止所有动画
rect.getTransitions().forEach(
  (path) => rect.stopTransition(path),
)

config(...)

config<C extends Cell.Config = Cell.Config>(presets: C): void

设置节点/边的选项默认值。

参数

名称类型必选默认值描述
options.propHooksCell.PropHooks<M, C>自定义选项。
options.attrHooksAttr.Definitions自定义属性键值对。
Key 是自定义属性的属性名,Value 是自定义属性对象(包含属性检查、应用属性等方法)。
options...othersobject其他选项,节点/边的属性(Properties)。

用法

选项默认值

该方法对自定义节点/边非常友好,方便我们为我们的节点/边设置一些预设选项。例如,我们在定义矩形节点时,为其指定了默认 Markup、默认大小和默认样式。

Shape.Rect.config({
  width: 80,
  height: 40,
  markup: ...,
  attrs: ...,
})

我们创建矩形的代码就可以非常简单:

const rect = graph.addNode({
  x: 100,
  y: 100,
  attrs: {
    label: {
      text: 'rect',
    },
  },
})

每次调用 config(presets) 都是与当前预设值进行深度 merge,例如下面代码分别将矩形的边框默认颜色修改为红色和将默认文本颜色修改为蓝色,最终效果是两者的叠加:

// 只修改边框的默认颜色
Shape.Rect.config({
  attrs: {
    body: {
      stroke: 'red',
    },
  },
})

// 只修改默认文本颜色
Shape.Rect.config({
  attrs: {
    label: {
      fill: 'blue',
      // 覆盖上面定义的 red
      stroke: '#000',
    },
  },
})

自定义选项

创建矩形时我们可以使用 label 来设置矩形的标签文本:

const rect = graph.addNode({
  x: 100,
  y: 100,
  label: 'rect',
})

而我们并没有为矩形定义 label 这个选项,那这个 label 是怎么应用到 attrs/label/text 上的呢?这就用到了 propHooks 钩子,我们可以定义 propHooks 钩子来消费这些非标准的选项。

看下面 label 选项钩子的实现细节:

Shape.Rect.config({
  // 通过钩子将 label 应用到 'attrs/text/text' 属性上
  propHooks(metadata) {
    const { label, ...others } = metadata
    if (label) {
      ObjectExt.setByPath(others, 'attrs/text/text', label)
    }
    return others
  },
})

通过 propHooks 钩子,我们很容易就扩展出一些自定义的选项。例如,我们可以将某些样式定义为节点的选项,这样不仅可以减少嵌套,而且使创建节点的代码语义性更强。

看下面的代码,为矩形定义 rxry 自定义选项:

Shape.Rect.config({
  propHooks: {
    rx(metadata) { 
      const { rx, ...others } = metadata
      if (rx != null) {
        ObjectExt.setByPath(others, 'attrs/body/rx', rx)
      }
      return others
    },
    ry(metadata) { 
      const { ry, ...others } = metadata
      if (ry != null) {
        ObjectExt.setByPath(others, 'attrs/body/ry', ry)
      }
      return others
    },
  },
})

这样,我们就可以很方便添加圆角矩形:

const rect = graph.addNode({
  x: 100,
  y: 100,
  rx: 5,
  ry: 10,
  label: 'rect',
})

自定义属性

自定义属性是指那些非标准的 SVG/HTML 属性,如系统内置的 refWidthrefHeightsourceMarkertargetMarker 等属性。这些属性都是全局共享的,我们可以通过 attrHooks 钩子来为节点/边定义独享的自定义属性。

例如:

import { Shape, Color } from '@antv/x6'

Shape.Rect.config({
  attrHooks: {
    fill: {
      set(val) {
        return Color.invert(val) // 自动反转填充色
      },
    },
    theme: {
      set(val) {
        // 同时设置填充色和边框色
        return {
          fill: val,
          stroke: Color.invert(val),
        }
      },
    },
  }
})

我们可以这样来使用上面定义的 filltheme 属性:

const rect = graph.addNode({
  x: 100,
  y: 100,
  rx: 5,
  ry: 10,
  label: 'rect',
  attrs: {
    body: {
      theme: '#f5f5f5',
    },
    label: {
      fill: '#fff',
    },
  },
})