【JS】heatmap.js v1.0 到 v2.0,詳細總結一下:)


前段時間,項目要開發熱力圖插件,研究了heatmap.js,打算好好總結一下。

本文主要有以下幾部分內容:

  1. 部分源碼理解
  2. 如何遷移到v2.0
  3. v2.0官方文檔譯文

 

關於heatmap.js介紹,請看這里: http://www.oschina.net/p/heatmap-js

目前,對於熱力圖的開發,百度、高德開發平台上使用的都是這款JS開源庫。當然,現在還有我們公司:P

百度示例:http://developer.baidu.com/map/jsdemo.htm#c1_15

高德示例:http://lbs.amap.com/api/javascript-api/example/layers/heatmap/

PS:本人對JS只能算是初級水平,剛開始寫熱力圖插件的時候,真是一頭霧水。充分利用搜索引擎后,在百度的開源庫發現了這個(示例源文件),總算有點眉目了。替換了地圖實例對象,剩下的難點是圖層處理和像素坐標轉換,刪刪改改,也弄出了插件的1.0版。v2.0版本的內容與v1.0相比還是有很多不同的,經過大半天廢寢忘食的努力,終於遷移到了2.0(准確的說是v2.0.5),也算對得起忘吃的午飯。

 

部分源碼理解

參數max

  經過源碼閱讀和測試,數據集合中的max參數表示熱力點權值的最大值,用於熱力顏色漸變的計算。其本質是熱力區域內部填充顏色的透明度。

使用到max的算式:

(value-min)/(max-min)    
/* 其中,
        value是某個熱力點的權值;
        max是最大權值,默認是1;
        min是最小權值,默認是10;
*/

當熱力點權值大於等於max,熱力點顏色達到最大漸變程度。

當熱力點權值遠遠小於max,熱力點顏色較淺,甚至顯示不出來。

所以,max的設定值會影響到熱力圖的展現效果,需要均衡熱力點權值,合理設置max值。
 
(——為什么顯示不出?根據前面算式,計算結果小於0.01已經不能被識別了。請查看canvas的globalalpha屬性)
 

addData方法

  該方法的參數可以是單個點的對象,也可以是個數組。但是方法內的處理是,在原圖的基礎上每增加一個點就渲染一次。如果參數類型是數組,則遞歸調用本方法,逐個點的增加並渲染。

  如果數據是少量動態增加的,則可以實時的呈現出熱力狀況。當大數據量頻繁更新的時候,推測對性能還是會有一點影響吧,這個需要測試驗證。

  ——2016-11-28 補充驗證結果:使用此方法添加10條數據,幾乎是立刻呈現;添加100條,需要2秒左右;添加1000條,需要20秒左右。測試瀏覽器為Chrome 版本53。

使用刪除方法(即用setData方法重新繪圖)刪除100條、1000條數據,基本都在1秒以內。

  另外一點需要注意的是,新增的熱力點的權值對max的值有影響。源碼中,會對同一坐標點的權值進行累加然后設置到Store._max屬性,這會使顏色漸變的標准發生改變,影響熱圖的一致性。

  github上也有人提出這個問題[How not to change 'max' when adding point with addData?]正問題中所描述的那樣,要想保證顏色漸變的標准在增加熱力點前后保持一致性,需要調用setDataMax方法重新設定max值,目前只能這樣。

 

removeData方法

  我所使用的是heatmap v2.0.5版本,其中removeData方法還是空的,具體處理還沒有實現。所以我在插件中自己寫了一個方法。

采用二次循環,將現存的數據與要刪除的數據進行比對,只保留那些經緯度不相同的數據,以及經緯度相同但是權值差大於0的數據,然后清空畫布,調用setData重新賦值繪圖。

方法有點low,求指點~~

 

內部數據存儲

  heatmap.js內部把數據存儲在Store._data屬性中。其數據格式是二維數組[x: [y: value]],x、y是熱力點的像素坐標,value是熱力點的權值。例如: 
data = [460: [280:15, 255:6], 490: [251:8], 416: [289:9]]

數組的長度是可變的,最外層長度是所有x值中最大的那個數值加1,如 data.length = 491。

每個x元素所對應的y值數組的長度,是x坐標下所有y值中最大的那個數值加1,如 data[460].length = 281 。
 
兩個處理數據的方法:

   _organiseData方法會將外部傳入數據存儲到Store._data中,並且會累計權值。如果本方法是被setData調用,則按照傳入參數中max來渲染;如果是被addData方法調用,則會按累計權值渲染。

   _unOrganizeData方法內部並無特殊處理,只是將內部以二維數組存儲的數據轉換為外部數據格式對象,該方法被getData方法調用,返回熱力數據。

 

如何遷移到v2.0

以下內容來自這里:https://github.com/pa7/heatmap.js/blob/master/docs/how-to-migrate.md

