antv x6 v2 使用笔记

基础

  • 注意版本,x6不同版本对React的要求是不同的,也需要注意插件版本,不同版本的x6的api可能是不同的
  • x6 是一个图引擎,多用来画多节点关系的图
  • 最重要的概念就是 节点 Node 和 边 Edge
  • 节点和节点通过边链接,边从哪里出发,到哪里去,就需要连接桩,其实就是连接点
  • 可使用React和vue来自定义节点,也可以使用默认的svg节点
  • 有很多扩展插件,内置功能来实现节点的新增,删除,复制等
  • 每个节点和边都要唯一的 id ,节点被复制后,新节点的id也是不一样的,唯一的
  • 节点和边的父类是 Cell对象,都要x和y属性,表示位置,都要shape属性,边就是edge,node是自定义的或者是svg的(比如Rect矩形)
  • 画布上每个对象都要层级 zindex,和网页的一样,不设置的话,后者会在前者上,zindex越大,层级越高

基本使用

<div id="container"></div>

import {
    
     Graph } from "@antv/x6";
const graph = new Graph({
    
    
  container: document.getElementById("container"),
  width: 800,
  height: 600,
  background: {
    
    
    color: "#F2F7FA",
  },
});

画布对象

画布对象是整个结果,包含都有的东西的引用,可用来设置宽度,背景色,栅格样式,开启是否移动缩放,监听事件(节点的增加和删除等),操作节点和边等,
比如我的画布配置是

const graphConfig = {
    
    
  connecting: {
    
    
    router: {
    
    
      name: 'normal',//’manhattan‘:智能正交路径
      args: {
    
    
        // offset: 25,
        // direction: 'H',
      },
    },
    allowMulti: false, // 是否允许在相同的起始节点和终止之间创建多条边,默认为 true。
    allowBlank: false,
    sourceAnchor: {
    
    
      name: "right", // 锚点会在节点右侧中心往上偏移 10px
      args: {
    
    
        dy: 0,
      },
    },
    targetAnchor: {
    
    
      name: "left", // 锚点会在节点右侧中心往上偏移 10px
      args: {
    
    
        dy: 0,
      },
    },
    connectionPoint: "anchor",
  },
  // 鼠标拖动画布
  panning: true,
  // 鼠标缩放画布
  mousewheel: true,
  background: {
    
    
    color: '#F2F7FA',
  },
  grid: {
    
    
    visible: true,
    type: 'doubleMesh',
    args: [
      {
    
    
        color: '#eee', // 主网格线颜色
        thickness: 1, // 主网格线宽度
      },
      {
    
    
        color: '#ddd', // 次网格线颜色
        thickness: 1, // 次网格线宽度
        factor: 4, // 主次网格线间隔
      },
    ],
  },
}

以下为常用的方法


/**
* 使用插件
*/
graph.use(某插件)

/**
* 通过id找cell
*/
graph.getCellById("1234")

/**
** 复制一个节点,并带位移粘贴,如果一个节点有很多子节点,使用内置方法是最好的,避免大量运算
*/

graph.copy([node], {
    
    deep: true})
graph.paste({
    
    offset: {
    
    dx: 22, dy: 22}})


/**
** 获取当前画布左上角的坐标,使用场景是新建一个节点,在最上角,否则不好找
*/
graph.graphToLocal()


/**
** 从json数据生产整个画布
*/
graph.fromJSON(json)

/**
** 画布导出json数据
*/
graph.toJSON()

/**
** 节点操作
*/
// 得到所有的节点
g.getNodes();
// 新建节点,并放到画布上
graph.addNode()
// 新建节点,不放到画布上,使用场景比如,节点被拖入画布
graph.createNode()
// 新建边,并放到画布上
graph.addEdge()
// 新建边,不放到画布上
graph.createEdge()


/**
** 常用事件
*/

// 监听节点的连接事件,得到边
graph.on('edge:connected', ({
     
      isNew, edge }) => {
    
    })
// 节点的双击事件
graph.on('node:dblclick', ({
     
      node }) => {
    
    })
// 节点的单击事件
graph.on('node:click', ({
     
      node }) => {
    
    })
// 监听节点里,子节点的变化
graph.on('cell:change:children', (args) => {
    
    })
// 监听节点嵌入,就是被拖入父节点的事件
graph.on('node:embedded', (args) => {
    
    })

Cell

就是节点和边的父类,有一些公用的方法

// 删除
cell.remove()
// 设置尺寸
cell.setSize()
// 设置位置
cell.setPosition()
cell.clone()
// 位置尺寸
cell.getBBox()
// 上级
cell.parent
// 下级
cell.children
// 显示和隐藏
cell.show()
cell.hide()

群组

就是父节点里有子节点, 子节点会和父节点一起被拖动


