九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
基于Canvas的熱力圖繪制方法

一. 介紹

最近參與的一個(gè)項(xiàng)目Marmot中需要根據(jù)點(diǎn)坐標(biāo)繪制熱力圖。

熱力圖

以特殊高亮的形式顯示訪客熱衷的頁(yè)面區(qū)域或訪客所在的地理區(qū)域

特點(diǎn)為:

1. 可以顯示不可點(diǎn)擊區(qū)域發(fā)生的事情。你將發(fā)現(xiàn)用戶經(jīng)常會(huì)點(diǎn)擊那些不是鏈接的地方,也許你應(yīng)該在那個(gè)地方放置一個(gè)資源鏈接。比如:如果你發(fā)現(xiàn)人們總是在點(diǎn)擊某個(gè)產(chǎn)品圖片,你能想到的是,他們也許想看大圖,或者是想了解該產(chǎn)品的更多信息。 同樣,他們可能會(huì)錯(cuò)誤地認(rèn)為特別的圖片就是導(dǎo)航鏈接。

2. 熱力圖同時(shí)還能告訴你,頁(yè)面的哪些部分吸引了大多數(shù)用戶的注意。這對(duì)那些對(duì)web分析數(shù)據(jù)沒(méi)有很多經(jīng)驗(yàn)的產(chǎn)品人員非常有用。

3. 如果你在一個(gè)頁(yè)面上有多個(gè)鏈接指向同一個(gè)URL,例如:如果有不同位置的3個(gè)鏈接指到同一個(gè)特定的產(chǎn)品頁(yè)面 ,那么熱力圖將會(huì)顯示你的訪客最喜歡點(diǎn)擊哪一個(gè)鏈接,這將幫助你提升網(wǎng)頁(yè)的設(shè)計(jì)并讓它對(duì)用戶更加友好,不過(guò)實(shí)現(xiàn)這個(gè)功能需要一些設(shè)置。

…………

實(shí)例如下:

需要注意的是上圖實(shí)例粒度粗,梯度小,容差大。反映了熱力圖的一個(gè)屬性:趨勢(shì)相關(guān)。不過(guò),熱力圖也可以做到粒度細(xì),梯度大,容差小。這完全是依據(jù)采樣數(shù)據(jù)的精確性以及分析需求來(lái)做的。給個(gè)例子(Google的眼動(dòng)分析[焦點(diǎn)梯度]圖):

下面介紹熱力圖繪制的方法,注意,以下代碼并沒(méi)有檢測(cè)數(shù)據(jù)有效性,也沒(méi)有對(duì)數(shù)據(jù)進(jìn)行過(guò)濾,剔除臟數(shù)據(jù),同時(shí)沒(méi)有處理異常。實(shí)際使用時(shí)請(qǐng)不要忽略此類情況,否則會(huì)對(duì)最終結(jié)果造成干擾……

二. 繪制

問(wèn)題描述:

假設(shè)有一塊畫布,1200px*2000px尺寸,一組坐標(biāo)數(shù)據(jù),格式為[x,y]二維數(shù)組,量級(jí)為10000~100000,采樣粒度為7*7。依據(jù)點(diǎn)坐標(biāo)的分布密度繪制熱力圖

方法一


思路:使用canvas元素標(biāo)簽將所有點(diǎn)繪制到畫布上,每個(gè)點(diǎn)給予較低的透明度。然后獲取畫布每個(gè)點(diǎn)的位數(shù)據(jù),根據(jù)其alpha值(alpha ∈ [0, 255])的大小計(jì)算每一位的r,g,b的值,得出所有新的位數(shù)據(jù)之后,重新繪制。使之呈現(xiàn)為紅色↔藍(lán)色漸變。

代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*假設(shè)點(diǎn)坐標(biāo)為aXY,二維數(shù)組*/
var aXY = [[x1, y1], [x2, y2], [x3, y3], [x4, y4]...];
//獲取canvas的context
var context = canvas.getContext('2d');
var pi2 = Math.PI * 2;
//設(shè)置填充樣式,透明度為0.1
context.fillStyle = 'rgba(255,30,0,0.1)';
for (var i = 0, len = aXY.length; i < len; i++) {
var x = aXY[i][0], y = aXY[i][1];
context.beginPath();
//繪制圓點(diǎn)
context.arc(x, y, 6, 0, pi2, true);
context.closePath();
context.fill();
}
//獲取這個(gè)畫布的位數(shù)據(jù)
var imgd = context.getImageData(0, 0, 1200, 2000);
var pix = imgd.data;
// 循環(huán)計(jì)算rgb,使之根據(jù)alpha值映射到紅藍(lán)漸變
for (var i = 0, n = pix.length; i < n; i += 4) {
//位數(shù)據(jù)的格式為[rgbargbargba……],每個(gè)rgba代表了每個(gè)點(diǎn)的rgba四個(gè)通道的值
var a = pix[i+3]; //alpha
//red
pix[i ] = 128 * Math.sin((1 / 256 * a - 0.5 ) * Math.PI ) + 200;
//green
pix[i+1] = 128 * Math.sin((1 / 128 * a - 0.5 ) * Math.PI ) + 127;
//blue,128之后直接衰減為0
pix[i+2] = 256 * Math.sin((1 / 256 * a + 0.5 ) * Math.PI );
pix[i+3] = pix[i+3] * 0.8;
}
context.putImageData(imgd, 0, 0);

 

上面的代碼將會(huì)呈現(xiàn):

顯而易見(jiàn),這并不是熱力圖,但是可以精確反映每個(gè)點(diǎn)的分布密度,紅色表示在該區(qū)域的點(diǎn)數(shù)據(jù)較多,淺,藍(lán)色表示密度小。那么如何改進(jìn)?

