heatmap-openlayers.js
4.63 KB
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
* heatmap.js OpenLayers Heatmap Class
*
* Copyright (c) 2011, Patrick Wied (http://www.patrick-wied.at)
* Dual-licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and the Beerware (http://en.wikipedia.org/wiki/Beerware) license.
*
* Modified on Jun,06 2011 by Antonio Santiago (http://www.acuriousanimal.com)
* - Heatmaps as independent map layer.
* - Points based on OpenLayers.LonLat.
* - Data initialization in constructor.
* - Improved 'addDataPoint' to add new lonlat based points.
*/
OpenLayers.Layer.Heatmap = OpenLayers.Class(OpenLayers.Layer, {
// the heatmap isn't a basic layer by default - you usually want to display the heatmap over another map ;)
isBaseLayer: false,
heatmap: null,
mapLayer: null,
// we store the lon lat data, because we have to redraw with new positions on zoomend|moveend
tmpData: {},
initialize: function(name, map, mLayer, hmoptions, options){
var heatdiv = document.createElement("div"),
handler;
OpenLayers.Layer.prototype.initialize.apply(this, [name, options]);
heatdiv.style.cssText = "position:absolute;width:"+map.size.w+"px;height:"+map.size.h+"px;";
// this will be the heatmaps element
this.div.appendChild(heatdiv);
// add to our heatmap.js config
hmoptions.element = heatdiv;
this.mapLayer = mLayer;
//this.map = map;
// create the heatmap with passed heatmap-options
this.heatmap = h337.create(hmoptions);
handler = function(){
if(this.map && this.tmpData.max){
this.updateLayer();
}
};
handler1 = function(){
if(this.tmpData && this.tmpData.max){
this.toggle();
this.updateLayer();
}
};
// on zoomend and moveend we have to move the canvas element and redraw the datapoints with new positions
//map.events.register("zoomend", this, handler);
map.events.register("moveend", this, handler);
//this.events.register("visibilitychanged", this,handler1);
map.events.register(
"removed",
this,
function(){
if(this.tmpData.max){
this.destroy();
}
});
},
updateLayer: function(){
var pixelOffset = this.getPixelOffset(),
el = this.heatmap.get('element');
// if the pixeloffset e.g. for x was positive move the canvas element to the left by setting left:-offset.y px
// otherwise move it the right by setting it a positive value. same for top
el.style.top = ((pixelOffset.y > 0)?('-'+pixelOffset.y):(Math.abs(pixelOffset.y)))+'px';
el.style.left = ((pixelOffset.x > 0)?('-'+pixelOffset.x):(Math.abs(pixelOffset.x)))+'px';
//var p = el.parentNode.style;
//console.warn(p.display)
if(this.visibility === true){
this.setDataSet(this.tmpData);
}
},
getPixelOffset: function () {
var o = this.mapLayer.map.layerContainerOrigin,
o_lonlat = new OpenLayers.LonLat(o.lon, o.lat),
o_pixel = this.mapLayer.getViewPortPxFromLonLat(o_lonlat),
c = this.mapLayer.map.center,
c_lonlat = new OpenLayers.LonLat(c.lon, c.lat),
c_pixel = this.mapLayer.getViewPortPxFromLonLat(c_lonlat);
return {
x: o_pixel.x - c_pixel.x,
y: o_pixel.y - c_pixel.y
};
},
setDataSet: function(obj){
var set = {},
dataset = obj.data,
dlen = dataset.length,
entry, lonlat, pixel, proj, tproj, vp;
set.max = obj.max;
set.data = [];
// get the pixels for all the lonlat entries
proj = this.map.getProjectionObject();
tproj = this.projection;
while(dlen--){
entry = dataset[dlen];
try{
lonlat = entry.lonlat.clone().transform(tproj, proj);
if(lonlat){
vp = this.getViewPortPxFromLonLat(lonlat);
pixel = this.roundPixels(vp);
if(pixel){
set.data.push({x: pixel.x, y: pixel.y, count: entry.count});
}
}
}
catch(e){}
}
this.tmpData = obj;
this.heatmap.store.setDataSet(set);
},
// we don't want to have decimal numbers such as xxx.9813212 since they slow canvas performance down + don't look nice
roundPixels: function(p){
if(p.x < 0 || p.y < 0){
return false;
}
p.x = (p.x >> 0);
p.y = (p.y >> 0);
return p;
},
// same procedure as setDataSet
addDataPoint: function(lonlat){
var pixel = this.roundPixels(this.mapLayer.getViewPortPxFromLonLat(lonlat)),
entry = {lonlat: lonlat},
args;
if(arguments.length == 2){
entry.count = arguments[1];
}
this.tmpData.data.push(entry);
if(pixel){
args = [pixel.x, pixel.y];
if(arguments.length == 2){
args.push(arguments[1]);
}
this.heatmap.store.addDataPoint.apply(this.heatmap.store, args);
}
},
toggle: function(){
this.heatmap.toggleDisplay();
},
destroy: function() {
// for now, nothing special to do here.
//OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
//this.tmpData = false;
},
CLASS_NAME: "OpenLayers.Layer.Heatmap"
});