tnpm install @tencent/bkflow
import D3Graph from '@tencent/bkflow'
let flowGraph = null // 全局定义,不要定义到Vue的data里面,D3数据绑定和Vue数据绑定冲突
flowGraph = new D3Graph('#flowgraph', options)
参数 |
说明 |
类型 |
可选值 |
默认值 |
mode |
画布模式, 编辑(edit)模式可以拖拽、点击节点,只读模式(readonly)会屏蔽拖拽、点击事件 |
String |
edit / readonly |
readonly |
background |
背景颜色 |
String |
—— |
#ddd |
renderVisibleArea |
是否只渲染可视区域内模板 |
Boolean |
—— |
false |
canvasPadding |
画布填充 |
Object |
—— |
{ x: 0, y: 0 } |
autoBestTarget |
自动连接最优连线 |
Boolean |
true / false |
true |
nodeConfig |
渲染节点模板配置 |
Array |
—— |
[{ type: 'default', width: 30, height: 30, radius: '50%' }], |
nodeTemplateKey |
匹配节点模板的key, 对应NodeConfig里面的模板类型的Key,这个Key需要在节点信息里面包含 |
String |
—— |
type |
zoom |
缩放相关 |
Object |
—— |
—— |
zoomFilter |
缩放的过滤函数,可以根据实际情况设置其缩放行为,参数为event 。默认情况下配置了 zoom 后所有行为均允许缩放。 |
Function |
—— |
—— |
lineConfig |
连线配置, 分别配置连线颜色和hover颜色 |
Object |
—— |
—— |
nodeClick |
节点点击事件类型(D3的Zoom会影响mouseup,hover弹出元素初次点击节点不触发click、mouseup,因此重写了click事件,根据需要选择是否启用) |
String |
native(原生事件) / Refactoring(重构点击事件) |
native |
onNodeRender |
节点渲染时的回调函数, 返回Html字符串 |
Function |
—— |
—— |
onLineConnectBefore |
完成连线之前的回调函数 |
Function |
—— |
—— |
onLineDelete |
删除连线之前函数 |
Function |
—— |
—— |
tree |
渲染树形结构配置 |
Object |
—— |
参考下面Tree配置 |
- 可配置多个模板,不同节点根据指定的type获取对应的配置,渲染图形宽度、高度、radius
- type: 节点类型,对应渲染画布的数据中不同模板, 此处的type为默认值,和nodeTemplateKey配合使用,nodeTemplateKey 定义此处key的名称,方便渲染数据处不同key的需求
- width:节点宽度,目前只支持'px'
- height:节点高度, 目前只支持'px'
- radius:节点四个角半径,String类型,可以是px|em|rem|n%|vw|vh
tree: {
// TODO: horizontal 调试渲染结果
mode: 'vertical', // horizontal | vertical,
node: {
width: 300,
height: 50
}
}
// 必须调用方法:
/**
* 渲染Tree
* @param {*} treeData 渲染数据 { name: '', children: [] } 可以是数组,数组的话渲染多棵树
* @param {*} id id字段
* @param {*} name name字段
*/
instance.renderTree(treeData, 'spanID', 'spanID')
参数 |
说明 |
类型 |
可选值 |
默认值 |
mode |
树形结构方向 |
String |
vertical/horizontal |
vertical |
node |
节点配置(目前只支持设置宽高) |
Object |
-- |
{ width: 300, height: 50 } |
zoom: {
scaleExtent: [1, 1],
controlPanel: false,
tools: []
}
参数 |
说明 |
类型 |
可选值 |
默认值 |
scaleExtent |
缩放倍数限制,默认为[1, 1], 即不可进行缩放操作 |
Array |
—— |
[1, 1] |
controlPanel |
缩放控制板,默认关闭 |
Boolean |
true / false |
false |
tools |
控制面板放大、缩小、还原的icon和text |
Object |
-- |
-- |
[{
text: '放大',
icon: 'icon-plus-circle',
type: 'zoomIn'
}, {
text: '缩小',
icon: 'icon-minus-circle',
type: 'zoomOut'
}, {
text: '还原',
icon: 'icon-full-screen',
type: 'resetPosition'
}]
{
canvasLine: false, // canvas模式(大数据渲染时启用Canvas模式。默认svg模式)渲染连线
color: '#ddd',
activeColor: '#3a84ff'
}
flowGraph.on('fn', callback)
方法名 |
说明 |
参数说明 |
nodeDblClick |
节点双击事件 |
(node, event) |
nodeMouseEnter |
鼠标滑入节点事件 |
(node, event) |
nodeMouseLeave |
鼠标离开节点事件 |
(node, event) |
nodeDragEnd |
节点拖拽结束事件 |
(node, event) |
lineConnected |
连线结束事件 |
(node, event) |
nodeClick |
节点点击事件 |
(node, event) |
/** 对外分发事件 */
const EVENTS = {
/** 可视区域改变事件 */
VISIBLE_AREA_CHANGED: 'visibleAreaChanged',
/** 可视区域移动中 */
VISIBLE_AREA_CHANGING: 'visibleAreaChanging',
/** 更新可视区域节点之前事件 */
BEFORE_VISIVLE_NODE_UPDATE: 'beforeVisibleNodeUpdate',
/** 配置节点渲染时回调,可在此处返回节点模板 */
ON_NODE_RENDER: 'onNodeRender',
/** 结束连线之前 */
ON_LINE_CONNECT_BEFORE: 'onLineConnectBefore',
/** 连线完成 */
ON_LINE_CONNECTED: 'lineConnected',
ON_NODE_MOUSE_ENTER: 'nodeMouseEnter',
ON_NODE_MOUSE_LEAVE: 'nodeMouseLeave',
ON_NODE_MOUSE_DOWN: 'nodeMousedown',
ON_NODE_MOUSE_UP: 'nodeMouseup',
/** 画布拖拽结束 */
ON_CANVAS_DRAG_END: 'canvasDragEnd',
/** 画布拖拽开始 */
ON_CANVAS_DRAG_START: 'canvasDragStart',
/** 节点拖拽结束 */
ON_NODE_DRAG_END: 'nodeDragEnd',
/** 节点鼠标左键双击事件 */
ON_NODE_DBCLICK: 'nodeDblClick',
ON_NODE_CLICK: 'nodeClick',
/** 连线删除点击事件 */
ON_LINE_DELETE_CLICK: 'lineDeleteClick',
ON_LINE_MOUSE_ENTER: 'lineMouseEnter',
ON_LINE_MOUSE_LEAVE: 'lineMouseLeave'
}
注意:
组件默认抛出的所有事件都是注册到了最外层的容器DOM元素,如果需要针对渲染的节点模板内部监听具体的元素事件,请根据DOM属性判断(Class、Attribute、ID)等
举个例子:
监听节点内部的一个ICON的点击事件
/** 监听点击事件 **/
handleGraphNodeClick(e, data) {
const nodeId = data.id
/** 处理点击事件样式改变 **/
this.handleClickedNodeClass(nodeId, e)
/** 根据点击DOM Class判断具体行为 **/
if (/__bk-node-setting/.test(e.target.className)) {
const index = this.graphData.locations.findIndex(node => node.id === nodeId)
if (index >= 0) {
/** 删除节点 **/
if (/bk-delete/.test(e.target.className)) {
this.handleDeleteNode(index, data)
}
/** 复制节点 */
if (/bk-copy/.test(e.target.className)) {
const sourceNode = this.graphData.locations[index]
this.handleCopyNode(sourceNode)
}
/** 查看更多 **/
if (/icon-more/.test(e.target.className)) {
this.handleAppendMoreAction(data)
}
}
}
/** 点击关联任务,查看 */
if (/icon-chain/.test(e.target.className)) {
this.handleNodeDblClick(data, 'referTask')
}
}
var data = {
locations: [
{ id: 'node1', x: 100, y: 100 },
{ id: 'node2', x: 280, y: 100 },
{ id: 'node3', x: 460, y: 100 },
{ id: 'node4', x: 400, y: 220 }
],
lines: [
{ id: 'line1', source: {id: 'node1'}, target: {id: 'node2'} },
{ id: 'line2', source: {id: 'node2'}, target: {id: 'node3'} },
{ id: 'line3', source: {id: 'node3'}, target: {id: 'node4'} },
]
}
key |
说明 |
locations |
节点配置信息 |
lines |
连线配置信息 |
var instance = new bkflow('#graph-wrapper', {
mode: 'readonly',
nodeConfig: [{ type: 'default', width: 70, height: 40, radius: '2px'}],
lineConfig: {canvasLine: false, color: '#a9adb6', activeColor: '#3a84ff'},
onNodeRender: function (node) {
return '<div class="node-item">'+ node.id +'</div>'
}
})
instance.renderGraph(data)
mounted() {
flowGraph = new D3Graph('#flowgraph', {
mode: 'edit',
nodeTemplateKey: 'groupTemplate',
canvasPadding: { x: 15, y: 15 },
background: 'rgba(0,0,0,0)',
lineConfig: {
canvasLine: false,
color: '#c4c6cc',
activeColor: '#3a84ff'
},
nodeConfig: [
{ groupTemplate: 'graph-square', width: 62, height: 62, radius: '4px' },
{ groupTemplate: 'graph-round', width: 72, height: 72, radius: '50%' },
{ groupTemplate: 'graph-ractangle', width: 225, height: 42, radius: '4px' }
],
zoom: {
scaleExtent: [0.5, 3],
controlPanel: true
},
nodeClick: 'Refactoring',
onNodeRender: node => new NodeTemplate(node).getTemplateById(node.groupTemplate, this.isReadonly && 'readonly' || 'edit', this.action),
onLineConnectBefore: this.beforeLineConnected,
onLineDelete: this.beforeLineDelete
})
.on('nodeDblClick', (node, event) => {
if (!this.isReadonly) {
this.handleNodeDblClick(node)
}
}, 'node')
.on('nodeMouseEnter', (node, event) => {
if (this.action === 'monitor') {
this.activeNode = node
this.$refs['bkGraphMonitor'].handleMouseenter(event)
}
}, 'node')
.on('nodeMouseLeave', (node, event) => {
if (this.action === 'monitor') {
this.activeNode = node
this.$refs['bkGraphMonitor'].handleMouseleave(event)
}
}, 'node')
.on('nodeDragEnd', (node, event) => {
this.updateLocations(node)
}, 'node')
.on('lineConnected', (line, evt) => {
this.updateLines(line)
}, 'line')
.on('nodeClick', (node, event) => {
!this.isReadonly && this.handleGraphNodeClick(event, node)
}, 'node')
}