antv/x6 @2.13.1学习笔记

关于antv/x6 2.0的一些基本使用

antv/x6

注册节点

	Graph.registerNode(
			'custom-rect',
			{
				inherit: 'rect',
				width: 66,
				height: 36,
				attrs: {
					body: {
						strokeWidth: 1,
						stroke: '#d2dae3',
						fill: '#fff',
					},
					text: {
						fontSize: 14,
						fill: '#262626',
					},
				},
				ports: { groups: {
                 group3: {
                 position: 'top',
                attrs: { circle },
               },
              group4: {
                position: 'bottom',
                attrs: { circle },
              },
            },
            items: [{ group: 'group3' }, { group: 'group4' }], },
			},
			true,
		)

自定义注册节点

export class StepNode extends Component {
  render() {
    const { node, graph, disabled } = this.props;
    const label = node.prop('label');
    const data = node.getData();
    return (
      
{label}
); } } 使用 import { StepNode } from '@c/x6Node'; chart_register_node = () => { register({ shape: 'custom-react-step', width: 200, height: 32, effect: ['data'], component: , }); };

初始化画布

import { Snapline } from '@antv/x6-plugin-snapline'  //对齐线
import { Clipboard } from '@antv/x6-plugin-clipboard' // 复制粘贴
import { Selection } from '@antv/x6-plugin-selection'  //选中状态 ,需配合样式使用
import { Keyboard } from '@antv/x6-plugin-keyboard'  //键盘事件
draw = data => {
		if (window.graph) {
			window.graph.fromJSON(data || '')
			return
		}
		let g = new Graph({
			container: this.ref.current,
		 connecting: {
    connector: { name: 'smooth' },
    createEdge() {
      return new Shape.Edge({
        attrs: {
          line: {
            stroke: '#0CB9DD',
            strokeWidth: 1,
          },
        },
        zIndex: -1,
      });
    },
    router: {
      name: 'normal', //’manhattan‘:智能正交路径
      args: {
        // offset: 25,
        // direction: 'H',
      },
    },
    allowMulti: false, // 是否允许在相同的起始节点和终止之间创建多条边,默认为 true。
    allowBlank: false,
    sourceAnchor: {
      name: 'bottom', // 锚点会在节点右侧中心往上偏移 10px
      args: {
        dy: 0,
      },
    },
    targetAnchor: {
      name: 'top', // 锚点会在节点右侧中心往上偏移 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, // 主次网格线间隔
      },
    ],
  },
			embedding: {
				enabled: true,
				findParent({ node }) {
					const bbox = node.getBBox()
					return this.getNodes().filter(n => {
						const data = n.getData()
						if (data && data.parent) {
							const targetBBox = n.getBBox()
							return bbox.isIntersectWithRect(targetBBox)
						}
						return false
					})
				},
			},
		})
		g.fromJSON(data ) // 渲染元素
		// g.centerContent(); // 居中显示
		g.use(new Keyboard())
		g.use(new Snapline({ enabled: true }))
		g.use(new Clipboard({ enabled: true, useLocalStorage: true }))
		g.use(
			new Selection({
				enabled: true,
				multiple: true,
				rubberEdge: true,
				rubberNode: true,
				modifiers: 'shift',
				rubberband: true,
				// showEdgeSelectionBox: true,
				// showNodeSelectionBox: true,
			}),
		)
		window.graph = g
		this.chart_add_events(g)
		this.props.initDrag(g)
	}
**css** 
		.x6-node-selected rect {
			// border-color: #1890ff;
			stroke: #1890ff;
			border-radius: 2px;
			box-shadow: 0 0 0 4px #d4e8fe;
		}
		.x6-node-selected .node-step {
			border-color: #1890ff;
			border-radius: 2px;
			box-shadow: 0 0 0 4px #d4e8fe;
		}
		.x6-edge:hover path:nth-child(2) {
			stroke: #1890ff;
			stroke-width: 1px;
		}

		.x6-edge-selected path:nth-child(2) {
			stroke: #1890ff;
			stroke-width: 1.5px !important;
		}