使用徑向漸變代替圓點(diǎn)的繪制,用以表示每一個(gè)點(diǎn)向周圍的點(diǎn)的輻射,漸變色的疊加可以展現(xiàn)梯度變換的效果。代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
var aXY = [[x1, y1], [x2, y2], [x3, y3], [x4, y4]...];
var context = canvas.getContext('2d');
for (var i = 0, len = aXY.length; i < len; i++) {
var x = aXY[i][0], y = aXY[i][1];
//繪制徑向漸變
var radgrad = this.context.createRadialGradient(x, y, 1, x, y, 8);
//錨點(diǎn)
radgrad.addColorStop( 0, 'rgba(255,30,0,1)');
//錨點(diǎn)
radgrad.addColorStop( 1, 'rgba(255,30,0,0)');
context.fillStyle = radgrad;
context.fillRect( x - 8, y - 8, 16, 16);
}

 

效果如下:

方案度量:這是比較簡(jiǎn)單的實(shí)現(xiàn)方案,稍微麻煩的地方在于根據(jù)alpha值計(jì)算紅藍(lán)綠值,使得alpha高的地方顯示紅色,alpha低的顯示藍(lán)色,中間部分顯示黃/綠色(考慮到效率與簡(jiǎn)單性,使用了簡(jiǎn)單的三角函數(shù),如果需要更為精確的色相漸變,可以使用冪次變換)。同時(shí)這個(gè)方案的缺點(diǎn)也十分明顯:在點(diǎn)數(shù)據(jù)量低的時(shí)候效率很高,但是點(diǎn)數(shù)據(jù)超過(guò)10000之后就會(huì)有明顯的時(shí)間延遲>3s,原因在于循環(huán)繪制漸變色會(huì)消耗資源。其次該方案的性能也會(huì)取決于畫布的大小。畫布大的情況,比如畫布尺寸為1200*3000,對(duì)其取位數(shù)據(jù)的時(shí)候,將會(huì)循環(huán)360萬(wàn)次,同時(shí)進(jìn)行3*360萬(wàn)sin運(yùn)算~~對(duì)于客戶端性能是個(gè)問(wèn)題。

方法二

思路:對(duì)所有點(diǎn)數(shù)據(jù)進(jìn)行計(jì)算,得出每個(gè)點(diǎn)的密度值,然后依據(jù)密度值由低到高,繪制點(diǎn)數(shù)據(jù)。

代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
var points = [[x1, y1], [x2, y2], [x3, y3], [x4, y4]...];
var cache = {};
//計(jì)算每個(gè)點(diǎn)的密度
for (var i = 0, len = points.length; i < len; i++) {
for (var j = 0, len2 = points[i].length; j < len2; j++) {
var key = points[i][j][0] + '*' + points[i][j][1];
if (cache[key]) {
cache[key] ++;
} else {
cache[key] = 1;
}
}
}
//點(diǎn)數(shù)據(jù)還原
var oData = [];
for (var m in cache) {
if (m == '0*0') continue;
var x = parseInt(m.split('*')[0], 10);
var y = parseInt(m.split('*')[1], 0);
oData.push([x, y, cache[m]]);
}
//簡(jiǎn)單排序,使用數(shù)組內(nèi)建的sort
oData.sort(function(a, b){
return a[2] - b[2];
});
var max = oData[oData.length - 1][2];
var pi2 = Math.PI * 2;
//設(shè)置閾值,可以過(guò)濾掉密度極小的點(diǎn)
var threshold = this._points_min_threshold * max;
//alpha增強(qiáng)參數(shù)
var pr = (Math.log(245)-1)/245;
for (var i = 0, len = oData.length; i < len; i++) {
if (oData[i][2] 0 ? 0 : 1);
//q參數(shù)用于平衡梯度差,使之符合人的感知曲線log2N,如需要精確梯度,去掉log計(jì)算
var q = parseInt(Math.log(oData[i][2]) / Math.log(max) * 255);
var r = parseInt(128 * Math.sin((1 / 256 * q - 0.5 ) * Math.PI ) + 200);
var g = parseInt(128 * Math.sin((1 / 128 * q - 0.5 ) * Math.PI ) + 127);
var b = parseInt(256 * Math.sin((1 / 256 * q + 0.5 ) * Math.PI ));
var alp = (0.92 * q + 20) / 255;
//如果需要灰度增強(qiáng),則取消此行注釋
//var alp = (Math.exp(pr * q + 1) + 10) / 255
var radgrad = this.context.createRadialGradient(oData[i][0], oData[i][1], 1, oData[i][0], oData[i][1], 8);
radgrad.addColorStop( 0, 'rgba(' + r + ',' + g + ','+ b + ',' + alp + ')');
radgrad.addColorStop( 1, 'rgba(' + r + ',' + g + ','+ b + ',0)');
this.context.fillStyle = radgrad;
this.context.fillRect( oData[i][0] - 8, oData[i][1] - 8, 16, 16);
}

以上代碼結(jié)果如下:

大約處理了25000個(gè)點(diǎn),用時(shí)大約700ms(鄙人的小本性能還行)。屬于可接受范圍內(nèi)。

方案度量:此方案性能比方案一有明顯優(yōu)勢(shì)。目前Marmot采用此方案。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
canvas 心形
實(shí)例講解利用HTML5 Canvas API操作圖形旋轉(zhuǎn)的方法
JavaScript圖形實(shí)例:黃金螺旋線
JavaScript動(dòng)畫實(shí)例:沿五角星形線擺動(dòng)的小圓
JavaScript圖形實(shí)例:窗花圖案
JavaScript圖形實(shí)例:曲線方程
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服