首頁  >  文章  >  web前端  >  基於HTML5的Web SCADA報表圖文代碼詳解

基於HTML5的Web SCADA報表圖文代碼詳解

黄舟
黄舟原創
2017-04-01 11:05:453198瀏覽

背景

最近在一個 SCADA 專案中遇到了在 Web 頁面中展示設備報表的需求。一個完整的報表,一般包含了篩選操作區、表格、Chart、展板等多種元素,而其中的資料表格是最常用的控制項。在以往的工業項目中,所有的表格看起來千篇一律,就是透過數字和簡單的背景顏色變化來展示相關資訊。但現在透過各種行動 App 和 Web 應用的薰陶,人們的美學和要求都在不斷提高,尤其是在 Web 專案中,也採用老式的數位表格確實也有點落伍了。 

如何選擇一個合適的 HTML 前端表格控制項?此處可以省略一萬字。哈哈。 jQuery、Angular、React 等陣營中的控制項庫中都有不少成熟案例,但是這些基於DOM 的控制項也有不足,一個是效率問題:如果在資料量大表格的中採用自訂的儲存格控制項,對瀏覽器的負擔實在太重,尤其是行動端。另一個問題是開發效率,上述的控制項庫中各自的封裝程度、介面形式都有所不同,但整體上還是要求開發者對 CSS、JS 都有較深的了解。還有控制的複用、嵌入、發布、移植,也都是問題。 

基於上述的考慮,最後採用了基於 Canvas 的 HT。透過HT 表格控制項的自訂渲染接口,以及Web Worker 的多執行緒資料模擬,實現的表格控制項效果如下: 

基於HTML5的Web SCADA報表圖文代碼詳解

開始

首先我們要做的就是結合業務邏輯,對表格中不同列的數據,進行不同的渲染。例如設備歷史資訊中的運行時間、停機時間等,比較適合用圓餅圖來總結展示,使用者就可以很直覺的從清單上比較出設備的歷史狀況。 我們來看看這一步是怎麼實現的。 

HT 有自己的 DataModel 資料模型,省略了我們對資料狀態管理、時間發放、ui刷新的開發工作。 DataModel 容器中的子元素 Data,也就是 HT 中最基礎的資料結構,可以對應到不同的ui控制項。在畫布上,Data 可以展示成向量、圖片或文字等,在樹狀控制項上,Data 展示為樹的節點。在表格當中每個 Data 對應表格中的一行 Row。 也就是表格控制項本身包含一個 DataModel,在繪製時,將這個 Model 中的每個 Data 都畫成一行。 不同的列,展示的是該 Data 中的不同屬性。例如我們可以把設備的停機時間,就儲存到 Data 的 stopping 屬性。在配置表格的列Column 資訊時,我們可以指定該列的表頭描述“停機時間”,其資料單元格對應Data 的Stopping 屬性,以及自訂繪製格式:

{
    name: 'stopping',       //对应的data属性
    accessType: 'attr',
    align: 'center',        
    color: '#E2E2E2',       //文字颜色
    displayName: '停机',    //表头描述
    drawCell: pageTable.getDrawLegend('stopping','#E2E2E2')
},

自訂渲染

在儲存格的基本顯示格式中,已經預設提供了文字、陣列、顏色等類型,可以自動的對資料格式化,並展示為文字或背景顏色等,但還未滿足我們的個性需求,因此就要將Column 中的drawCell 重載為自訂的渲染函數。 drawCell 的參數:function (g, data, selected, column, x, y, w, h, view),其中g 是Canvas 的環境信息,data 是該行的數據體,我們根據這些信息,再利用HTML5 原生的Canvas API 就可以畫出想要的效果。 

我懶得親自直接用 HTML5 的原生介面? HT 提供了對 Canvas API 的封裝接口,包括各種向量類型以及一些簡單的 Chart。利用該功能,可以輕鬆組合出複雜的效果,具體介紹可以參考我們的向量手冊

先創建一個對象,該image 向量對象負責包含對組合向量的描述信息,然後將該image 對像以及drawCell 的上下文訊息,作為參數傳入ht.Default.drawStretchImage 函數,即可實現自訂繪製。

