從零開發(fā)可視化大屏制作平臺
幾個月前開源的H5頁面制作平臺H5-Dooring 收到了很多熱心的反饋和交流,順著筆者之前的規(guī)劃,我們又做了一款可視化大屏編輯器V6.Dooring。 接下來筆者就來帶大家一起看看我們的方案設(shè)計和技術(shù)實現(xiàn)。
你將收獲
- 可視化大屏產(chǎn)品設(shè)計思路
- 主流可視化圖表庫技術(shù)選型
- 大屏編輯器設(shè)計思路
- 大屏可視化編輯器Schema設(shè)計
- 用戶數(shù)據(jù)自治探索
在介紹之前,我們先看看實現(xiàn)的效果展示。
效果預(yù)覽
方案實現(xiàn)
可視化大屏產(chǎn)品設(shè)計思路
目前很多企業(yè)或多或少的面臨“信息孤島”問題,各個系統(tǒng)平臺之間的數(shù)據(jù)無法實現(xiàn)互通共享,難以實現(xiàn)一體化的數(shù)據(jù)分析和實時呈現(xiàn)。
相比于傳統(tǒng)手工定制的圖表與數(shù)據(jù)儀表盤,可視化大屏制作平臺的出現(xiàn),可以打破抵消的定制開發(fā),數(shù)據(jù)分散的問題,通過數(shù)據(jù)采集、清洗、分析到直觀實時的數(shù)據(jù)可視化展現(xiàn),能夠多方位、多角度、全景展現(xiàn)各項指標(biāo),實時監(jiān)控,動態(tài)一目了然。
針對以上需求, 我們設(shè)計了一套可視化大屏解決方案, 具體包含如下幾點;
上圖是筆者4個月前設(shè)計的基本草圖, 后期會持續(xù)更新. 通過以上的設(shè)計分解,我們基本可以搭建一個可自己定制的數(shù)據(jù)大屏。
主流可視化圖表庫技術(shù)選型
目前筆者調(diào)研的已知主流可視化庫有:
- echart 一個基于 JavaScript 的老牌開源可視化圖表庫
- D3.js 一個數(shù)據(jù)驅(qū)動的可視化庫, 可以不需要其他任何框架獨立運行在現(xiàn)代瀏覽器中,它結(jié)合強大的可視化組件來驅(qū)動 DOM 操作
- antv 包含一套完整的可視化組件體系
- Chart.js 基于 HTML5 的 簡單易用的 JavaScript 圖表庫
- metrics-graphics 建立在D3之上的可視化庫, 針對可視化和布置時間序列數(shù)據(jù)進行了優(yōu)化
- C3.js 通過包裝構(gòu)造整個圖表所需的代碼,使生成基于D3的圖表變得容易
我們使用以上任何一個庫都可以實現(xiàn)我們的可視化大屏搭建的需求,各位可以根據(jù)喜好來選擇。
大屏編輯器設(shè)計思路
在上面的分析中我們知道一個大屏編輯器需要有個編輯器核心, 主要包含以下部分;
- 組件庫
- 拖拽(自由拖拽, 參考線, 自動提示)
- 畫布渲染器
- 屬性編輯器
如下圖所示:
組件庫我們可以用任何組件封裝方式(react/vue等),這里沿用H5-Dooring的可視化組件設(shè)計方式,對組件模型進行優(yōu)化和設(shè)計。
類似的代碼如下:
import { Chart } from '@antv/f2';
import React, { memo, useEffect, useRef } from 'react';
import styles from './index.less';
import { IChartConfig } from './schema';
const XChart = (props:IChartConfig) => {
const { data, color, size, paddingTop, title } = props;
const chartRef = useRef(null);
useEffect(() => {
const chart = new Chart({
el: chartRef.current || undefined,
pixelRatio: window.devicePixelRatio, // 指定分辨率
});
// step 2: 處理數(shù)據(jù)
const dataX = data.map(item => ({ ...item, value: Number(item.value) }));
// Step 2: 載入數(shù)據(jù)源
chart.source(dataX);
// Step 3:創(chuàng)建圖形語法,繪制柱狀圖,由 genre 和 sold 兩個屬性決定圖形位置,genre 映射至 x 軸,sold 映射至 y 軸
chart
.interval()
.position('name*value')
.color('name');
// Step 4: 渲染圖表
chart.render();
}, [data]);
return (
<div className={styles.chartWrap}>
<div className={styles.chartTitle} style={{ color, fontSize: size, paddingTop }}>
{title}
</div>
<canvas ref={chartRef}></canvas>
</div>
);
};
export default memo(XChart);
以上只是一個簡單的例子, 更具業(yè)務(wù)需求的復(fù)雜度我們往往會做更多的控制,比如動畫(animation),事件(event),數(shù)據(jù)獲取(data inject)等。
組件拖拽可以采用市面已有的Dragable等插件,也可以采用H5-Dooring的智能網(wǎng)格拖拽,這里筆者選擇自由拖拽來實現(xiàn),已有的有:
- rc-drag
- sortablejs
- react-dnd
- react-dragable
- vue-dragable
等等,具體拖拽呈現(xiàn)流程如下:
具體拖拽流程就是:
- 使用H5 dragable API拖拽左側(cè)組件(component data)進入目標(biāo)容器(targetBox)
- 監(jiān)聽拖拽結(jié)束事件拿到拖拽事件傳遞的data來渲染真實的可視化組件
- 可視化組件掛載,schema注入編輯面板,編輯面板渲染組件屬性編輯器
- 拖拽,屬性修改,更新
- 預(yù)覽,發(fā)布
組件的schema參考Dooring DSL設(shè)計
可視化大屏數(shù)據(jù)自治探索
目前我們實現(xiàn)的搭建平臺可以靜態(tài)的設(shè)計數(shù)據(jù)源,也可以注入第三方接口,如下:
我們可以調(diào)用內(nèi)部接口來實時獲取數(shù)據(jù),這塊在可視化監(jiān)控平臺用的場景比較多,方式如下:
參數(shù)(params)編輯區(qū)可以自定義接口參數(shù),代碼編輯器筆者這里推薦兩款,大家可以選用:
- react-monaco-editor
- react-codemirror2
使用以上之一可以實現(xiàn)mini版vscode,大家也可以嘗試一下。
輔助功能
可視化大屏一鍵截圖 一鍵截圖功能還是沿用H5-Dooring 的快捷截圖方案, 主要用于對大屏的分享,海報制作等需求, 我們可以使用以下任何一個組件實現(xiàn):
- dom-to-image
- html2canvas
撤銷重做
撤銷重做功能我們可以使用已有的庫比如react-undo,也可以自己實現(xiàn), 實現(xiàn)原理:
有點鏈表的意思, 我們將每一個狀態(tài)存儲到數(shù)組中,通過指針來實現(xiàn)撤銷重做的功能,如果要想更健壯一點,我們可以設(shè)計一套“狀態(tài)淘汰機制”,設(shè)置可保留的最大狀態(tài)數(shù),之前的自動淘汰(刪除,更高大上一點的叫出棧),這樣可以避免復(fù)雜操作中的大量狀態(tài)存儲,節(jié)約瀏覽器內(nèi)存。
標(biāo)尺參考線 標(biāo)尺和參考線這里我們自己實現(xiàn),通過動態(tài)dom渲染來實現(xiàn)參考線在縮放后的動態(tài)收縮,實現(xiàn)方案核心如下:
arr.forEach(el => {
let dom = [...Array.from(el.querySelectorAll('.calibrationNumber'))][0] as HTMLElement;
if (dom) {
dom.style.transform = `translate3d(-4px, -8px, 0px) scale(${(multiple + 0.1).toFixed(
1,
)})`;
}
});