antvis / X6

🚀 JavaScript diagramming library that uses SVG and HTML for rendering.
https://x6.antv.antgroup.com
MIT License
5.76k stars 1.71k forks source link

请问如何导出或加载Graph的JSON数据? #57

Closed loongmxbt closed 4 years ago

loongmxbt commented 4 years ago

Expected Behavior

原先gg-editor或G6项目中通过data定义nodes和edges的json数据,可以方便找到Data或导出json。

import GGEditor, { Flow } from 'gg-editor';

const data = {
  nodes: [{
    type: 'node',
    size: '70*70',
    shape: 'flow-circle',
    color: '#FA8C16',
    label: '起止节点',
    x: 55,
    y: 55,
    id: 'ea1184e8',
    index: 0,
  }, {
    type: 'node',
    size: '70*70',
    shape: 'flow-circle',
    color: '#FA8C16',
    label: '结束节点',
    x: 55,
    y: 255,
    id: '481fbb1a',
    index: 2,
  }],
  edges: [{
    source: 'ea1184e8',
    sourceAnchor: 2,
    target: '481fbb1a',
    targetAnchor: 0,
    id: '7989ac70',
    index: 1,
  }],
};

<GGEditor>
  <Flow style={{ width: 500, height: 500 }} data={data} />
</GGEditor>

Current Behavior

目前通过 addNode 或 addEdge 添加元素后渲染,或是通过 graph.render(data)进行渲染。 如果绘图后这个data数据需要导出,请问在graph的哪个属性或函数里可以获取?

listeners: {selectionChanged: Array(2), root: Array(2), escape: Array(4), startEditing: Array(2), pan: Array(4), …}
isDisposed: false
disabled: false
options: {trackable: true, trackInfo: {…}, defaultShadowColor: "#808080", defaultShadowOffsetX: 2, defaultShadowOffsetY: 3, …}
container: div.graph
model: Model {listeners: {…}, maintainEdgeParent: true, cellIdPrefix: "cell-", cellIdPostfix: "", autoCreateCellId: true, …}
view: View {listeners: {…}, isDisposed: false, captureDocumentGesture: true, updateStyle: false, rendering: true, …}
renderer: Renderer {antialiased: true, minSvgStrokeWidth: 1, defaultTextShape: ƒ, defaultNodeShape: ƒ, defaultEdgeShape: ƒ, …}
selection: Selection {isDisposed: false, graph: ContextMenuAccessor, cells: Array(0)}
panX: 0
panY: 0
changeManager: ChangeManager {isDisposed: false, graph: ContextMenuAccessor}
eventloopManager: EventLoopManager {isDisposed: false, graph: ContextMenuAccessor, mouseListeners: Array(11), lastTouchX: 0, lastTouchY: 0, …}
viewportManager: ViewportManager {isDisposed: false, graph: ContextMenuAccessor}
pageBreakManager: PageBreakManager {isDisposed: false, graph: ContextMenuAccessor, horizontalPageBreaks: Array(0), verticalPageBreaks: Array(0)}
zoomManager: ZoomManager {isDisposed: false, graph: ContextMenuAccessor}
selectionManager: SelectionManager {isDisposed: false, graph: ContextMenuAccessor}
creationManager: CreationManager {isDisposed: false, graph: ContextMenuAccessor}
connectionManager: ConnectionManager {isDisposed: false, graph: ContextMenuAccessor}
retrievalManager: RetrievalManager {isDisposed: false, graph: ContextMenuAccessor}
styleManager: StyleManager {isDisposed: false, graph: ContextMenuAccessor}
validationManager: ValidationManager {isDisposed: false, graph: ContextMenuAccessor}
collapseManager: CollapseManager {isDisposed: false, graph: ContextMenuAccessor, collapseToPreferredSize: true}
overlayManager: OverlayManager {isDisposed: false, graph: ContextMenuAccessor}
groupManager: GroupManager {isDisposed: false, graph: ContextMenuAccessor}
sizeManager: SizeManager {isDisposed: false, graph: ContextMenuAccessor}
editingManager: EditingManager {isDisposed: false, graph: ContextMenuAccessor}
movingManager: MovingManager {isDisposed: false, graph: ContextMenuAccessor}
panningManager: PanningManager {isDisposed: false, graph: ContextMenuAccessor, damper: 0.16666666666666666, delay: 10, handleMouseOut: true, …}
cellEditor: CellEditor {isDisposed: false, textarea: null, editingCell: null, modified: false, autoSize: true, …}
tooltipHandler: TooltipHandler {listeners: {…}, isDisposed: false, disabled: true, graph: ContextMenuAccessor, ignoreTouchEvents: true, …}
cursorHandler: CursorHandler {listeners: {…}, isDisposed: false, disabled: false, graph: ContextMenuAccessor}
selectionHandler: SelectionHandler {listeners: {…}, isDisposed: false, disabled: false, graph: ContextMenuAccessor, handlers: Dictionary, …}
connectionHandler: ConnectionHandler {listeners: {…}, isDisposed: false, disabled: true, graph: ContextMenuAccessor, autoSelect: true, …}
guideHandler: GuideHandler {listeners: {…}, isDisposed: false, disabled: false, graph: ContextMenuAccessor, guide: null, …}
selectHandler: SelectCellHandler {listeners: {…}, isDisposed: false, disabled: false, graph: ContextMenuAccessor}
movingHandler: MovingHandler {listeners: {…}, isDisposed: false, disabled: false, graph: ContextMenuAccessor, preview: Preview, …}
panningHandler: PanningHandler {listeners: {…}, isDisposed: false, disabled: true, graph: ContextMenuAccessor, useLeftButtonForPanning: false, …}
contextMenuHandler: ContextMenuHandler {listeners: {…}, isDisposed: false, disabled: true, graph: ContextMenuAccessor, showing: false, …}
rubberbandHandler: RubberbandHandler {listeners: {…}, isDisposed: false, disabled: true, graph: ContextMenuAccessor, fadeOut: false, …}
keyboardHandler: KeyboardHandler {listeners: {…}, isDisposed: false, disabled: true, graph: ContextMenuAccessor, target: div.graph, …}
mouseWheelHandler: MouseWheelHandler {listeners: {…}, isDisposed: false, disabled: true, graph: ContextMenuAccessor, wheelZoomDelay: 10, …}