注册事件

	chart_add_events = g => {
		g.on('edge:connected', ({ e, edge }) => {
			const { source, target } = edge
			g.getEdges().forEach(e => {
				e.setAttrs(LineAttr)
			})
		})
		g.on('node:click', ({ node }) => {
			this.setState({
				info: { ...node.getData(), nodeId: node.id },
			})
		})

		g.on('node:dblclick', ({ node }) => {
			const { index } = this.state
			if (index !== 0) {
				this.setState({
					index: 0,
					info: { ...node.getData(), nodeId: node.id },
				})
			} else {
				this.setState({
					info: { ...node.getData(), nodeId: node.id },
				})
			}
		})

		g.on('blank:click', e => {
			this.onClose()
			setTimeout(() => {
				this.setState({
					info: {},
				})
			}, 100)
		})

		g.bindKey('delete', () => {
			const cells = g.getSelectedCells()
			console.log(cells, 'cells')
			if (cells && cells.length) {
				g.removeCells(cells)
			}
			return false
		})
	}
	

Dnd拖拽组件

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

	initDrag = target => {
		this.dnd = new Dnd({
			target,
			scaled: false,
			dndContainer: this.ref.current,
		})
	}

	startDrag = (e, v) => {
		const g = window.graph
		const { x, y } = window.graph?.graphToLocal()
		const config = {
			shape: 'custom-rect',
			...size1,
			x,
			y,
			ports,
			label: v.name,
			data: v,
			zIndex: 3,
		}
		this.dnd.start(g.createNode(config), e.nativeEvent)
	}
	render() {
		const { loading } = this.state
		return (
			
) }

导出

  handleExport = () => {
    const json = window.graph?.toJSON();
    const cells = json?.cells;
    exportFileJSON(cells, `导出.json`);
  };
  // 对象导出为json文件
export const exportFileJSON = (data, filename) => {
  if (typeof data === 'object') {
    data = JSON.stringify(data, null, 4);
  }
  // 导出数据
  const blob = new Blob([data], { type: 'text/json' }),
    e = new MouseEvent('click'),
    a = document.createElement('a');

  a.download = filename;
  a.href = window.URL.createObjectURL(blob);
  a.dataset.downloadurl = ['text/json', a.download, a.href].join(':');
  a.dispatchEvent(e);
};

导入

 handleImport = (a) => {
    const num = this.state.count;
    importFileJSON(a)
      .then((data) => {
        if (Array.isArray(data)) {
          const g = window.graph;
          let json = g.toJSON();
          let list = data.map((v, i) => {
            if (v.id) {
              v.id = v.id + num;
            }
            if (v.ports) {
              v.ports.items.forEach((vs) => vs + num);
            }
            if (v.source) {
              v.source.cell = v.source.cell + num;
              v.source.port = v.source.port + num;
            }
            if (v.target) {
              v.target.cell = v.target.cell + num;
            }
            return v;
          });
          json.cells = json.cells.concat(list);
          g.fromJSON(json);
          this.setState({ count: this.state.count + 1 });
        }
      })
      .catch((e) => {
        message.error(e);
      });
  };
// 导入解析json文件
export const importFileJSON = (ev) => {
  return new Promise((resolve, reject) => {
    const fileDom = ev.target,
      file = fileDom.files[0];

    // 格式判断
    if (file.type !== 'application/json') {
      reject('仅允许上传json文件');
    }
    // 检验是否支持FileRender
    if (typeof FileReader === 'undefined') {
      reject('当前浏览器不支持FileReader');
    }

    // 执行后清空input的值,防止下次选择同一个文件不会触发onchange事件
    ev.target.value = '';

    // 执行读取json数据操作
    const reader = new FileReader();
    reader.readAsText(file); // 读取的结果还有其他读取方式,我认为text最为方便

    reader.onerror = (err) => {
      reject('json文件解析失败', err);
    };

    reader.onload = () => {
      const resultData = reader.result;
      if (resultData) {
        try {
          const importData = JSON.parse(resultData);
          resolve(importData);
        } catch (error) {
          reject('读取数据解析失败', error);
        }
      } else {
        reject('读取数据解析失败');
      }
    };
  });
};

你可能感兴趣的:(javascript,前端,react)