Home

Awesome

antv-x6-react

React components for building x6 editors

参照lloydzhou/antv-x6-vue实现组件抽象

核心思想

  1. 由于x6主要面向编辑场景,所以对每一个节点有更多的交互逻辑。所以,将x6的Shape抽象成组件,每一个组件负责管理自己的生命周期。
  2. 针对复杂的自定义图形,利用x6支持渲染html组件antv-x6-html2的功能,节点渲染交给当前组件,将图形相关逻辑交给x6。

Online Demos

  1. 基础示例使用了antdInputNumber(一个带按钮的输入框)展示了自定义组件如何做到和x6做数据交互
  2. swimlane 泳道图参照x6官方示例实现
  3. DAG画布参照x6官方的DAG示例实现AlgoNode的节点逻辑与官方示例相比较处理起来更简单
  4. ER图参照x6官方的ER图示例
  5. 展开收起树形图参照x6官方的示例

安装

yarn add antv-x6-react

Components

shape 名称描述
Noderect等同于Shape.Rect
Edgeedge等同于Shape.Edge
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.Edgeedge边。
Shape.DoubleEdgedouble-edge双线边。
Shape.ShadowEdgeshadow-edge阴影边。

另外提供帮助函数

名称描述
useCell使用这个函数可以通过传递markup之类的参数自定义节点
useCellEvent通过这个函数绑定事件到cell上面
useNodeSize通过这个函数可以按照react节点内部渲染的大小调整节点大小
名称描述
Grid渲染网格
Background渲染背景
Scroller滚动组件
Clipboard剪贴板,配合Keyboard组件可以使用ctrl+c/ctrl+x/ctrl+v
Keyboard键盘快捷键
MouseWheel鼠标滚轮,支持使用滚轮实现画布放大缩小
Connecting配置连线相关参数和帮助方法
名称描述
Snapline对齐线
Selection点选/框选
MiniMap小地图
Contextmenu右键菜单

demo

import Graph, { Grid, Background, Clipboard, Keyboard, MouseWheel, Connecting } from './lib'
import { Node, Edge, ReactNode } from './lib'
import { Selection, MiniMap, ContextMenu, Portal } from './lib'


function Node1(props: any) {
  // 自动按照内部节点大小更新x6节点大小
  useNodeSize(props)
  const { node, data = {} } = props;
  const { num = 0 } = data;
  return (
    <div style={{width: 150, border: '1px solid'}}>
      <Button onClick={(e) => node.setData({ num: num + 1 })}>
        Ant Button {num}
      </Button>
      <InputNumber value={num} onChange={num => node.setData({ num })} />
    </div>
  );
}

function App() {
  return (
    <div className="App">
      {/* 内部会自动判断,只要这个组件被挂载了就使用portal模式,否则使用ReactDOM.render */}
      <PortalProvider />
      <Graph>
        <Grid />
        <Background />
        <Clipboard />
        <Keyboard />
        <MouseWheel />
        <Selection />
        <Connecting />
        <Node id="1" x="100" y="100" label="node1" />
        <Node id="2" x="200" y="200" label="node2" />
        <ReactNode id="999" x="650" y="200" data={{num: 2}} component={Node1} />
        <ReactNode id="99" x="500" y="200" data={{num: 2}} component={Node1} />
        <ReactNode id="9" x="500" y="300" data={{num: 2}} component={Node1} primer="circle" />
        <Edge source="1" target="2" />
        <ContextMenu>
          <Menu style={{background: '#fff'}}>
            <Menu.Item>菜单1</Menu.Item>
            <Menu.Item>菜单2</Menu.Item>
            <Menu.Item>菜单3</Menu.Item>
          </Menu>
        </ContextMenu>
      </Graph>
    </div>
  );
}