//drawCellfunction (g, data, selected, column, x, y, w, h, tableView) {    
var value = data.a(attr);    var image = {
        width: 60,
        height: 30,
        comps: [
            {
                type: 'rect',
                rect: [11,11,8,8],
                borderWidth: 1,
                borderColor: '#34495E',
                background: legendColor,
                depth: 3
            },
            {
                type: 'text',
                text: value,
                rect:[30, 0, 30, 30],
                align: 'left',
                color: '#eee',
                font: 'bold 12px Arial'
            }
        ]};
    ht.Default.drawStretchImage(g, image, 'centerUniform', x, y, w, h);
}

因為有多個 Legend 圖例顯示的列,所以我們可以簡單包裝一下,用了一個 getDrawLegend 函數,參數是該列圖例的顏色及 Data 屬性名稱,傳回值是 drawCell 函數。

getDrawLegend: function(attr,legendColor){return drawCell}

至此,我們就完成了啟停時間這幾列的自訂繪製: 

基於HTML5的Web SCADA報表圖文代碼詳解

#

“统计”列的饼图,实际上更简单。还是利用 HT 的矢量接口,把上述几项时间数据传入饼图矢量结构即可。

var values = [
    data.a('running'), 
    data.a('stopping'), 
    data.a('overhauling')
];var image = {
    width: 200,
    height: 200,
    comps: [
        {
            type: 'pieChart',
            rect: [20,20, 150, 150],
            hollow: false,
            label: false,
            labelColor: 'white',
            shadow: true,
            shadowColor: 'rgba(0, 0, 0, 0.8)',
            values: values,
            startAngle: Math.PI,
            colors: pieColors
        }
    ]
};

其他列的渲染过程大同小异。在“风速”列中,我们可以根据风速大小计算一个颜色透明值,来实现同一色系的映射变换,比原来那种非红即绿的报警表,看起来更舒服一些。在“可用率”列,用 Rect 的不同长度变化,来模拟进度条的效果。在功率曲线中稍微有点不同,因为想实现曲线覆盖区域的颜色渐变,在 HT 的 lineChart 中没有找到相关接口,所以直接采用了 Canvas 绘制。 

基於HTML5的Web SCADA報表圖文代碼詳解

为了运行效率考虑,在表格的单元格中绘制 Chart,应该追求简洁大方,一目了然。这几个 Legend 图例小矩形,其实是应该画在表头的。我为了偷懒,就画在了单元格,导致画面显得有点乱。

Web Worker

众所周知,浏览器的 JS 环境是基于单进程的,在页面元素较多,而且有很大运算需求的情况下,会导致无法兼顾渲染任务和计算任务,造成页面卡顿或失去响应。在这种情况,可以考虑使用 Web Worker 的多线程,来分担一些计算任务。 

Web Worker 是 HTML5 的多线程 API,和我们原来传统概念中的多线程开发有所不同。Web Worker 的线程之间,没有内存共享的概念,所有信息交互都采用 Message 的异步传递。这样多线程之间无法访问对方的上下文,也无法访问对方的成员变量及函数,也不存在互斥锁等概念。在消息中传递的数据,也是通过值传递,而不是地址传递。 

在 Demo 中,我们利用 Web Worker 作为模拟后端,产生虚拟数据。并采用前端分页的方式,从 worker 获取当前页显示条目的相关数据。 在主线程中,创建 Web Worker注册消息监听函数。

worker = new Worker("worker.js");    
worker.addEventListener('message', function(e) {  
    //收到worker的消息后,刷新表格
    pageTable.update(e.data);
});

pageTable.request = function(){    //向worker发送分页数据请求
    worker.postMessage({
        pageIndex: pageTable.getPageIndex(),
        pageRowSize: pageTable.getPageRowSize()        
    });                 
}; 
pageTable.request();

本处的new Worker创建,对于主线程来说是异步的,等加载完 worker.js,并完成初始化后,该 worker 才是真正可用状态。我们不需要考虑 worker 的可用状态,可以在创建语句后直接发送消息。在完成初始化之前向其发送的请求,都会自动保存在主线程的临时消息队列中,等 worker 创建完成,这些信息会转移到 worker 的正式消息队列。 

