关于前端:HT-for-Web-Hightopo-使用心得2-2D图纸节点连线与基本动画

3次阅读

共计 6630 个字符,预计需要花费 17 分钟才能阅读完成。

概括来说,用 HT for Web 做可视化次要分为两局部,也就是 2D3D。这两局部须要独自创立。在它们被创立实现后,咱们再把它们集成到一起。

HT for Web2D 局部次要是指 ht.graph.GraphView (简称 GraphView,也就是 2D 图纸)。所谓 2D 图纸其本质是一个 canvas。咱们能够在下面进行根本图形的绘制和编辑,进行连线布局,或者渲染动画。GraphView 能够脱离开 3D 独自应用,比方用于创立一般网页,组态软件,组织图,流程图等。

本节咱们次要以一个示例阐明一下 2D 图纸的基本概念、性能及用法。其次要包含以下几局部:

  • 创立 2D 图纸 -(GraphView
  • 增加节点 -(ht.Node
  • 坐标系与坐标转换
  • 增加连线 –(ht.Edge
  • 动画 – ht.Default.startAnim()

创立 2D 图纸 -(GraphView)

通过 new ht.graph.GraphView() 便可创立一张图纸。创立完图纸后,对于 HT 视图组件,能够通过 GraphView.addToDOM() 办法将其增加到 DOM 中。addToDOM() 办法自身接管一个参数。如果为空,则默认增加到 body 上面。也能够通过传递一个 div2D 图纸固定到页面的某个地位。

对于新创建的图纸,其默认具备缩放、平移、编辑,以及框选等属性。咱们能够依据须要对其进行启用或禁用。

与其余视图组件一样,如果不指定 DataModel, GraphView 本身也会创立一个空的 DataModel 容器用来治理所有增加到其外面的各种图元。通过 GraphView.getDataModel()GraphView.dm() 能够获取该容器。对于 GraphView,它反对通过 DataModel.setBackground() 来配置图纸的背景色彩。

/*************** 创立一张 2D 图纸,增加到 body 下,并配置各种属性 *******************/
const gv = new ht.graph.GraphView();
gv.addToDOM();
gv.setZoomable(true); // 可缩放,默认:true
gv.setPannable(true); // 可平移,默认:true
gv.setEditable(true); // 图纸上的 Node 是否可编辑,默认:true
gv.setRectSelectable(true); // 是否容许对 Node 进行框选,默认:true
const dm = gv.getDataModel(); // 获取图纸的 DataModel,简写模式:gv.dm()
dm.setBackground('#DADADA'); // 同 dm.setBackground('rgba(218, 218, 218, 1)');

为什么要通过 DataModel 来设置图纸的背景而不是间接操作 GraphView 自身?

在第一节咱们提到过,为了能将咱们创立的 2D/3D 数据保留与复原,能够通过对 DataModel 进行序列化与反序列化来实现。留神,这里的序列化操作针对的是 DataModel 而不是视图组件。因而,像如 GraphView 这种视图组件,其背景色彩这种显示属性须要通过配置到 DataModel 能力保留下来。而像缩放,平移等操作属性,则须要依据我的项目运行须要独自配置。

增加节点 -(ht.Node)

有了 2D 图纸的 DataModel,咱们便能够向其增加节点或者叫图元。这里咱们增加了两个机柜图标。

/**************** 别离创立两个 HT 节点并增加到图纸中 ************************/
const server1 = new ht.Node();
server1.setSize(40, 100); // 节点宽高。该当依据图片比例设置,不然会呈现拉伸成果
server1.setPosition(100, 100); // 节点地位。左上角为(0,0)坐标
server1.setImage('assets/server.png'); // 节点图片
server1.setName('Server 1'); // 显示名称
dm.add(server1); // 增加到 DataModel 中,也就是增加到图纸中
const server2 = new ht.Node();
server2.setSize(40, 100);
server2.setPosition(250, 100);
server2.setImage('assets/server.png');
server2.setName('Server 2');
dm.add(server2); // 留神肯定要增加到 DataModel 中

在传统前端(Vue, React, HTML)的开发过程中,要增加一个节点,咱们往往须要先手动创立该节点(如增加一个 icon)并增加到 HTML 上面。而后通过数据绑定对该节点进行操作。而在 HT 中,咱们只须要将新增的节点增加到 DataModel 上面。HT 的视图组件会监听 DataModel 的变动,主动触发从新渲染操作。咱们对节点的所有款式格调配置和操作都能够间接在节点上进行。

节点配置

ht.Node(简称为 Node)是 2D 图纸和 3D 场景出现节点图元的根底类,它继承自 ht.Data。在 ht.Data 的根底上,其又新增了地位,大小,旋转,缩放,吸附等属性。这些属性都能够通过 set*/get* 来设置和获取。

GraphView 中,新增一个 ht.Node 节点,默认其会显示一个电脑图片。咱们能够通过 setImage(image) 办法来更改。如在上例的代码中,咱们找了一个机柜照片并将它给了新增的节点。

因为机柜图片可能很大,咱们能够通过 setSize(width, height) 来对节点大小进行管制。通过配置不同的宽高还能够实现拉伸成果。如果不想要拉伸成果,则能够依据原始图片宽高比来设置节点的大小。

坐标系与坐标转换

增加的节点如果不指定地位,其默认会被放到(x: 0, y: 0)点。通过 Node.setPosition(x, y)Node.p(x, y) 能够管制节点的地位。通过 Node.getPosition()Node.p() 能够获取其坐标。在 GraphView 中,如果不手动批改节点的坐标,其在 GraphView 中的地位便是固定不变的。

因为 GraphView 自身具备缩放、平移等属性,因而其外面的节点显示在浏览器上的地位是不固定的。因而咱们能够晓得 GraphView 的坐标系与浏览器的坐标系是不一样的。

实际上,GraphView 采纳的是一个绝对坐标系,其方向与 canvas 统一,即左上角为(0, 0)点。往右为 x 轴的正方向,往下为 y 轴的正方向。通过以下两个办法能够在 GraphView 坐标与浏览器坐标之间进行转换。

  • GraphView.getLogicalPoint(event): 传入 HTML 事件对象,将浏览器坐标转换为 GraphView 中的逻辑坐标
  • GraphView.getScreenPoint(point, y): 传入 GraphView 中的坐标,转换为浏览器坐标

增加连线 –(ht.Edge)

在增加了两个机柜图标之后,咱们当初用连线将他们连接起来。HT 中的连线是用 ht.Edge 实现的。

ht.Edge 类型(简称 Edge)用于连贯起始和指标两个 Node 节点,两个节点间能够有多条 Edge 存在,也容许起始和指标为同一节点。可通过 new ht.Edge(source, target) 间接在构造函数中传入 sourcetarget 节点对象,也可构建 Edge 对象之后再别离设置。

  • getSource()setScource(node) 获取和设置起始节点
  • getTarget()setTarget(node) 获取和设置指标节点
  • isLooped() 判断连线的起始和指标是否为同一节点
/****************************** 创立连线 *************************************/
const edges = [];
// 创立三条连线连贯 server1 和 server2
edges.push(createEdge(4, 'green', 6, 'yellow', [20, 10]));
edges.push(createEdge(3, '#fff', 3, '#000', [10, 10])); // 黑白线
edges.push(createEdge(10, 'rgb(51,153,255)', 5, 'rgb(242,83,75)', [5, 10])); // 红蓝线
function createEdge(width, color, dashWidth, dashColor, pattern) {const edge = new ht.Edge(server1, server2);
  edge.s({
    'edge.width': width, // 连线宽度
    'edge.gap': 30, // 连线与连线的间隔
    'edge.color': color, // 连线色彩。也可应用 rgb 或 16 进制色彩
    'edge.dash': true, // 是否应用虚线
    'edge.dash.width': dashWidth, // 虚线宽度
    'edge.dash.color': dashColor, // 虚线色彩
    'edge.dash.pattern': pattern, // 虚线与连线的占比。[虚线, 连线]
    'edge.offset': 0, // 偏移
  });
  dm.add(edge); // 留神肯定要增加到 DataModel 中
  return edge;
}
// 创立第四条连线用于 server1 自连线
const edge = new ht.Edge();
edge.setSource(server1);
edge.setTarget(server1);
edge.s({
  'edge.width': 5, // 连线宽度
  'edge.gap': 30, // 连线与连线的间隔
  'edge.color': 'pink', // 连线色彩。也可应用 rgb 或 16 进制色彩
  'edge.dash': true, // 是否应用虚线
  'edge.dash.width': 5, // 虚线宽度
  'edge.dash.color': 'purple', // 虚线色彩
  'edge.dash.pattern': [10, 10], // 虚线与连线的占比。[虚线, 连线]
    'edge.offset': 0, // 偏移    
});
dm.add(edge); // 留神肯定要增加到 DataModel 中
edges.push(edge);

下面的代码创立了 4Edge,其中前三条别离是连贯 server1server2,第四条是 server1 自连贯。ht.Edge 的属性次要是由 edge.s() 办法来配置,该办法是 edge.setStyle() 的简写模式。edge.s() 次要用来配置节点内置的属性。HT for Web 引擎会依据属性键值来渲染不同的成果。如果想要设置自定义属性,须要应用 edge.a() 来实现。

ht.Node 雷同的是,ht.Edge 也是由 ht.Data 扩大而来。但在大部分状况下,其又有本人的特点:

  • 须要设置起始节点和指标节点。二者能够为同一个节点(如上例最初一条 Edge)。
  • 短少起始或指标节点的 Edge 不会在图纸上显示。
  • Edge 会追随节点挪动。也就是说当咱们拖动起始节点和指标节点的时候,其所相干的 Edge 会追随挪动。
  • 因为 Edge 的地位由两个端点决定,因而 Edge 不反对 getPosition()/setPosition() 办法。同样的,其宽度是在 edge.s() 中配置的,因而 Edge 也不反对 getSize()/setSize() 办法。
  • 除了下面示例中的配置,ht.Edge 还反对自定义连线类型。如果嫌麻烦,也能够应用 HT 内置的十几种连线类型,如 edge.s(’edge.type’,‘boundary’) 就代表连线仅连贯到图元矩形边缘。如果要应用内置连线类型,须要引入连线类型插件:
<script src="../../lib/plugin/ht-edgetype.js"></script>

在创立了连线后,如何让它们流动起来呢?这里就用到了动画性能。

动画 – ht.Default.startAnim()

要实现动画性能,不外乎有这样几个要害属性:动画播放时长,播放过程中的属性变动,播放完的回调事件。

HT 反对多种形式来实现动画。这里咱们抉择一种比拟罕用的。先来看代码:

/****************************** 连线动画 *************************************/
const animParams = {
  // frames: 12, // 动画帧数
  // interval: 10, // 动画帧距离毫秒数
  duration: 2000, // 动画播放时长
  easing: function(t){return t * t;}, // 动画缓动函数,默认采纳 `ht.Default.animEasing`
  finishFunc: function(){ht.Default.startAnim(animParams);
  }, // 动画完结后调用的函数。action: function(v, t){ // action 函数必须提供,实现动画过程中的属性变动。// v 代表通过 easing(t)函数运算后的值,t 代表以后动画进行的进度,范畴:[0~1]
    edges.forEach((edge, index) => {
      const direction = index%2 == 0 ? 1 : -1;
      edge.s('edge.dash.offset', t * 20 * direction);
    });
  }
};
ht.Default.startAnim(animParams);

这里 HT 用于播放动画的办法是 ht.Default.startAnim(animParams),该办法会返回一个 anim 对象,可调用 anim.stop(true) 终止动画。同时 anim 还具备 anim.pause()anim.resume() 办法可用来中断和持续动画性能,以及 anim.isRunning() 函数判断动画是否正在进行。

该办法所应用的参数也很简略:

  • duration: 动画播放时长。如果想准确地管制动画播放帧数及帧距离,咱们也能够用 frames + interval 的模式来管制动画播放。
  • easing: 缓动函数。应用数学公式来管制动画播放的速度与快慢。
  • finishFunc: 播放完回调。在动画完结后,该办法会被执行。
  • action: 动作管制。节点的哪些属性须要变动都是在这里定义。如管制节点的地位,旋转,大小等。在动画执行过程中的每一帧都会调用一次该办法。其中的两个参数别离是:
    t: 代表以后动画进行的进度。其范畴是从开始执行 0 到执行完结1。该值的变动随着工夫后退,是绝对平均的。如果咱们想要动画匀速执行,这里能够用 t 来实现。
    v: 代表通过 easing(t) 函数运算后的值。其范畴在大部分状况下也是从 01。然而这里的 v 值在变动上由 easing(t) 函数决定,不肯定是平均的。对于有的缓动成果,如 easeOutBack (),其 v 值在两头阶段就可能大于 1。如果想要在动画中应用缓动成果,这里就须要应用 v 参数来管制属性变动。

小结

本节咱们次要介绍了 HT for Web 图纸的创立与根本配置。在 GraphView 中,咱们能够向其 DataModel 增加 ht.Node 来绘制机柜。通过 Node.setPosition(x, y)Node.p(x, y) 办法能够管制节点的地位,并通过 Node.getPosition()Node.p() 办法来获取其坐标。同时,GraphView 中的坐标系与浏览器坐标系不同,咱们能够应用 GraphView.getLogicalPoint(event)GraphView.getScreenPoint(point, y) 办法在两种坐标系之间进行转换。

对于连线,咱们应用 ht.Edge 类型示意。创立 ht.Edge 对象时须要传入起始节点和指标节点,同时能够通过 edge.s() 办法配置其属性,如宽度、色彩、虚线等。在创立多条连线后,咱们能够应用 ht.Default.startAnim(animParams) 办法来实现连线动画,其中 animParams 是一个对象,蕴含动画播放时长、缓动函数、动画完结回调函数和动作管制函数等参数。

正文完
 0