D3.jsのV3バージョン-Vueフレームワークで使用(第10章)---フローチャート



V3 Version D3 Js Used Vue Framework Flowchart



エフェクト表示



2.dagre-d3を使用する



dagre-d3ライブラリ、d3プロセスライブラリをインストールする必要があります。

3.コード例(パッケージコンポーネント)

メインコードは次のように説明しています。



//フローチャート描画オブジェクトを取得します

this.graph = new dagreD3.graphlib.Graph()。setGraph({

//方向を制御します

ランクディレクトリ:this.direction

})。setDefaultEdgeLabel(function(){return {}})

//ノードを描画します

this.graph.setNode()

//接続を描画します

this.graph.setEdge()

ヒント:詳細な使用法については、公式Webサイトにアクセスして問い合わせることができます。

div.dagre-graph-container(:id='containerId') div.zoom-div button(v-for='item in directions' :key='item.prop' @click='direction = item.prop') {{item.label}} Button.zoom(@click='zoomCtrl('in')') Zoom out Button(@click='zoomCtrl('out')') svg.dagre g.container /** * Flow chart */ import * as d3 from 'd3' import dagreD3 from 'dagre-d3' let container = null export default { name: 'DagreGraph', props: ['nodes', 'edges'], data() { return { id: '', renderer: null, graph: null, direction: 'LR', directions: [ { prop: 'LR', Label: 'from left to right' }, { prop: 'RL', Label: 'from right to left' }, { prop: 'TB', Label: 'from top to bottom' }, { prop: 'BT', Label: 'from bottom to top' } ], zoom: null, containerId: '', width: 0, height: 0 } }, created() { this.containerId = this.uuid() this.graph = new dagreD3.graphlib.Graph().setGraph({ rankdir: this.direction }).setDefaultEdgeLabel(function () { return {} }) }, methods: { uuid () { function s4 () { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1) } return ( s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4() ) }, zoomCtrl (symbal) { let scale = symbal === 'out' ? 1.1 : 0.8 const svg = d3.select(this.$el).select('svg.dagre') this.zoom.scaleBy(svg, scale) }, /** * @description control the canvas zoom to up or down */ zoomed () { d3.select(this.$el).select('g.container').attr('transform', d3.event.transform) }, /** * @description draw node */ strokeNodes () { / / Get the previous nodes cache and clear let nodes = this.graph.nodes() if (nodes.length) { nodes.forEach( item => { this.graph.removeNode(item) } ) } / / draw shape by operator (BranchPythonMapOperator: branch JoinOperator: merge) this.nodes.forEach( (item) => { let state = item.state ? item.state : 'no-status' let shape = 'rect' if (item.value.operator === 'BranchPythonMapOperator') { shape = 'ellipse' } else if (item.value.operator === 'JoinOperator') { shape = 'circle' } this.graph.setNode(item.id, {label: item.value.label, shape: shape, class: item.value.operator + ' dagre ' + state}) } ) this.renderer(container, this.graph) }, /** * @description line drawing */ strokeEdges () { / / A script node: do not render eage if (this.nodes.length > 1) { this.edges.forEach( (item) => { if (item.label) { this.graph.setEdge(item.from, item.to, {label: item.label}) } else { this.graph.setEdge(item.from, item.to) } } ) this.renderer(container, this.graph) } } }, mounted () { this.width = document.getElementById(this.containerId).clientWidth this.height = document.getElementById(this.containerId).clientHeight // eslint-disable-next-line this.renderer = new dagreD3.render() const svg = d3.select(this.$el).select('svg.dagre') .attr('width', this.width) .attr('height', this.height) container = svg.select('g.container') // transform const transform = d3.zoomIdentity.translate(this.width / 3, this.height / 6).scale(1) this.zoom = d3.zoom() .scaleExtent([1 / 2, 8]) .on('zoom', this.zoomed) container.transition().duration(750).call(this.zoom.transform, transform) svg.call(this.zoom) this.strokeNodes() this.strokeEdges() }, watch: { nodes () { this.strokeNodes() }, edges () { this.strokeEdges() }, direction () { this.graph.setGraph({ rankdir: this.direction }) this.renderer(container, this.graph) } } } .edgePath path { stroke: #333 fill: #333 stroke-width: 1.5px } /************ Chart variable ***************/ $fail: #f77d6b $success: #61b2e4 $running: #87d86f $skipped: #faec91 $queued: #43e3ed $retry: #f8b96c $no-status: #fff $upstream_failed: rgb(163, 108, 108) /**************** dagre node graph **************************/ g.node.dagre { tspan { fill: #fff cursor: pointer } &.no-status { rect { stroke: #333 fill: #fff } ellipse { stroke: #333 fill: #fff } circle { stroke: #333 fill: #fff } tspan { fill: #333 } } &.success { rect { stroke: #fff fill: $success } ellipse { stroke: #fff fill: $success } circle { stroke: #fff fill: $success } } &.failed { rect { stroke: #fff fill: $fail } ellipse { stroke: #fff fill: $fail } circle { stroke: #fff fill: $fail } } &.upstream_failed { rect { stroke: #fff fill: $upstream_failed } ellipse { stroke: #fff fill: $upstream_failed } circle { stroke: #fff fill: $upstream_failed } } &.running { rect { stroke: #fff fill: $running } ellipse { stroke: #fff fill: $running } circle { stroke: #fff fill: $running } } &.skipped { rect { stroke: #fff fill: $skipped } ellipse { stroke: #fff fill: $skipped } circle { stroke: #fff fill: $skipped } } &.queued { rect { stroke: #fff fill: $queued } ellipse { stroke: #fff fill: $queued } circle { stroke: #fff fill: $queued } } &.BashOperator { &:hover { & > rect { cursor: pointer fill: #7cc9fa } } } &.BranchPythonMapOperator { &:hover { & > ellipse { cursor: pointer fill: #c52bd3 } } } &.JoinOperator { &:hover { & > circle { cursor: pointer fill: #0beb8d } } } } .zoom { margin-left: 40px }

4.コンポーネント呼び出し

div.dagre-graph-container Dagre-Graph(:nodes='nodes' :edges='edges') /** * Flow chart */ import DagreGraph from './DagreGraph' export default { name: 'FlowDiagram', data() { return { nodes: [], edges: [] } }, created() { this.init() }, methods: { init () { this.nodes = [ { id: 'e1', state: '', value: { Label: 'start', operator: 'BashOperator' } }, { id: 'e2', state: 'success', value: { Label: 'branch one', operator: 'BranchPythonMapOperator' } }, { id: 'e3', state: 'success', value: { Label: 'Branch two', operator: 'BranchPythonMapOperator' } }, { id: 'e4', state: 'queued', value: { Label: 'node 3', operator: 'BashOperator' } }, { id: 'e5', state: 'failed', value: { Label: 'node 4', operator: 'BashOperator' } }, { id: 'e6', state: 'upstream_failed', value: { Label: 'end', operator: 'JoinOperator' } } ] this.edges = [ { from: 'e1', to: 'e2' }, { from: 'e1', to: 'e3' }, { from: 'e2', to: 'e4', Label: 'Condition 1' }, { from: 'e3', to: 'e5', Label: 'condition 2' }, { from: 'e4', to: 'e6' }, { from: 'e5', to: 'e6' } ] } }, components: { DagreGraph } } .dagre-graph-container { width: 100% height: 800px }