[JS]Canvasを使って、リアルタイムにヒートマップを描くスクリプト -real time heatmap
Post on:2010年10月26日
sponsorsr
ユーザーのマウスの動きに伴い、リアルタイムにヒートマップを生成するスクリプトを紹介します。

[ad#ad-2]
デモの画像の上でマウスを動かすと、その動いた量に伴いカラーがブルー、グリーン、イエロー、レッドとマウスの移動し滞在した量をヒートマップとして生成します。ヒートマップのデータはエクスポートも可能です。
また、iPhoneのシングルタップもサポートしている、とのことです。
スクリプトはjQueryなどの他のスクリプトは依存せず、下記のようになります。
JavaScirpt
/*
Copyright (c) 2010, Patrick Wied. All rights reserved.
Code licensed under the BSD License:
http://patrick-wied.at/static/license.txt
*/
var heatmapApp = (function(){
// var definition
// canvas: the canvas element
// ctx: the canvas 2d context
// width: the heatmap width for border calculations
// height: the heatmap height for border calculations
// invoke: the app doesn't react on the mouse events unless the invoke var is set to true
var canvas,
ctx,
width,
height,
radius1 = 20,
radius2 = 40,
invoke = false,
// function for coloring the heatmap
colorize = function(x,y,x2){
// initial check if x and y is outside the app
// -> resetting values
if(x+x2>width)
x=width-x2;
if(x<0)
x=0;
if(y<0)
y=0;
if(y+x2>height)
y=height-x2;
// get the image data for the mouse movement area
var image = ctx.getImageData(x,y,x2,x2),
// some performance tweaks
imageData = image.data,
length = imageData.length;
// loop thru the area
for(var i=3; i < length; i+=4){
var r = 0,
g = 0,
b = 0,
tmp = 0,
// [0] -> r, [1] -> g, [2] -> b, [3] -> alpha
alpha = imageData[i];
// coloring depending on the current alpha value
if(alpha<=255 && alpha >= 235){
tmp=255-alpha;
r=255-tmp;
g=tmp*12;
}else if(alpha<=234 && alpha >= 200){
tmp=234-alpha;
r=255-(tmp*8);
g=255;
}else if(alpha<= 199 && alpha >= 150){
tmp=199-alpha;
g=255;
b=tmp*5;
}else if(alpha<= 149 && alpha >= 100){
tmp=149-alpha;
g=255-(tmp*5);
b=255;
}else
b=255;
// we ve started with i=3
// set the new r, g and b values
imageData[i-3]=r;
imageData[i-2]=g;
imageData[i-1]=b;
}
// the rgb data manipulation didn't affect the ImageData object(defined on the top)
// after the manipulation process we have to set the manipulated data to the ImageData object
image.data = imageData;
ctx.putImageData(image,x,y);
},
// this handler is listening to the mouse movement of the user
mouseMoveHandler = function(ev){
// if the invoke variable is set to true -> do the alphamap manipulation
if(invoke){
// at first we have to get the x and y values of the user's mouse position
var x, y;
if (ev.layerX) { // Firefox
x = ev.layerX;
y = ev.layerY;
} else if (ev.offsetX) { // Opera
x = ev.offsetX;
y = ev.offsetY;
}
if(typeof(x)=='undefined')
return;
// storing the variables because they will be often used
var r1 = radius1;
var r2 = radius2;
//console.log("x: "+x+"; y:" +y);
// create a radial gradient with the defined parameters. we want to draw an alphamap
var rgr = ctx.createRadialGradient(x,y,r1,x,y,r2);
// the center of the radial gradient has .1 alpha value
rgr.addColorStop(0, 'rgba(0,0,0,0.1)');
// and it fades out to 0
rgr.addColorStop(1, 'rgba(0,0,0,0)');
// drawing the gradient
ctx.fillStyle = rgr;
ctx.fillRect(x-r2,y-r2,2*r2,2*r2);
// negate the invoke variable
// next execution of the logic is when the activate method activates the invoke var again
invoke=!invoke;
// at least colorize the area
colorize(x-r2,y-r2,2*r2);
}
},
// we don't want to capture all events because this would result in low performance
// -> a function for activating the heatmap logic which will be called in a specified interval
activate = function(){
invoke = !invoke;
};
return {
// initialization
initialize: function(c, wt, ht){
canvas = document.getElementById(c);
canvas.width = wt;
canvas.height = ht;
canvas.style.border = "2px solid black";
ctx = canvas.getContext("2d");
width = wt;
height = ht;
canvas["onmousemove"] = function(ev){ mouseMoveHandler(ev); };
// iPhone / iPad support
canvas["ontouchmove"] = function(ev){
var touch = ev.touches[0],
// simulating a mousemove event
simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent("mousemove", true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);
// dispatching the simulated event
touch.target.dispatchEvent(simulatedEvent);
// we don't want to have the default iphone scrolling behaviour ontouchmove
ev.preventDefault();
};
// call the activate function in an interval of 50ms
(function(fn){
setInterval(fn, 50);
})(activate);
},
// if you like to process the image data e.g onbeforeunload
// just call the getData method -> returns imagedata as a dataurl string
getData: function(){
return canvas.toDataURL();
}
};
})();
window["onload"]=function(){
//call the initialization
heatmapApp.initialize("c",300,900);
}
ライセンスはBSD Licenseとのことです。
sponsors











