0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

フローチャート描画とデータ連携

Last updated at Posted at 2022-09-11

フローチャート作成・描画をマウス操作で行い、データ連携させる

フローチャートをGUIで作図し、一覧のデータと連携させるということをやったので備忘録です。
主にライブラリに頼りますので、以下のようなものを使いました。

  • vis.js
  • joint.js

vis.js

vis.jsのサンプルです。
オプションについては公式に詳細があるのでそちらを。
vis.js

data: any;

network: Network;
nodes: any;
edges: any;

const nodeData: any[] = [];
    for (const element of ELEMENTLIST) {
      nodeData.push({id: element.elementId, label: element.elementName});
    }

    const nodes = new DataSet(nodeData);
    const edges = new DataSet([
      {from: '01', to: '02'},
      {from: '01', to: '03'},
      {from: '02', to: '04'},
      {from: '02', to: '05'},
    ]);

    // create a network
    this.data = {
      nodes: nodes,
      edges: edges
    };
    const options = {
      layout: {
        hierarchical: {
          sortMethod: 'directed'
        },
      },
      interaction: {
        dragNodes: false,
        dragView: false,
        hover: true,
      },
      manipulation: {
        enabled: false,
        initiallyActive: false,
        addEdge: function (data, callback) {
          console.log('add edge', data);
          if (data.from === data.to) {
              const r = confirm('Do you want to connect the node to itself?');
              if (r === true) {
                  callback(data);
              }
          } else {
              callback(data);
          }
          // after each adding you will be back to addEdge mode
          this.network.addEdgeMode();
        },
        controlNodeStyle: {
          // all node options are valid.
        }
      },
      edges: {
        arrows: 'to',
        smooth: false
      },
      nodes: {
        shape: 'box',
      },
      physics: {
        enabled: true,
        hierarchicalRepulsion: {
            nodeDistance: 180,
        },
        solver: 'hierarchicalRepulsion'
      }
    };
    this.network = new Network(this.visElement.nativeElement, this.data, options);
    this.network.addEdgeMode();

joint.js

途中でこっちに乗り換えました。
使い勝手とカスタマイズ性がこちらの方が良さそうだったので。

this.graph = new joint.dia.Graph;
    const paper = new joint.dia.Paper({
      el: document.getElementById('myholder'),
      width: '200vh',
      height: '100vh',
      model: this.graph,
      background: {
        color: '#eaeaea',
      },
      gridSize: 10,
      drawGrid: {
        color: '#efefef',
        name: 'mesh'
      },
      restrictTranslate: true,
      defaultRouter: { name: 'manhattan' },
      defaultLink: new joint.dia.Link({
        attrs: { '.marker-target': { d: 'M 10 0 L 0 5 L 10 10 z', stroke: '#505050', fill: '#505050' }, '.connection' : { stroke: '#505050', strokeWidth: 2 } }
      }),
      linkPinning: false,
      validateConnection: function(cellViewS, magnetS, cellViewT, magnetT, end, linkView) {
        // Prevent linking from input ports.
        if (magnetS && magnetS.getAttribute('port-group') === 'in') {
          return false;
        }
        // Prevent linking from output ports to input ports within one element.
        if (cellViewS === cellViewT) {
          return false;
        }
        // Prevent linking to input ports.

        return magnetT && magnetT.getAttribute('port-group') === 'in';
      },
      validateMagnet: function(cellView, magnet) {
          // Note that this is the default behaviour. Just showing it here for reference.
          // Disable linking interaction for magnets marked as passive (see below `.inPorts circle`).
          return magnet.getAttribute('magnet') !== 'passive';
      }
    });
    paper.scale(0.8);

エレメントの設定はこんな感じ。 詳細はhttp://visjs.org/docs/network/
export const layout = {
  size: { width: 200, height: 80 },
  inPorts: ['in'],
  outPorts: ['out'],
  ports: {
      groups: {
          'in': {
              attrs: {
                  '.port-body': {
                      fill: '#16A085',
                      magnet: 'passive'
                  }
              },
              position: 'top',
          },
          'out': {
              attrs: {
                  '.port-body': {
                      fill: '#E74C3C'
                  }
              },
              position: 'bottom'
          }
      }
  },
  attrs: {
      '.label': { text: 'agra', 'ref-x': .5, 'ref-y': .2 },
      rect: { fill: '#2ECC71' }
  },
  strokeWidth: 0,
  cursor: 'pointer',
  magnet: true,
  label: {
    fill: '#333333',
    fontWeight: 'bold',
    cursor: 'pointer',
  },
  rect: {
    fill: 'red'
  },
  refPoints: '0,10 10,0 20,10 10,20',
  filter: {
    name: 'dropShadow',
    args: {
      dx: 2,
      dy: 2,
      blur: 3,
      angle: 50,
    }
  },
  defaultFill: {
    type: 'linearGradient',
    stops: [
      { offset: '0%', color: '#ffffff' },
      { offset: '100%', color: '#e2f1fc' },
    ],
    attrs: { x1: '0%', y1: '0%', x2: '0%', y2: '100%' }
  },
  executingFill: {
    type: 'linearGradient',
    stops: [
      { offset: '0%', color: '#fac695' },
      { offset: '37%', color: '#f5ab66' },
      { offset: '100%', color: '#ef8d31' },
    ],
    attrs: { x1: '0%', y1: '0%', x2: '0%', y2: '100%' }
  },
};

リンク追加はこんな感じです。

new joint.dia.Link({
      source: {
        id: source,
        port: ' '
      },
      target: {
        id: target,
        port: ''
      },
      attrs: {
        '.marker-target': { d: 'M 10 0 L 0 5 L 10 10 z', stroke: '#505050', fill: '#505050' }, '.connection' : { stroke: '#505050', strokeWidth: 2 }
      }
    });

データ連携

作りたいエレメントとリンクの数だけ回せばデータができる。
エレメントの追加や動的なリンク情報取得は同様にaddしたり、portのリンク情報取得するだけ。
グラフのイベント発火を待ってデータ取得する。

this.paper.on('link:connect', (linkView, evt, cellView, magnet, arrowhead) => {
  this.graph.getConnectedLinks(
    this.graph.attributes.cells._byId[linkView.model.attributes.source.id],
    { outbound: true}
  )
}

総括

ライブラリの使い方という感じになってしまいましたが、どのライブラリも情報少ないし使いづらい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?