1. element -> container 

 作為熱圖canvas的容器,heatmap作者認為“container”能更加形象的描述這個配置參數,所以原來的element屬性現在叫container。

var cfg = {
   "container": domElement
};

 

2. opacity -> maxOpacity

heatmap.js v2.0中的透明度屬性opacity,會對全局的透明度產生影響(它會為所有熱力點設置透明度,還會阻止顏色漸變的平滑性)。
如果你想讓熱點數據的顏色漸變達到平滑的效果,現在起你需要使用配置屬性maxOpacity。
var cfg = {
   "maxOpacity": .8
}

 另外,opacity、maxOpacity、minOpacity這仨屬性現在都是[0,1]范圍內的數。

 

3. 裝填數據

heatmap.js的作者決定減少API,使其變為更扁平的結構。為了添加數據你不必訪問heatmap的數據存儲,而是向heatmap實例直接添加新數據。同時也擺脫了重復命名。(heatmap.store.addDataPoint -> heatmap.addData, heatmap.store.setDataSet -> heatmap.setData).
var datapoint = { x: 100, y: 100, value: 10 }; 

heatmap.addData(datapoint); 

heatmap.setData({ 
    max: 10, 
    data: [datapoint] 
});

 

同時,你可能注意到:熱力點的權值屬性count現在默認叫value,為了順利遷移你可以把“count”設置為valueField屬性的值。

var datapoint = { x: 100, y: 100, count: 10 };

var heatmap = h337.create({
   container: domElement,
   // ...
   valueField: 'count'
});

heatmap.addData(datapoint);

heatmap.setData({
   max: 10,
   data: [datapoint]
});

 

4. 總結

舊的配置實例:

var cfg = { 
    "element": domElement,
    "opacity": 80 
} 

var heatmap = h337.create(cfg);

heatmap.store.setDataSet(data);

 

變成了新的配置:

var cfg = {
   "container": domElement,
   "maxOpacity": .8
}

var heatmap = h337.create(cfg);

heatmap.setData(data);

 

本人補充幾條:

1. 支持自定義熱點數據的屬性名稱

如果之前你的熱力數據是這樣的:

{"lng":123.456789, "lat":987.654321, "count": 10}

為了向heatmap內部設置數據,你需要將數據轉換成這樣的:

{"x":123.456789, "y":987.654321, "value": 10}

現在,配置參數中新增加了三個屬性xField、yField、valueField,分別對應x坐標、y坐標、權值的屬性名稱。設置了這三個屬性就不需要上面的數據格式轉換了。例如:xField="lng"; yField="lat"; valueField="count;

 

2. 清空畫布

我之前的做法是:

heatmap.clear();

現在是:

heatmap._renderer._clear();

 

3. 重置畫布大小

之前是:

heatmap.set("width", w);
heatmap.set("height", h);
heatmap.store.get("heatmap").resize();

現在改為:

heatmap._renderer.setDimensions(w, h);

 

v2.0官方文檔譯文

下面是我翻譯的heatmap.js v2.0官方文檔。水平有限,如有疏漏或錯誤請指正。

API函數的優先級排序:

  紅色 最常用的函數;-)
  綠色 用於自定義實現
   藍色  較少使用的功能

h337

  • create(configObject)
  • register(pluginKey, plugin)

heatmapInstance

  • addData(object|array)
  • setData(object)
  • setDataMax(number)
  • setDataMin(number)
  • configure(configObject)
  • getValueAt(object)
  • getData()
  • getDataURL()
  • repaint() 

 

h337

"h337"是heatmap.js注冊的全局對象的名字。你可以用它創建heatmap實例。

h337.create(configObject)

返回一個heatmap實例對象 heatmapInstance
使用h337.create創建heatmap實例。通過設置配置參數configObject可以實現熱力圖的自定義。配置參數configObject是必需參數。

可配置的屬性:

  • container 圖像容器 (DOMNode)  必需參數

  它是熱力圖像canvas所依附的DOM節點(熱圖將適應節點的大小)。

  • backgroundColor 背景色 (string)  可選參數

  背景色字符串可以是16進制編碼、英文顏色名稱、rgb顏色。

  • gradient 漸變度 (object)  可選參數

  代表顏色漸變的對象(語法:數值字符串[0,1]: 顏色字符串),請查看代碼示例。

  • radius  半徑 (number)  可選參數

  每個熱力點的半徑(如果節點本身未被指定)。

  • opacity  透明度 (number) [0,1]  可選參數 default = .6   

  heatmap的全局透明度。將覆蓋之前設置的maxOpacity 和 minOpacity。

  • maxOpacity  最大透明度 (number) [0,1]  可選參數

  heatmap將擁有的最大透明度。(會被opacity的設置覆蓋)。

  • minOpacity 最小透明度 (number) [0,1]  可選參數

  heatmap將擁有的最小透明度。(會被opacity的設置覆蓋)。

  • onExtremaChange function callback 回調函數

  傳遞一個回調函數來接收極值變化更新。對於DOM legends很有用。

  • blur  濾鏡系數 (number) [0,1] 可選參數 default = 0.85 ,應用於所有點數據。系數越高,漸變越平滑,默認是0.85

  濾鏡系數將應用於所有熱點數據。系數越高,顏色漸變越平滑。

  • xField (string) 可選參數 default = "x" 

  熱點數據x坐標的屬性名稱。

  • yField (string) 可選參數 default = "y" 

  熱點數據y坐標的屬性名稱。

  • valueField (string) 可選參數 default = "value" 

  熱點數據權值的屬性名稱。

 

