自己实现的网络拓扑图

September 09, 2018

拓扑图库

一 、前言

目前 drawtool.js 已经服务于四个以上的项目。

二 、drawtool.js 提供的功能

drawtool.js 为图(包含树)这样结构的数据的界面化,提供了解决方案。

即: 为点和线的图形操作提供了方案。

可以举例以下几种情况

  1. 画一个流程图。
  2. 画一个组织架构图。
  3. 画一个城市交通图。

可以看下面的 demo 这里写图片描述 在这里插入图片描述

在这里插入图片描述

三、 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 的监听,调用线条的方法,可以完成局部属性设置。

支持三种局部属性:

  1. setStyle 箭头设置, arrow,none;
  2. setType 线性设置, broken,bezier,straight
  3. 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


Profile picture

Written by Vance who lives and works in Shenzhen, China, and is working hard to improve. You should follow them on csdn