拓扑图库


一 、前言

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


二 、drawtool.js提供的功能

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

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

可以举例以下几种情况

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

可以看下面的demo

拓扑图 软件 JavaScript js拓扑图 组件_设计模式


拓扑图 软件 JavaScript js拓扑图 组件_api_02

拓扑图 软件 JavaScript js拓扑图 组件_api_03

三、 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