Possible Solution

Steps To Reproduce

  1. ...
  2. ...
  3. ...
Error Message & Stack Trace

```txt ```

Additional Context

Your Environment

bubkoo commented 4 years ago

渲染 JSON 数据

import { Graph } from '@antv/x6'

const container = document.getElementById('container')
const graph = new Graph(container)

graph.render({
  nodes: [
    {
      id: 'node-0',
      x: 60,
      y: 60,
      width: 80,
      height: 30,
      label: 'Hello',
    },
    {
      id: 'node-1',
      x: 240,
      y: 240,
      width: 80,
      height: 30,
      label: 'World',
    },
  ],
  edges: [
    {
      id: 'edge-0',
      source: 'node-0',
      target: 'node-1',
      label: 'Edge Label',
    },
  ],
})

以上数据中的 id 由用户定义,在 x6 中,只会在渲染时用于搜索关联关系,其他时候不会使用到这个 id。

导出 JSON 数据需要自己处理,API 现在还不够简洁,可以先用下面的方式。


const parent = graph.getDefaultParent()

graph.model.filterDescendants(
      cell => cell.getData() != null && graph.view.getState(cell) != null, // 过滤
      parent,
    )
    .forEach(cell => {
      // 这里可以拿到 cell 的相关数据
    })
loongmxbt commented 4 years ago

谢谢!之前这个方案试了一下,自己组合的确不太方便。请问直接导出graph data的API在roadmap中么?

我这里的使用场景是这样的,先通过x6来绘制基本图形得到graphData,一系列计算步骤后,增加其他结果数据到graphData中,然后再通过G6来渲染。

bubkoo commented 4 years ago

@loongmxbt 导出数据能力,我们还需要更多的思考,感觉这个 API 应该很不通用。

loongmxbt commented 4 years ago

因为G6渲染是通过装载data实现的,所以如果先使用x6图编辑器绘制图形,再通过 graph.data(data);graph.render(); 渲染数据,这时候就需要导出x6所绘制图形的data了。当时是这么考虑的。

import G6 from '@antv/g6';

const data = {
  nodes: [
    {
      id: 'node1',
      label: 'Circle1',
      x: 150,
      y: 150
    },
    {
      id: 'node2',
      label: 'Circle2',
      x: 400,
      y: 150
    }
  ],
  edges: [
    {
      source: 'node1',
      target: 'node2'
    }
  ]
};

const graph = new G6.Graph({
  container: 'container',
  width: 500,
  height: 500,
  defaultNode: {
    shape: 'circle',
    size: [ 100 ],
    color: '#5B8FF9',
    style: {
      fill: '#9EC9FF',
      lineWidth: 3
    },
    labelCfg: {
      style: {
        fill: '#fff',
        fontSize: 20
      }
    }
  },
  defaultEdge: {
    style: {
      stroke: '#e2e2e2'
    }
  }
});

graph.data(data);
graph.render();
bubkoo commented 4 years ago

嗯,我已经给自己开了 issue,导出数据的解构思考清楚了就会添加。

github-actions[bot] commented 4 years ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.

loongmxbt commented 4 years ago

@bubkoo 请问如何拿到 edges 数据 目前一级的cell都是node节点,在Cell.edges中有node关联的edges数据 例如 N1 -- Edge1 -- N2 N1和N2的Cell.edges均会有Edge1出现,假如网络拓扑较为复杂edges的这种重复表示是否会造成性能问题?

此外是否有方便的方法能取到所有的edges?谢谢!

x6-bot[bot] commented 3 years ago

This thread has been automatically locked because it has not had recent activity.

Please open a new issue for related bugs and link to relevant comments in this thread.