配置示例

簡單配置和標注顏色漸變
// create configuration object 
var config = { 
    container: document.getElementById('heatmapContainer'),
    radius: 10, 
    maxOpacity: .5, 
    minOpacity: 0, 
    blur: .75};
// create heatmap with configuration 
var heatmapInstance = h337.create(config);

 自定義顏色漸變

// create configuration object 
var config = { 
    container: document.getElementById('heatmapContainer'), 
    radius: 10, 
    maxOpacity: .5, 
    minOpacity: 0, 
    blur: .75, 
    gradient: { 
        // enter n keys between 0 and 1 here 
        // for gradient color customization 
        '.5': 'blue', 
        '.8': 'red', 
        '.95': 'white' 
    }};var heatmapInstance = h337.create(config);

 

heatmapInstance

熱力圖實例是通過 h337.create方法返回的。熱力圖實例有自己的內部數據存儲對象和渲染對象,你可以通過它們來操作數據,使熱力圖得到更新(根據需要決定是局部更新,還是全部更新)。

heatmapInstance.addData(object|array)

返回 heatmapInstance
使用此功能只是用於隨時添加數據,而不是用於數據初始化。addData方法可以向heatmap的數據存儲對象添加單個或者多個點的數據。
// a single datapoint 
var dataPoint = { 
    x: 5, // x coordinate of the datapoint, a number 
    y: 5, // y coordinate of the datapoint, a number 
    value: 100 // the value at datapoint(x, y) 
}; 
heatmapInstance.addData(dataPoint);
// multiple datapoints (for data initialization use setData!!) 
var dataPoints = [dataPoint, dataPoint, dataPoint, dataPoint]; heatmapInstance.addData(dataPoints);

 

heatmapInstance.setData(object)

返回heatmapInstance

通過數據集合初始化heatmap。“min”、“max”和“data”這三個參數是必需的。setData從實例中清除所有之前存儲的數據,然后重新初始化數據存儲對象。
var data = { 
    max: 100, 
    min: 0, 
    data: [ 
        dataPoint, dataPoint, dataPoint, dataPoint 
    ]}; 
heatmapInstance.setData(data);

 

heatmapInstance.setDataMax(number)

返回 heatmapInstance
改變數據集的上限並且觸發完全渲染。
heatmapInstance.setDataMax(200);
// setting the maximum value triggers a complete rerendering of the heatmap 
heatmapInstance.setDataMax(100);

 

heatmapInstance.setDataMin(number)

返回 heatmapInstance
改變數據集的下限並且觸發完全渲染。
heatmapInstance.setDataMin(10);
// setting the minimum value triggers a complete rerendering of the heatmap 
heatmapInstance.setDataMin(0);

 

heatmapInstance.configure(configObject)

返回 heatmapInstance
在heatmap實例初始化之后重新配置參數。觸發完全渲染。
var nuConfig = { 
    radius: 10, 
    maxOpacity: .5, 
    minOpacity: 0, 
    blur: .75}; 
heatmapInstance.configure(nuConfig);

 

heatmapInstance.getValueAt(object)

返回熱力點的權值。
注意:如果該點沒有被存儲的話,返回值是基於顏色漸變混合后的填充值。
heatmapInstance.addData({ x: 10, y: 10, value: 100});
// get the value at x=10, y=10 
heatmapInstance.getValueAt({ x: 10, y: 10 }); // returns 100

 

heatmapInstance.getData()

返回一個持久化並且可重裝的JSON對象。

var currentData = heatmapInstance.getData();
// now let's create a new instance and set the data 
var heatmap2 = h337.create(config); 
heatmap2.setData(currentData); // now both heatmap instances have the same content

 

heatmapInstance.getDataURL()

返回值是base64編碼的dataURL字符串。

heatmapInstance.getDataURL(); // data:image/png;base64... 
// ready for saving locally or on the server

 

heatmapInstance.repaint()

返回 heatmapInstance
重新繪制整個熱力圖canvas。

 

----------------------完 結----------------------------------------------------------------------------------------------------------------------


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM