拓扑图库
一 、前言
目前 drawtool.js 已经服务于四个以上的项目。
二 、drawtool.js 提供的功能
drawtool.js 为图(包含树)这样结构的数据的界面化,提供了解决方案。
即: 为点和线的图形操作提供了方案。
可以举例以下几种情况
- 画一个流程图。
- 画一个组织架构图。
- 画一个城市交通图。
三、 drawtool.js 提供的 API
1.引入
drawtool.js 支持 nodeJs 引入,AMD 规范引入、CMD 规范引入和直接引入。
标签直接引入: drawtool.css 是内置样式表,可以方便覆盖。
<link rel="stylesheet" type="text/css" href="../drawtool/drawtool.css" />
<script type="text/javascript" src="../drawtool/drawtool.js"></script>
drawtool 也支持 npm 安装
npm install drawtool
安装后引入如下:
import Drawtool from "drawtool"
import "drawtool/drawtool.css"
2.初始化
页面放置一个 div,drawtool.js 会根据 div 的大小初始化一个画布。
html
<div id="canvas" class="canvas"></div>
style
#canvas {
width: 800px;
height: 400px;
background: #fafafa;
}
javascript
var canvas = document.getElementById("canvas")
var drawtool = new Drawtool(canvas)
3 全局属性配置
drawtool.js 在初始化的过程中可以配置一些常用属性。
可配置属性包括下面:
序号 | 属性 | 含义 | 默认值 |
---|---|---|---|
1 | lineColor | 线的颜色 | #26b7d0 |
2 | lineHoverColor | 线处于 hover 状态的颜色 | rgba(200, 200, 200, 0.4) |
3 | arrowColor | 箭头的颜色 | #444 |
4 | lineStyle | 线有无箭头 arrow 有箭头 none 无箭头 | arrow |
5 | lineType | 线性 broken 折线 bezier 贝塞尔曲线 straight 直线 | bezier |
6 | auto | 是否自动计算控制点,只对折线有效。 true 自动计算, false 不自动计算 | true |
7 | lineActiveColor | 线处于激活状态颜色 | #2177C7 |
var canvas = document.getElementById("canvas")
var setting = {
lineColor: "#26b7d0",
lineHoverColor: "#aaa",
arrowColor: "#444",
lineStyle: "arrow",
lineType: "broken",
auto: false,
}
var drawtool = new Drawtool(canvas, setting)
注意:此处配置为全局性的,权重级别最低。
4.增加节点
drawtool.js 的节点是用 dom 构造,这样做是为了更灵活的操作节点。 配置一个节点有四个属性:
属性 | 说明 |
---|---|
pos | 节点添加的位置坐标 x 为横坐标, y 为纵坐标 |
template | 可以传入 html 字符串模板或者一个 dom 元素,drawtool.js 将会为 html 模板创建一个节点容器,若是 html 字符串,则 innerHTML 方法将模板写入节点容器。若是 dom 元素,则会直接将 dom 元素插入节点容器。 |
anchors | 连线点的相对坐标,以 html 模板的中心为坐标系原点。 |
nodeid | 节点 id, 为数值类型,不传入会自动递增构造。 |
若是采用 vue 等无 dom 开发,可以在 template 内传入 dom。 addNode 方法的返回值是节点 dom,dom 上挂载了 nodeid 属性。
var option = {
pos: { x: 20, y: 20 },
template: "<div class='node js-node'>test</div>",
anchors: [
[0, 20],
[40, 20],
[20, 0],
[20, 40],
],
}
var node = drawtool.addNode(option)
console.log(node.nodeid)
5.删除节点
通过 nodeid 可以删除节点。nodeid 可以通过 dom 获取。 删除节点的同时,会将与之相连的线条全部删除。
// jquery代码示例
var nodeid = $(".js-node").get(0).nodeid
drawtool.deleteNodeById(nodeid)
6.清除画布
清除画布是删除 drawtool.js 上面所有的节点和连线。
drawtool.clear()
7.事件监听
drawtool.js 提供了事件监听切面,让我们可以控制连线点击等操作。而对于节点事件的操作,则全部交给 dom 完成。
drawtool.js 提供的事件如下:
序号 | 方法 | 含义 | 说明 |
---|---|---|---|
1 | clickLine | 点击连线 | 参数是当前点击的线条 |
2 | deleteLineBefore | 删除连线之前 | 参数是当前线条,返回 true 表示可以删除,返回 false 不删除。 缺省为 true。 |
3 | deleteLineAfter | 删除连线之后 | 参数是当前线条 |
4 | linkLineBefore | 连线前 | 参数是当前线条,此时为点击第二个连线点,返回 true 表示可以连线,返回 false 不连线。 缺省为 true。 |
5 | linkLineAfter | 连线后 | 参数是当前线条 |
6 | linkLineStart | 开始连线 | 参数是当前线条,此处是设置局部线性配置的地方。 |
可以使用如下监听方式:
drawtool.listen({
clickLine: function (line) {
console.log(line)
},
deleteLineBefore: function (line) {
return true
},
deleteLineAfter: function (line) {
console.log(line)
},
linkLineBefore: function (line) {
return true
},
linkLineAfter: function (line) {
console.log(line)
},
})
drawtool.js 也支持下列调用
drawtool.listen("linkLineStart", function (line) {
console.log(line)
})
注意: — drawtool.js 不支持重复绑定,重复绑定会引发覆盖操作。 — 所有的事件方法,this 都指向 drawtool 实例。
8.局部属性设置
drawtool.js 局部属性是针对线条设置的,它覆盖全局属性。
通过对 linkLineStart 的监听,调用线条的方法,可以完成局部属性设置。
支持三种局部属性:
- setStyle 箭头设置, arrow,none;
- setType 线性设置, broken,bezier,straight
- setAuto 是否自动计算,只支持折线, true,false
// 动态设置线的样式
drawtool.listen("linkLineStart", function (line) {
line.setStyle("arrow")
line.setType("broken")
line.setAuto(false)
})
9.禁用模式
drawtool.js 可以设置禁用模式
drawtool.setDisabled(true)
setDisabled 方法接收一个布尔值, true 为禁用模式,false 为非禁用模式。 禁用模式下,点线事件失效,但可以通过 api 调用。
10.存为图片
drawtool.js 利用 svg 和 canvas 合成图片。。 若有图片,受 svg 限制,必须使用 img 标签引入图片,使用 background 将不会被支持导出。
drawtool.getImage(fn, deep)
fn — 回调方法,函数类型。参数为 base64 编码。 deep — 是否深获取,布尔类型,true 为下载图片。
drawtool.getImage(function (res) {
console.log(res)
}, true)
注意:受浏览器兼容影响,ie 浏览器不支持,若完成复杂的图片存储,建议采用其他插件配合完成。
11.数据存储
drawtool.js 内部管理节点栈和连线栈。我们可以通过接口,来获取数组格式的节点和连线。
var lineArr = drawtool.getAllLines()
var nodeArr = drawtool.getAllNodesInfo()
localStorage.setItem("lineArr", JSON.stringify(lineArr))
localStorage.setItem("nodeArr", JSON.stringify(nodeArr))
drawtool.js 还管理了所有的 canvas 上的所有 dom,我们也可以获取。
var domArr = drawtool.getAllNodes()
12.数据读取
drawtool.js 可以直接读取节点和连线数组,来初始化画布。
init 方法可以直接读取 drawtool.js 输出的数据。
var lineArr = JSON.parse(localStorage.getItem("lineArr"))
var nodeArr = JSON.parse(localStorage.getItem("nodeArr"))
drawtool.init(nodeArr, lineArr)
13.vue 中使用
drawtool.js 没有对 dom 进行控制,而是通过 addNode 方法将 dom 的操作权转让给外界。也即 drawtool.js 不干涉 dom 行为,只提供一个节点容器。
例如下面: 可以构造一个 node 模板
<template>
<div>
<div @contextmenu="show">
<div>A</div>
<button v-if="option" @click="deletes">删除</button>
</div>
</div>
</template>
<script>
export default {
name: "node",
data() {
return {
option: false,
}
},
methods: {
show() {
this.option = !this.option
},
deletes() {
this.$emit("deleteClick", null)
},
},
}
</script>
然后在主模块中做如下操作:
let option = {
pos: {
x: 30,
y: 50,
},
template: this.$refs.node.$el,
anchors: [
[0, 20],
[40, 20],
[20, 0],
[20, 40],
],
}
this.drawtool.addNode(option)
四、 性能
drawtool.js 最大性能问题是事件和渲染, 事件:drawtool.js 内部实现了自己的事件方法,优化管理事件。 渲染:drawtool.js 采用局部渲染方法,保证最小程度的重绘。
五、 自我保护
1. 数据私有化
drawtool.js 所有数据都采用 getter/setter 获取和设置。
2. 动态 class
drawtool.js 提供了 dom 的标准化获取方法,不建议使用 dom 操作来获取和操作 dom,因此 drawtool.js 会将关键的 dom 采用动态 class 生成方法,来防止外界直接操作 dom。
六、 存在的问题
- 线上文字未实现。
七、 代码 demo
版本: 1.1.1 代码量:28k
版本: 1.2.0 代码量:53k
gitHub 地址: https://github.com/fwx426328/drawtool