在 worker 中,创造虚拟随机数据,监听主线程消息,并返回其指定的数据。

self.addEventListener('message', function(e) {    
var pageInfo = getPageInfo(e.data.pageIndex, e.data.pageRowSize);   
    self.postMessage(pageInfo);
}, false);

由于前面提到的无法内存共享,Web Worker 无法操作 Dom,也不适用于与主线程进行大数据量频繁的交互。那么在生产环境中,Web Worker 能发挥什么作用?在我们这种应用场景,Web Worker 适合在后台进行数据清洗,可以对从后端取到的设备历史数据进行插值计算、格式转换等操作,再配合上 HT 的前端分页,就能实现大量数据的无压力展示。

分页

传统上有后端分页和前端分页,我们可以根据实际项目的数据量、网速、数据库等因素综合考虑。 

采用后端分页的话,可以简化前端架构。缺点是换页时会有延迟,用户体验不好。而且在高并发的情况下,频繁的历史数据查询会对后端数据库造成很大压力。 

采用前端分页,需要担心的是数据量。整表的数据量太大,会造成第一次获取时的加载太慢,前端资源占用过多。 

在本项目中,得益于给力的 GOLDEN 实时数据库,我们可以放心的采用前端分页。历史数据插值、统计等操作可以在数据库层完成,传递到前端的是初步精简后的数据。在数千台设备的历史查询中,得到的数据量完全可以一次发送,再由前端分页展示。 

在某些应用场景,我们会在表格中显示一些实时数据,这些数据是必须是动态获取的。类似在 Demo 中的趋势刷新效果,我们可以在创建表格时批量获取所有历史数据,然后再动态向数据库获取当前页所需的实时数据。如果网速实在不理想,也可以先只获取第一页的历史数据,随后在后台线程慢慢接收完整数据。 

这样的架构实现了海量数据的快速加载,换页操作毫无延迟,当前页面元素实时动态刷新的最终效果。 

还有一些传统客户,喜欢在一张完整的大表上进行数据筛选、排序等操作。 

我们可以把 Demo 中的数据总量改成一万条,单页数量也是一万条,进行测试:

基於HTML5的Web SCADA報表圖文代碼詳解

出乎意料的是,HT 面对上万数据量的复杂表格,轻松经受住了考验。页面的滚动、点击等交互毫无影响,动态刷新没有延迟,表格加载、排序等操作时,会有小的卡顿,在可接受的程度之内。当然也跟客户端的机器配置有关。可以想象,几万个 Chart的展示以及动态刷新,对于基于dom的控件几乎是件无法完成的任务。关于 HT 的其他矢量和控件,同样有高性能特性:

后记

如前文所述,我们基于 HT 的表格实现了海量数据的可定制展现,并取得了令人满意的效果。以下是一些还可以改进的地方。 

在 Demo 中,通过对 HT 表格控件的 drawCell 进行重载,实现了自定义渲染,然后把这些 drawCell 放到了 PageTable 的原型函数中,以供 Column 调用。实际上,更好的办法应该是把这些常见的 Chart、图例封装到 Column 的基本类型中,那样在配置表格 Column 列时,可以指定 type 为 pieChart 或 lineChart 即可,不需再自行绘制相关矢量。 

对于这些表格中的 Chart,也可以增加一些交互接口,例如可以增加单元格 Tooltip 的自定义渲染功能,在鼠标停留时浮出一个信息量更大的 Chart,可以对指定设备进行更深入的了解。 
界面美观优化。对 HT 的控件进行颜色定制,可以通过相关接口进行配置:

var tableHeader = pageTable.getTablePane().getTableHeader();    
tableHeader.getView().style.backgroundColor = 'rgba(51,51,51,1)';     
tableHeader.setColumnLineColor('#777');var tableView = pageTable.getTablePane().getTableView();                 
tableView.setSelectBackground('#3D5D73');
tableView.setRowLineColor('#222941');
tableView.setColumnLineVisible(false);                
tableView.setRowHeight(30);

今后也可以对htconfig进行全局配置,在单独文件中进行样式的整体管理,实现外观样式与功能的分离,有助于工程管理。

以上是基於HTML5的Web SCADA報表圖文代碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn