butterfly-dag
Version:
一个基于数据驱动的节点式编排组件库,让你有方便快捷定制可视化流程图表
937 lines (598 loc) • 21.8 kB
Markdown
# 画布(Canvas)
```js
let canvas = new Canvas({
// 如下属性
root: dom, //canvas的根节点(必传)
layout: 'ForceLayout', //布局设置(选填),可使用集成的,也可自定义布局
zoomable: true, //可缩放(选填)
moveable: true, //可平移(选填)
draggable: true, //节点可拖动(选填)
linkable: true, //节点可连接(选填)
disLinkable: true, //节点可取消连接(选填)
layout: {}, //初始化自动布局(选填)
theme: { //主题定制(选填)
group: {
type: 'normal' //节点组类型(选填): normal(随意拖入拖出),inner(只能拖入不能拖出)
},
edge: {
type: 'Bezier', //线条默认类型
label: 'test', //线条默认label
arrow: true, //线条默认是否带箭头
arrowPosition: 0.5, //箭头位置(0 ~ 1)
arrowOffset: 0.0, //箭头偏移
arrowShapeType: '', //自定义箭头样式
Class: XXClass, //自己拓展的class,拖动连线的时候会采用该拓展类
isExpandWidth: false,//增加线条交互区域
defaultAnimate: false//默认开启线条动画
},
endpoint: {
position: [], //限制锚点位置['Top', 'Bottom', 'Left', 'Right'],
linkableHighlight: true,//连线时会触发point.linkable的方法,可做高亮
limitNum: 10, //限制锚点的连接数目
expandArea: { //锚点过小时,可扩大连线热区
left: 10,
right: 10,
top: 10,
botton: 10
}
},
zoomGap: 0.001, //鼠标放大缩小间隙设置
autoFixCanvas: { //节点拖动或连线拖动到画布边缘时,画布自动延展
enable: false,
autoMovePadding: [20, 20, 20, 20] //触发自动延展的画布内边距
},
autoResizeRootSize: true // 自动适配root大小,默认为true
},
global: { //自定义配置,会贯穿所有canvas,group,node,edge,endpoint对象
isScopeStrict: false //scope是否为严格模式(默认为false)
}
});
canvas.draw({
// 数据
})
```
<br>
<br>
## 属性
### root _`<dom>`_ (必填)
实例容器,一般是一个具有宽高的dom元素, canvas 根节点(必传)
### zoomable _`<Boolean>`_ (选填)
画布是否可缩放;值类型 `boolean`,默认 `false`
### moveable _`<Boolean>`_ (选填)
画布是否可移动;值类型 `boolean`,默认 `false`
### draggable _`<Boolean>`_ (选填)
画布节点是否可拖动;值类型 `boolean`,默认 `false`
### linkable _`<Boolean>`_ (选填)
画布锚点是否可以拖动连线;值类型 `boolean`,默认 `false`
### disLinkable _`<Boolean>`_ (选填)
画布锚点是否可以拖动断开线;值类型 `boolean`,默认 `false`
### layout _`<Object>`_ (选填)
画布初始化根据设置的布局来自动排版,[可参考](https://github.com/alibaba/butterfly/blob/master/docs/zh-CN/layout.md)
### theme
画布主题配置,默认初始化样式和交互,主要分为:
* edge 连线配置: 默认所有线段的样式和交互。拖动出来的线也会使用该配置。
*参数*:
* type _`<String>`_ 标志线条连接到节点还是连接到锚点。默认为`node`
* shapeType _`<String>`_ 线条类型可以是:Bezier(贝塞尔曲线),Flow(折线),Straight(直线),Manhattan(曼哈顿路由线),AdvancedBezier(更美丽的贝塞尔曲线),Bezier2-1,Bezier2-2,Bezier2-3(二阶贝塞尔曲线),BrokenLine(折线);默认为`Straight`
<img width="650" src="https://img.alicdn.com/imgextra/i3/O1CN01sHnesN1SMIhN62CLK_!!6000000002232-2-tps-1418-404.png">
* label _`<String/Dom>`_ 线条注释
* labelPosition _`<Number>`_ 线条上注释位置: 取值0-1之间, 0代表代表在线段开始处,1代表在线段结束处。 默认值`0.5`
* labelOffset _`<Number>`_ 线条上注释的位置的偏移值: 距离线段注释位置的偏移值。 默认值为`0`,单位是像素
```js
// labelPosition & labelOffset: 注释位置在线段中间处,再往结束方向偏移20px
{
labelPosition: 0.5,
labelOffset: 20
}
```
* arrow _`<Boolean>`_ 线条箭头; 默认为`true`
* arrowPosition _`<Number>`_ 箭头位置: 取值0-1之间, 0代表代表在线段开始处,1代表在线段结束处。 默认值`0.5`
* arrowOffset _`<Number>`_ 箭头位置的偏移值: 距离线段箭头位置的偏移值。 默认值为`0`,单位是像素
* isExpandWidth _`<Boolean>`_ 增加线条交互区域, 默认为`false`。若true时,获取`eventHandlerDom`用于挂载事件
* defaultAnimate `<Boolean>`_ 默认开启线条动画; 默认为`false`
* Class _`<Class>`_ 自定义拓展的Class
* endpoint 锚点配置: 默认所有锚点的样式和交互
*参数*:默认所有节点组的样式和交互
* linkableHighlight _`<Boolean>`_ 连线时会触发point.linkable的方法,可做线条高亮展示;默认为 `true`
* limitNum _`<Number>`_ 限制锚点的连接数目;默认为 `10`
* expandArea _`<Object>`_ 锚点连接的热区: 由于锚点区域有可能过小,所以提供了热区扩大的属性;默认 `{left: 10, top: 10, right: 10, bottom: 10}`
* group 节点组配置
*参数*:
* type _`<String>`_ 节点组类型: `normal`(随意拖入拖出), `inner`(只能拖入不能拖出);默认为 `normal`
* includeGroups _`<Boolean>`_ 节点组是否允许嵌套节点组
* zoomGap _`<Number>`_ 鼠标放大缩小间隙设置;取值[0-1]之间,默认 `0.001`
* autoFixCanvas 节点拖动或连线拖动到画布边缘时,画布自动延展
*参数*:
* enable _`<Boolean>`_ 画布是否自动延展;默认 `false`
* autoMovePadding _`<Array>`_ 触发自动延展的画布内边距;默认 `[20,20,20,20]`
<img width="650" src="https://img.alicdn.com/tfs/TB16lUNBG61gK0jSZFlXXXDKFXa-1665-801.gif">
* autoResizeRootSize _`<Boolean>`_ 自动适配Root容器大小;默认 `true`
### global (选填)
global 全局属性; _`object (Option)`_,默认 `undefined`
<br>
<br>
## API
### canvas.draw (data, calllback)
*作用*:画布的渲染方法, `注意画布渲染是异步渲染`
*参数*
* `{object} data` 里面包含分组,节点,连线
* `{function} calllback` `*渲染过程是异步的过程,需要的用户请留意回调`
```js
draw = (data, calllback) => {}
```
### canvas.redraw (data, calllback)
*作用*:重新渲染方法,会将之前的所有元素删除重新渲染, `注意画布渲染是异步渲染`
*参数*
* `{object} data` 重绘时新的分组,节点,连线
* `{function} calllback` `*渲染过程是异步的过程,需要的用户请留意回调`
```js
redraw = (data, calllback) => {}
```
### canvas.getDataMap (data, calllback)
*作用*:获取画布的所有数据:节点,线段,分组
*返回*
* `{object} data` 分组,节点,连线的数据
```js
getDataMap = () => {}
```
### canvas.setLinkable (boolean)
*作用*:设置画布所有节点是否可拉线
*参数*
* `{true|false} boolean` 是否支持所有节点可拉线
```js
setLinkable = (boolean) => {}
```
### canvas.setDisLinkable (boolean)
*作用*:设置画布所有节点是否可断线
*参数*
* `{true|false} boolean` 是否支持所有节点可断线
```js
setDisLinkable = (boolean) => {}
```
### canvas.setDraggable (boolean)
*作用*:设置画布所有节点是否可拖动
*参数*
* `{true|false} boolean` 是否支持所有节点可拖动
```js
setDraggable = (boolean) => {}
```
### canvas.getGroup (string)
*作用*:根据id获取group
*参数*
* `{string} id` group id
*返回*
* `{Group}` 分组对象
```js
getGroup = (string) => {}
```
### canvas.addGroup (object|Group, nodes, options)
*作用*:添加分组。若分组不存在,则创建分组并把nodes放进分组内;若分组存在,则会把nodes放进当前分组内。
*参数*
* `{object | Group} object` 分组: 新建分组信息或Group分组实例
* `{array< object | Node >} object` (选填)节点信息: 会把这些节点加入到分组内, 若节点不存在会新建节点
* `{object} options` 参数
* `{string} options.posType` 'absolute or relative' , 标识节点的坐标是相对画布的绝对定位还是相对于节点组
* `{number} options.padding` 添加节点组padding
```js
addGroup = ([object](./group.md#group-attr) | Group, nodes, options) => {}
```
此API除了可以新建节点组以外, 还可以做多选成组:
<img width="650" src="https://img.alicdn.com/imgextra/i1/O1CN01S2n8Sy1aayJ8euH7n_!!6000000003347-1-tps-600-400.gif">
### canvas.removeGroup (string | Group)
*作用* 删除节点组, 但不会删除里面的节点
*参数*
* `{string | Group} id` group id / Group实例
*返回*
* `{Group}` 删除的对象
```js
removeGroup = (string | Group) => {}
```
### canvas.getNode (string)
*作用*:根据id获取node
*参数*
* `{string} id` node id
*返回*
* `{Node}` 节点对象
```js
getNode = (string) => {}
```
### canvas.addNode ( [object](./node.md#node-attr) | Node )
*作用*:添加节点
*参数*
* `{object|Node} object` 节点的信息;Node - 节点的基类
```js
addNode = (object|Node) => {}
```
### canvas.addNodes ( array< [object](./node.md#node-attr) | Node > )
*作用*:批量添加节点
*参数*
* `{array<object|Node>}` 节点的信息;Node - 节点的基类
```js
addNodes = (array<object|Node>) => {}
```
### canvas.removeNode (string)
*作用*:删除节点
*参数*
* `nodeId string` - 节点id
```js
removeNode = (string) => {}
```
### canvas.removeNodes (array)
*作用*:批量删除节点
*参数*
* `nodeIds array` - 批量节点id
```js
removeNodes = (array) => {}
```
### canvas.addEdge (object|Edge)
*作用*:添加连线
*参数*
* `{object|Edge} object` - 连线的信息;Edge - 连线的基类
```js
addEdge = ([object](./edge.md#edge-attr) | Edge ) => {}
```
### canvas.addEdges (array<object|Edge>)
*作用*:批量添加连线
*参数*
* `{array<object | Edge>}` - 连线的信息;Edge - 连线的基类
```js
addEdges = (array< [object](./edge.md#edge-attr) | Edge >) => {}
```
### canvas.removeEdge (param)
*作用*:根据id或者Edge对象来删除线
*参数*
* `{string | Edge} id or Edge` - 线的id或者Edge对象
*返回*
* `{Edge}` - 删除的线
```js
removeEdge = (param) => {}
```
### canvas.removeEdges (param)
*作用*:根据id或者Edge对象来批量删除线
*参数*
* `{array} string or Edge` - 线的id或者Edge对象的数组
*返回*
* `{array} Edge` - 删除的线
```js
removeEdges = (param) => {}
```
### canvas.getNeighborEdges (string)
*作用*:根据node id获取相邻的edge
*参数*
* `{string} nodeId` - node id
*返回*
* `{Edges}` - 相邻的连线
```js
getNeighborEdges = (string) => {}
```
### canvas.getNeighborEdgesByEndpoint (string, string)
*作用*:根据endpoint id获取相邻的edge
*参数*
* `{string} nodeId` - node id
* `{string} endpointId` - endpoint id
*返回*
* `{Edges}` - 相邻的连线
```js
getNeighborEdgesByEndpoint = (string, string) => {}
```
### canvas.getNeighborNodesAndEdgesByLevel (options)
*作用*:查找 N 层关联节点和边
*参数*
* `{Object} options` - 参数
* `{Node} options.node` - 起始节点
* `{Endpoint} options.endpoint` - 起始锚点,可选
* `{String} options.type` - 查找方向,可选值为 all\in\out,默认all,可选
* `{Number} options.level` - 层数,起始节点为第 0 层,默认 Infinity
* `{Function} options.iteratee` - 是否继续遍历判定函数,返回 boolean 值
*返回*
* `{Object<nodes: Node, edges: Edge>} filteredGraph` - 查找结果
```js
getNeighborNodesAndEdgesByLevel = (options) => {}
```
### canvas.setEdgeZIndex (edges, zIndex)
*作用*:设置线段z-index属性
*参数*
* `{Array<Edge>} edges` - 线段
* `{number} zIndex` - z-index的值
```js
setEdgeZIndex = (edges, zIndex) => {}
```
### canvas.setZoomable (boolean, boolean)
*作用*:设置画布缩放
*参数*
* `{true|false} boolean` - 是否支持画布缩放
* `{true|false} boolean` - 放大缩小方向。现在默认为MAC的双指方向,却于Window的鼠标滑轮方向相反。默认值:false。若true,则方向相反
```js
setZoomable = (boolean, boolean) => {}}
```
### canvas.setMoveable (boolean)
*作用*:设置是否能通过拖动画布空白出来移动整体画布
*参数*
* `{true|false} boolean` - 是否支持画布平移
```js
setMoveable = (boolean) => {}
```
### canvas.move (postion)
*作用*:手动设置画布偏移
*参数*
* `{[x, y]} array` - x,y坐标
```js
move = (postion) => {}
```
### canvas.zoom (scale)
*作用*:手动设置画布缩放
*参数*
* `{float} scale` - 0-1之间的缩放值
* `{function} callback` - 缩放后的回调
```js
zoom = (scale) => {}
```
### canvas.getZoom ()
*作用*:获取画布的缩放
*返回*
* `{float}` - 画布的缩放(0-1)
```js
getZoom = () => {}
```
### canvas.getOffset ()
*作用*:获取画布整体移动的偏移值
*返回*
* `{[x, y]}` - 画布的偏移值
```js
getOffset = () => {}
```
### canvas.getOrigin ()
*descripition*:获取画布的缩放的中心点,一般跟随着鼠标的位置
*return*
* `{[x, y]}` - 画布的缩放的中心点(单位是百分比)
```js
getOrigin = () => {}
```
### canvas.setOrigin ([x ,y])
*descripition*:手动设置画布缩放的中心点,一般跟随着鼠标的位置
*params*
* `{[x, y]} array` - 画布的缩放的中心点(单位是百分比)
```js
setOrigin = ([x ,y]) => {}
```
### canvas.focusNodeWithAnimate (string, type, options, callback)
*作用*:聚焦某个节点/节点组
*参数*
* `{string} nodeId/groupId` - 节点/分点组的id
* `{string} type` - 节点的类型, `node` 或者 `group`
* `{object} options {offset: [0,0]}` - 聚焦配置属性,如偏移值
* `{function} callback` - 聚焦后的回调
```js
focusNodeWithAnimate = (string, type, options, callback) => {}
```
### canvas.focusNodesWithAnimate (objs, type, options, callback)
*作用*:聚焦某多个节点/节点组
*参数*
* `{object} {nodes: [], groups: []}` - 节点和节点组的id数组
* `{array} type` - 节点的类型, `node` 或者 `group`
* `{object} options {offset: [0,0]}` - 聚焦配置属性,如偏移值
* `{function} callback` - 聚焦后的回调
```js
focusNodesWithAnimate = (objs, type, options, callback) => {}
```
### canvas.focusCenterWithAnimate (options, callback)
*作用*:聚焦整个画布,会自动调整画布位置和缩放
*参数*
* `{object} options {offset: [0,0]}` - 聚焦配置属性,如偏移值
* `{function} callback` - 聚焦后的回调
```js
focusCenterWithAnimate = (options, callback) => {}
```
<img width="650" src="https://img.alicdn.com/imgextra/i2/O1CN01zrkUqk1SP34Sup0vt_!!6000000002238-1-tps-1661-824.gif">
### canvas.redo ()
*作用*:重做操作
```js
redo = () => {}
```
### canvas.undo ()
*作用*:回退操作
```js
undo = () => {}
```
### canvas.pushActionQueue (options)
*作用*:给操作队列(undo/redo的队列)新增最顶部元素
*参数*
* `{Object} options` - 参数
* `{String} options.type` - 队列类型
* `{Object} options.data` - 队列数据
```js
pushActionQueue = (options) => {}
```
### canvas.popActionQueue (options)
*作用*:给操作队列(undo/redo的队列)删除最顶部元素
```js
popActionQueue = (options) => {}
```
### canvas.clearActionQueue (options)
*作用*:清除操作队列(undo/redo的队列)
```js
clearActionQueue = (options) => {}
```
### canvas.terminal2canvas (coordinates)
*作用*:屏幕转换为画布的坐标
*参数*
* `{array<number>} coordinates` - 需要换算的坐标([x,y])
*返回*
* `{array<number>}` - 转换后的坐标
```js
terminal2canvas = (coordinates) => {}
```
### canvas.canvas2terminal (coordinates)
*作用*:画布转换为屏幕的坐标
*参数*
* `{array<number>} coordinates` - 需要换算的坐标([x,y])
*返回*
* `{number}` - 转换后的坐标
```js
canvas2terminal = (coordinates) => {}
```
*描述*
* 如图所示,画布缩放,移动后的坐标和原来画布的坐标并不匹配,需要此方法来转换。特别注意:有拖动添加节点的用户们注意这两个`e.clientX`和`e.clientY`,需要调用此方法进行转换。
<img width="650" src="http://img.alicdn.com/tfs/TB1lWIAFHvpK1RjSZPiXXbmwXXa-973-850.jpg">
### canvas.setSelectMode (boolean, contents , selecMode)
*作用*:设置框选模式: 注意, 注意框选模式和普通拖动画布模式是互斥的, 没办法同时设置
*参数*
* `{true|false} boolean` - 是否开启框选功能
* `{array} contents` - 可接受框选的内容(node|endpoint|edge),默认'node')
* `{string} selecMode` - 可接受框选的内容(include|touch|senior),默认'include',include:全部包含才可选中,touch:触碰就选中,senior:从左到右需要全部包含,从右到左只需触碰就能选中)
```js
setSelectMode = (boolean, contents , selecMode) => {}
```
### canvas.getUnion (name)
*作用*:获取聚合组
*参数*
* `{name} string` - 聚合组的名称
```js
getUnion = (name) => {}
```
### canvas.getAllUnion ()
*作用*:获取所有聚合组
```js
getAllUnion = () => {}
```
### canvas.add2Union (name, obj)
*作用*:添加聚合组 || 添加聚合组元素,用于框选模式
*参数*
* `{name} string` - 聚合组名称。假如不存在,则添加聚合组;假如已存在,则添加聚合组元素
* `{obj} object` - 聚合组的元素
```js
add2Union = (name, obj) => {}
this.canvas.add2Union('我的聚合组', {
nodes: [] // Node对象或者nodeId
groups: [] // Group对象或者groupId
edges: [] // Edge对象或者edgeId
endpoints: [] // Endpoint对象
});
```
### canvas.removeUnion (name)
*作用*:去除聚合组
*参数*
* `{name} string` - 聚合组的名称
```js
removeUnion = (name) => {}
```
### canvas.removeAllUnion ()
*作用*:去除所有聚合组
```js
removeAllUnion = () => {}
```
<br>
<br>
## 事件
```js
let canvas = new Canvas({...});
canvas.on('type key', (data) => {
//data 数据
});
```
*参数key值*
* `system.canvas.click` 点击画布空白处
* `system.canvas.zoom` 画布缩放
* `system.nodes.delete` 删除节点
* `system.node.move` 移动节点
* `system.nodes.add` 批量节点添加
* `system.links.delete` 删除连线
* `system.link.connect` 连线成功
* `system.link.reconnect` 线段重连
* `system.link.click` 线段点击事件
* `system.group.add` 新增节点组
* `system.group.delete` 删除节点组
* `system.group.move` 移动节点组
* `system.group.addMembers` 节点组添加节点
* `system.group.removeMembers` 节点组删除节点
* `system.multiple.select` 框选结束
* `system.drag.start` 拖动开始
* `system.drag.move` 拖动
* `system.drag.end` 拖动结束
```js
/**
* 发送事件
*/
emit = (string, obj) => {}
/**
* 接受事件
*/
on = (string, callback) => {}
```
<br>
<br>
## 其他辅助方法
### canvas.setGridMode (show, options)
*作用*:设置网格背景
*参数*
* `{true|false} boolean` - 是否开启网格背景功能
* `{array} options` - 网格背景的定制化参数
```js
setGridMode = (show, options) => {}
this.canvas.setGridMode(true, {
isAdsorb: false, // 是否自动吸附,默认关闭
theme: {
shapeType: 'line', // 展示的类型,支持line & circle
gap: 23, // 网格间隙
adsorbGap: 8, // 吸附间距
background: '#fff', // 网格背景颜色
lineColor: '#000', // 网格线条颜色
lineWidth: 1, // 网格粗细
circleRadiu: 1, // 圆点半径
circleColor: '#000' // 圆点颜色
}
});
```
### canvas.setMinimap = (show, options)
*作用*:设置是否开启缩略图
*参数*
* `{true|false} boolean` - 是否开启缩略图功能
* `{Object}` 具体请参考缩略图章节
```js
setMinimap = (show, options) => {}
```
### canvas.save2img (options)
*作用*:画布保存为图片
*参数*
* `{object=} options` - 保存的图片参数,可选
* `{string=} options.type` - 图片格式(png/jpeg/svg,默认png),可选
* `{number=} options.quality` - 图片质量(0~1,默认为1),可选
* `{number=} options.width` - 图片宽度(默认为画布宽度),可选
* `{number=} options.height` - 图片高度(默认为画布高度),可选\
*返回*
* `{Promise}`
```js
save2img = (options) => {}
this.canvas.save2img({type: 'png', width: 1920, height: 1080, quality: 1})
.then(dataUrl => {
var link = document.createElement('a');
link.download = 'XXX.png';
link.href = dataUrl;
link.click();
});
```
### canvas.justifyCoordinate ()
*作用*:把画布上的节点,节点组自动对齐(必须在网格布局下才生效)
```js
justifyCoordinate = () => {}
```
### canvas.setGuideLine (show, options)
*作用*:设置辅助线
*参数*
* `{true|false} boolean` - 是否开启辅助线功能
* `{array} options` - 辅助线的定制化参数
```js
setGuideLine = (show, options) => {}
this.canvas.setGuideLine(true, {
limit: 1, // 限制辅助线条数
theme: {
lineColor: 'red', // 网格线条颜色
lineWidth: 1, // 网格粗细
}
});
```
### canvas.updateRootResize ()
*作用*:当root移动或者大小发生变化时需要更新位置
```js
updateRootResize = () => {}
```