热力图组件Heatmap
热力图组件 Heatmap 是一种通过颜色渐变来展示数据分布和密度的可视化工具,常用于展示机房温度分布(温度云图
)等情况,以下均以 温度云图
为例进行讲解演示。 Heatmap
组件一般挂载在 楼层Floor 或者 园区Campus ,且 Heatmap
组件是自动挂载组件,不需要手动添加。
数据点位
GlowJS约定使用 数据点位 标签来标记温度云图的设备点位,一般在机柜模型上设置该标签。数据点位可以用来绑定温度值。只要场景层级中存在带有 数据点位
标签的物体实体,那么该场景层级就会自动挂载 Heatmap
组件。
Heatmap
组件对象有一个只读实例成员 points
,该成员是一个 实体 对象数组,数组中的每个元素表示一个数据点位。
热力图类型
热力图类型使用枚举类型 HeatmapType 来表示,支持以下类型:
HeatmapType.Horizontal
:水平图HeatmapType.Vertical
:垂直图
Heatmap
组件对象有一个实例属性 heattype
,该属性用于设置热力图类型。
typescript
heatmap.heattype = GLOW.HeatmapType.Horizontal;
注意:其中水平图是根据机房房间生成的,因此不能将房间地板删除,但可以隐藏房间地板,否则将引发错误
。
图层配置
使用静态成员 Heatmap.layers
来设置图层, layers
是一个对象数组,每个对象表示一个图层,包含以下属性:
name
:图层名称offsetY
:离地高度
layers
默认包含0个元素,需要手动添加。一般情况下,为了生成温度云图,会在机柜的上、中、下位置各安装一个温度传感器(共3各)采集温度数据,有时为了区别机柜前后的温度会在机柜的上、中、下位置的前、后面各安装一个温度传感器(共6个)。以下是一个配置示例:
typescript
GLOW.Heatmap.layers.push({ name: '上层', offsetY: 1.7 });
GLOW.Heatmap.layers.push({ name: '中层', offsetY: 1 });
GLOW.Heatmap.layers.push({ name: '下层', offsetY: 0.3 });
注意:
①当添加了3个图层时,一个
数据点位
可以绑定3个温度值。②当一个机柜安装了6个温度传感器时,如果只在机柜模型上添加
数据点位
标签,显然无法满足需求了。此时可以使用专门的数据点位
模型(位于 其它/杂项 中),分别在机柜的前、后面各摆放一个该模型即可。
Heatmap
组件对象有一个实例属性 layerName
,当生成水平图时,需要设置该属性来指定图层名称;当生成垂直图时,该属性无效。
typescript
heatmap.layerName = '上层';
数值限定
使用静态成员 Heatmap.min
和 Heatmap.max
来设置数值限定, min
和 max
是一个数字,表示值的最小值和最大值。最小值默认为 18
,最大值默认为 30
。
typescript
GLOW.Heatmap.min = 15;
GLOW.Heatmap.max = 35;
生成温度云图步骤
参考 温度云图完整示例 。
完整示例代码:
typescript
let app: GLOW.App;
let timeId: number = -1;
/**
* 入口函数
* @param container DIV容器
*/
function main(container: HTMLDivElement): void {
//设置云图图层
GLOW.Heatmap.layers.push({ name: '上层', offsetY: 1.7 });
GLOW.Heatmap.layers.push({ name: '中层', offsetY: 1 });
GLOW.Heatmap.layers.push({ name: '下层', offsetY: 0.3 });
//设置值范围
GLOW.Heatmap.min = 18;
GLOW.Heatmap.max = 30;
//创建一个GlowJS App实例
app = new GLOW.App({
container,
projectFile: 'glowjs/project/file/2f66ef33c2bdfa9ac2d19eb8522b4157.json'
});
app.once(GLOW.EventType.LevelCreate, () => {
let btn_H1 = createButton("水平图_上层", '20px');
btn_H1.onclick = () => onShowClick(GLOW.HeatmapType.Horizontal, '上层');
let btn_H2 = createButton("水平图_中层", '150px');
btn_H2.onclick = () => onShowClick(GLOW.HeatmapType.Horizontal, '中层');
let btn_H3 = createButton("水平图_下层", '280px');
btn_H3.onclick = () => onShowClick(GLOW.HeatmapType.Horizontal, '下层');
let btn_V = createButton('垂直图', "410px");
btn_V.onclick = () => onShowClick(GLOW.HeatmapType.Vertical);
let btn_T = createButton('显隐值', "500px");
btn_T.onclick = () => {
let heatmap = app.levelMgr.current.getComponent(GLOW.Heatmap);
heatmap.showValues = !heatmap.showValues;
}
let btn_C = createButton('清理', "600px");
btn_C.onclick = () => onCleanClick();
});
//调用App实例的加载方法
app.load();
}
function onCleanClick(): void {
if (timeId !== -1) {//如果已有定时器,则先清理
clearTimeout(timeId);
timeId = -1;
}
let heatmap = app.levelMgr.current.getComponent(GLOW.Heatmap);
heatmap.clean();
}
async function onShowClick(type: GLOW.HeatmapType, layerName?: string): Promise<void> {
if (timeId !== -1) {//如果已有定时器,则先清理
clearTimeout(timeId);
timeId = -1;
}
let heatmap = app.levelMgr.current.getComponent(GLOW.Heatmap);
heatmap.heattype = type;//设置云图类型
if (layerName) heatmap.layerName = layerName;//设置图层名称
loop();//启动定时器循环渲染
await renderOnce();//立即渲染一次
}
function loop(): void {//循环渲染
timeId = setTimeout(async () => {
await renderOnce();
loop();
}, 3000);
}
async function renderOnce(): Promise<void> {//渲染单次
let heatmap = app.levelMgr.current.getComponent(GLOW.Heatmap);
for (let p of heatmap.points) {
p.userData['上层'] = newValue();
p.userData['中层'] = newValue();
p.userData['下层'] = newValue();
}
await heatmap.render();
}
function newValue(): number {//模拟生成一个新值
return 10 + Math.random() * 30;
}
function createButton(text: string, left: string): HTMLButtonElement {
let btn: HTMLButtonElement = document.createElement('button');
btn.textContent = text;
btn.style.position = 'absolute';
btn.style.left = left;
btn.style.top = '20px';
btn.style.padding = '5px 10px';
btn.style.cursor = 'pointer';
document.body.append(btn);
return btn;
}
以下是生成温度云图的步骤:
- 配置图层,一般三层。
typescript
GLOW.Heatmap.layers.push({ name: '上层', offsetY: 1.7 });
GLOW.Heatmap.layers.push({ name: '中层', offsetY: 1 });
GLOW.Heatmap.layers.push({ name: '下层', offsetY: 0.3 });
- 配置数值限定,一般保持默认值即可。
typescript
GLOW.Heatmap.min = 18;
GLOW.Heatmap.max = 30;
- 设置温度云图类型。
typescript
heatmap.heattype = GLOW.HeatmapType.Horizontal;
4.设置图层名称。
typescript
heatmap.layerName = '上层';//水平图需要设置
heatmap.layerName = '';//垂直图设置为空字符串即可
5.设置是否显示数值。默认不显示,如果不需要显示数值,则可以不设置或者显式设置为false。
typescript
heatmap.showValues = true;
6.设置 数据点位
实体对象的温度值。这里需要用到实体对象的 userData
属性,该属性是一个对象,用图层名称作为键,用温度值作为值。
typescript
entity.userData['上层'] = 15;
entity.userData['中层'] = 32;
entity.userData['下层'] = 27.8;
7.调用渲染方法render(),该方法是一个异步方法。
typescript
await heatmap.render();
8.循环刷新。通过定时器循环执行步骤6、7,即可实现温度云图的动态刷新。
9.退出云图。应该先清理定时器,然后调用 heatmap.clean()
方法来清除云图。
typescript
clearTimeout(timeId);
timeId = -1;
heatmap.clean();