共计 6630 个字符,预计需要花费 17 分钟才能阅读完成。
概括来说,用 HT for Web
做可视化次要分为两局部,也就是 2D
和 3D
。这两局部须要独自创立。在它们被创立实现后,咱们再把它们集成到一起。
HT for Web
的 2D
局部次要是指 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
上面。也能够通过传递一个 div
将 2D
图纸固定到页面的某个地位。
对于新创建的图纸,其默认具备缩放、平移、编辑,以及框选等属性。咱们能够依据须要对其进行启用或禁用。
与其余视图组件一样,如果不指定 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)
间接在构造函数中传入 source
和 target
节点对象,也可构建 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);
下面的代码创立了 4
条 Edge
,其中前三条别离是连贯 server1
和 server2
,第四条是 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)
函数运算后的值。其范畴在大部分状况下也是从0
到1
。然而这里的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
是一个对象,蕴含动画播放时长、缓动函数、动画完结回调函数和动作管制函数等参数。