返回

让流程图应用动起来-实现流程图的画布功能(02)

前端

从哪里开始 ##

我们开始实现流程图的画布功能,从两个方面着手,第一是画布的静态特性 ,包括网格和背景,即流程图长什么样子,第二是画布的操作特性 ,包括平移和缩放,即我们如何使用流程图。

1. 画布的静态特性

网格

网格的设置非常简单,我们只需在canvas元素上设置grid属性即可,我们添加如下 CSS 代码:

.flowchart-canvas {
  grid: 10px / 10px;
}

该代码将为画布设置一个10px大小的网格,网格在视觉上并不会很明显,但它将有助于对齐流程图中的结点和连线。

背景

给画布设置背景也是非常容易的,我们只需在canvas元素上设置background属性即可,我们添加如下 CSS 代码:

.flowchart-canvas {
  background-color: #f5f5f5;
}

该代码将为画布设置一个浅灰色的背景。你也可以将背景颜色设置为其他颜色,或使用渐变或图片作为背景。

2. 画布的操作特性

平移

在实现平移功能之前,我们需要知道平移的具体含义。平移可以是任意方向的,但我们现在仅仅考虑向左和向右平移,平移的目的是让用户能够查看隐藏在当前画布外侧的流程图结点。我们首先需要创建一个div元素,该元素的大小和位置完全匹配canvas元素,这个元素的overflow属性设置为hidden,即当canvas元素内容超过div元素的大小时,那么canvas元素内容的该部分将被隐藏,不会被显示出来。我们来看看 HTML 结构:

<div class="flowchart-canvas-wrapper">
  <canvas class="flowchart-canvas"></canvas>
</div>

我们再添加如下 CSS 代码:

.flowchart-canvas-wrapper {
  position: relative;
  overflow: hidden;
}

.flowchart-canvas {
  position: absolute;
  top: 0;
  left: 0;
}

平移操作的具体实现需要我们监听div元素的mousemove事件,当div元素mousemove时,我们获取mousemove事件对象,并通过计算得到移动的距离,最后将计算出的距离应用到canvas元素的位置。我们来看看具体的 JavaScript 代码:

// 缓存平移的距离
var canvasTranslateX = 0;
var canvasTranslateY = 0;

// 监听平移操作
$(".flowchart-canvas-wrapper").mousemove(function(e) {
  // 获取`mousemove`事件对象
  var mousemove = e.originalEvent;

  // 
  var canvas = $(this).find(".flowchart-canvas");

  // 根据`mousemove`事件对象计算出的平移距离
  var translateX = mousemove.clientX - canvasTranslateX;
  var translateY = mousemove.clientY - canvasTranslateY;

  // 将平移距离应用到`canvas`元素
  canvas.css({
    left: translateX,
    top: translateY
  });
});

缩放

缩放操作的实现与平移操作的实现非常相似,我们同样需要一个div元素,大小和位置都完全匹配canvas元素,这个元素的overflow属性也设置为hidden,我们来看看修改后的 HTML 结构:

<div class="flowchart-canvas-wrapper">
  <canvas class="flowchart-canvas"></canvas>
  <div class="flowchart-canvas-scale-controller"></div>
</div>

缩放操作的具体实现需要我们监听div元素的mousemove事件,当div元素mousemove时,我们获取mousemove事件对象,并通过计算得到移动的距离,最后将计算出的距离应用到canvas元素的大小上。我们来看看具体的 JavaScript 代码:

// 缓存缩放的比例
var canvasScale = 1;

// 监听缩放操作
$(".flowchart-canvas-wrapper").mousemove(function(e) {
  // 获取`mousemove`事件对象
  var mousemove = e.originalEvent;

  // 
  var canvas = $(this).find(".flowchart-canvas");

  // 根据`mousemove`事件对象计算出的缩放比例
  var scale = Math.max(0.1, mousemove.clientX / canvasScale);

  // 将缩放比例应用到`canvas`元素
  canvas.css({
    transform: "scale(" + scale + ")"
  });
});