let g = new Graph({
    
    
  container: this.ref.current,
  ...graphConfig,
  // 通过 embedding对象来控制群组,实现能不能拖拽进入父节点的功能
  embedding: {
    
    
    enabled: true,
    findParent({
     
      node }) {
    
    
      const bbox = node.getBBox();
      return this.getNodes().filter((n) => {
    
    
        if (node.shape === 'custom-react-node') {
    
    
          return false;
        }
        const data = n.getData();
        if (data && data.parent) {
    
    
          const targetBBox = n.getBBox();
          return bbox.isIntersectWithRect(targetBBox);
        }
        return false;
      });
    },
  },
});

// 给节点,添加子节点 
node.addChildren()

使用React自定义节点

节点自身的引用,画布的引用都可以取到,data就类似副作用,使用它来更新节点

import {
    
     register } from '@antv/x6-react-shape';


export class NodeProcess extends Component {
    
    

  toggle = () => {
    
    
    const {
    
    node} = this.props;
    const data = node.getData();
    let nextValue = !data.open;
    node.setData({
    
    open: nextValue})

    // 控制自身的长宽
    if (nextValue) {
    
    
      node.prop('size', {
    
    
        width: data.width || 720,
        height: data.height || 360
      });
    } else {
    
    
      node.prop('size', size);
    }
    // 子节点的显示隐藏
    if (Array.isArray(node.children)) {
    
    
      node.children.forEach(n => {
    
    
        if (nextValue) {
    
    
          n.show()
          if (n.children && n.children.length) {
    
    
            n.children.forEach(n1 => {
    
    
              n1.show()
            })
          }
        } else {
    
    
          n.hide()
          if (n.children && n.children.length) {
    
    
            n.children.forEach(n1 => {
    
    
              n1.hide()
            })
          }
        }
      })
    }
  }

  render() {
    
    
    const {
    
    node, graph ,disabled} = this.props;
    const label = node.prop('label');
    const data = node.getData();
    return (
      <div>
        {
    
    
          data.open ? (
            <div className="node-process-wrapper" style={
    
    {
    
    width: data.width || 720, height: data.height || 360}}>
              <div className={
    
    'node-process'}>
                {
    
    label}
                <RightOutlined onClick={
    
    () => this.toggle(false)}/>
              </div>
            </div>
          ) : (
            <div className={
    
    'node-process'}>
              {
    
    label}
              {
    
    
                data.sub.length >= 0 && <RightOutlined onClick={
    
    () => this.toggle(true)}/>
              }
            </div>
          )
        }
      </div>
    )
  }
}

register({
    
    
  shape: "custom-react-node",
  width: 100,
  height: 
  100,
  effect: ["data"],
  component: NodeProcess,
});

const node = graph.addNode({
    
    
  shape: "custom-react-node",
  x: 60,
  y: 100,
  data: {
    
    
    progress: 30,
  },
});

setInterval(() => {
    
    
  const {
    
     progress } = node.getData<{
    
     progress: number }>();
  node.setData({
    
    
    progress: (progress + 10) % 100,
  });
}, 1000);

插件

更多内容可以看官网文档

对齐线

import {
    
     Snapline } from "@antv/x6-plugin-snapline";
const graph = new Graph({
    
    
  background: {
    
    
    color: "#F2F7FA",
  },
});
graph.use(
  new Snapline({
    
    
    enabled: true,
  })
);

复制粘贴

import {
    
     Clipboard } from "@antv/x6-plugin-clipboard";

const graph = new Graph({
    
    
  background: {
    
    
    color: "#F2F7FA",
  },
});
graph.use(
  new Clipboard({
    
    
    enabled: true,
  })
);

快捷键

import {
    
     Clipboard } from "@antv/x6-plugin-clipboard";

const graph = new Graph({
    
    
  background: {
    
    
    color: "#F2F7FA",
  },
});
graph.use(
  new Clipboard({
    
    
    enabled: true,
  })
);

拖拽

import {
    
     Dnd } from "@antv/x6-plugin-dnd";

const graph = new Graph({
    
    
  background: {
    
    
    color: "#F2F7FA",
  },
});

const dnd = new Dnd({
    
    
  target: graph,
});

export default () => {
    
    
  const startDrag = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    
    
    // 该 node 为拖拽的节点,默认也是放置到画布上的节点,可以自定义任何属性
    const node = graph.createNode({
    
    
      shape: "rect",
      width: 100,
      height: 40,
    });
    dnd.start(node, e.nativeEvent);
  };

  return (
    <ul>
      <li onMouseDown={
    
    startDrag}></li>
    </ul>
  );
};

缩放

import {
    
     Transform } from '@antv/x6-plugin-transform'

graph
  .use(
    new Transform({
    
    
      resizing: true,
      rotating: true,
    })
  )

历史

import {
    
     History } from '@antv/x6-plugin-history'
graph.use(new History())

猜你喜欢

转载自blog.csdn.net/qq_29334605/article/details/130059390