最近玩了玩圖表的熱力圖,由於公司有同事想作無線設備的信號強度可視化,在不一樣頻段(x 軸: MHz)的信號強度 ( y軸: dbm)自己就是一個兩維的數據,加上隨着時間的信號強度變化,在二維空間中會累加出熱區效果,咱們能夠計算出熱力值做爲第三維數據。git
ps: 如下圖表顯示的都是隨機的模擬數據。github
利用chart.js 咱們能夠完成基本的座標軸和信號強度線條的繪製,可是熱力圖是chart.js 自己不支持的,因此須要二次開發。 熱力圖實質上能夠認爲是點密度圖,就是數據點在空間中的密集程度,越密集值越高。具體的算法能夠根據本身的需求來定,可是主流的作法仍是點密度。這種算法能夠是截斷的,也就是搜索半徑內有多少數據點,就做爲熱力值。也能夠是隨着距離衰減的,好比IDW。算法
距離越遠的點對於當前單元格的熱力值影響相對弱,這也是地理學第必定律的典型應用。canvas
static computeDensity(heatSets: any[], lineSets: number[], maxValueY: number) {
if (!heatSets) {
mat = this.genMat(matY, matX, 0); // 初始化 Y*X 的矩陣
} else {
mat = heatSets; // 上一次累加後的熱力值矩陣
}
//
for (let x = 0; x < matX; x += 1) {
try {
// 把當前的信號強度點直接累加到原有的熱力值矩陣上,若是想要把信號的其餘屬性做爲權重,那麼就把1 替換成當前點的某屬性值
mat[lineSets[x] - 1][x] += 1;
this.addBuffer(mat, lineSets, x, radius); // 搜索半徑爲 radius, 對於當前數據點,咱們要把ta 累加到附近的熱力矩陣單元格內。
}
}
}
// 根據熱力矩陣的統計結果(最大最小值)來限定邊界顏色,從紅色漸變到背景色
static setColor(densityData: DensityData) {
// 使得每一個熱力值都對應 不一樣的漸變色。
}
複製代碼
性能在實時性要求較高的熱力圖中很重要,包括 heatmap.js 這種著名的熱力圖庫是具備很高性能的,由於ta 直接在canvas 的渲染函數裏面 putImageDate, 利用漸變函數直接上色,性能是很是高的, 毫秒級別。bash
而我最開始的熱力計算函數是很笨的,遍歷整個矩陣(假如n * n)去搜索要計算熱力的數據點或者線的節點(m個點),複雜度很高,最多須要執行 n * n * m 次累加函數。 可是後來逆向思惟了一下,直接遍歷數據點(m個),最多再加上遍歷周邊半徑(rad)內的單元格,至多執行 m * rad 次累加函數。 這個複雜度大大下降,耗時從1000ms左右降到10ms 之內。 原諒我搞不清楚大O 算法複雜度。。哈哈函數
關於點密度的計算仍是挺有趣的,後面整理後再把關鍵代碼放到Github 上。對,就是那個已經被微軟收購的Github..性能