Project

General

Profile

Download (6.28 KB) Statistics
| Branch: | Revision:

git_sitools_idoc / webstatDev / idoc_Maison / static / heatmap / gmaps-heatmap.js @ 8792cad8

1
/*
2
* heatmap.js gmaps overlay
3
*
4
* Copyright (c) 2014, Patrick Wied (http://www.patrick-wied.at)
5
* Dual-licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
6
* and the Beerware (http://en.wikipedia.org/wiki/Beerware) license.
7
*/
8

    
9
function HeatmapOverlay(map, cfg){ 
10
  this.setMap(map);
11
  this.initialize(cfg || {});
12
};
13

    
14
HeatmapOverlay.prototype = new google.maps.OverlayView();
15

    
16

    
17
HeatmapOverlay.CSS_TRANSFORM = (function() {
18
  var div = document.createElement('div');
19
  var props = [
20
    'transform',
21
    'WebkitTransform',
22
    'MozTransform',
23
    'OTransform',
24
    'msTransform'
25
  ];
26

    
27
  for (var i = 0; i < props.length; i++) {
28
    var prop = props[i];
29
    if (div.style[prop] !== undefined) {
30
      return prop;
31
    }
32
  }
33

    
34
  return props[0];
35
})();
36

    
37
HeatmapOverlay.prototype.initialize = function(cfg) {
38
  this.cfg = cfg;
39
  
40
  var map = this.map = this.getMap();
41
  var container = this.container = document.createElement('div');
42
  var mapDiv = map.getDiv();
43
  var width = this.width = mapDiv.clientWidth;
44
  var height = this.height = mapDiv.clientHeight;
45

    
46
  container.style.cssText = 'width:' + width +'px;height:' + height+'px;';
47

    
48
  this.data = [];
49
  this.max = 1;
50
  this.min = 0;
51

    
52
  cfg.container = container;
53
};
54

    
55
HeatmapOverlay.prototype.onAdd = function(){
56

    
57
  this.getPanes().overlayLayer.appendChild(this.container);
58

    
59
  this.changeHandler = google.maps.event.addListener(
60
    this.map,
61
    'bounds_changed',
62
    this.draw
63
  );
64
 
65
  if (!this.heatmap) {
66
    this.heatmap = h337.create(this.cfg);
67
  }
68
  this.draw();
69
};
70

    
71
HeatmapOverlay.prototype.onRemove = function() { 
72
  if (!this.map) { return; }
73

    
74
  this.map = null;
75

    
76
  this.container.parentElement.removeChild(this.container);
77

    
78
  if (this.changeHandler) {
79
    google.maps.event.removeListener(this.changeHandler);
80
    this.changeHandler = null;
81
  }
82

    
83
};
84

    
85
HeatmapOverlay.prototype.draw = function() {
86
  if (!this.map) { return; }
87

    
88
  var bounds = this.map.getBounds();
89

    
90
  var topLeft = new google.maps.LatLng(
91
    bounds.getNorthEast().lat(),
92
    bounds.getSouthWest().lng()
93
  );
94

    
95
  var projection = this.getProjection();
96
  var point = projection.fromLatLngToDivPixel(topLeft);
97

    
98
  this.container.style[HeatmapOverlay.CSS_TRANSFORM] = 'translate(' +
99
      Math.round(point.x) + 'px,' +
100
      Math.round(point.y) + 'px)';
101

    
102
  this.update();
103
};
104

    
105
HeatmapOverlay.prototype.resize = function() {
106

    
107
  if (!this.map){ return; }
108

    
109
  var div = this.map.getDiv(),
110
    width = div.clientWidth,
111
    height = div.clientHeight;
112

    
113
  if (width == this.width && height == this.height){ return; }
114

    
115
  this.width = width;
116
  this.height = height;
117

    
118
  // update heatmap dimensions
119
  this.heatmap._renderer.setDimensions(width, height);
120
  // then redraw all datapoints with update
121
  this.update();
122
};
123

    
124
HeatmapOverlay.prototype.update = function() {
125
  var projection = this.map.getProjection(),
126
    zoom, scale, bounds, topLeft;
127

    
128
  if (!projection){ return; }
129

    
130
  bounds = this.map.getBounds();
131

    
132
  topLeft = new google.maps.LatLng(
133
    bounds.getNorthEast().lat(),
134
    bounds.getSouthWest().lng()
135
  );
136

    
137
  zoom = this.map.getZoom();
138
  scale = Math.pow(2, zoom);
139

    
140
  this.resize();
141

    
142
  if (this.data.length == 0) {
143
    return;
144
  }
145

    
146
  var generatedData = { max: this.max, min: this.min };
147
  var latLngPoints = [];
148
  // iterate through data 
149
  var len = this.data.length;
150
  var layerProjection = this.getProjection();
151
  var layerOffset = layerProjection.fromLatLngToDivPixel(topLeft);
152
  var radiusMultiplier = this.cfg.scaleRadius ? scale : 1;
153
  var localMax = 0;
154
  var localMin = 0;
155
  var valueField = this.cfg.valueField;
156

    
157

    
158
  while (len--) {
159
    var entry = this.data[len];
160
    var value = entry[valueField];
161
    var latlng = entry.latlng;
162

    
163

    
164
    // we don't wanna render points that are not even on the map ;-)
165
    if (!bounds.contains(latlng)) {
166
      continue;
167
    }
168
    // local max is the maximum within current bounds
169
    localMax = Math.max(value, localMax);
170
    localMin = Math.min(value, localMin);
171

    
172
    var point = this.pixelTransform(layerProjection.fromLatLngToDivPixel(latlng));
173
    var latlngPoint = { x: Math.round(point.x - layerOffset.x), y: Math.round(point.y - layerOffset.y) };
174
    latlngPoint[valueField] = value;
175

    
176
    var radius;
177

    
178
    if (entry.radius) {
179
      radius = entry.radius * radiusMultiplier;
180
    } else {
181
      radius = (this.cfg.radius || 2) * radiusMultiplier;
182
    }
183
    latlngPoint.radius = radius;
184
    latLngPoints.push(latlngPoint);
185
  }
186
  if (this.cfg.useLocalExtrema) {
187
    generatedData.max = localMax;
188
    generatedData.min = localMin;
189
  }
190

    
191
  generatedData.data = latLngPoints;
192

    
193
  this.heatmap.setData(generatedData);
194

    
195
};
196

    
197
HeatmapOverlay.prototype.pixelTransform = function(point) {
198
  if (point.x < 0) {
199
    point.x += this.width;
200
  }
201
  if (point.x > this.width) {
202
    point.x -= this.width;
203
  }
204
  if (point.y < 0) {
205
    point.y += this.height;
206
  }
207
  if (point.y > this.height) {
208
    point.y -= this.height;
209
  }
210
  return point;
211
};
212

    
213
HeatmapOverlay.prototype.setData = function(data) { 
214
  this.max = data.max;
215
  this.min = data.min;
216

    
217
  var latField = this.cfg.latField || 'lat';
218
  var lngField = this.cfg.lngField || 'lng';
219
  var valueField = this.cfg.valueField || 'value';
220

    
221
  // transform data to latlngs
222
  var data = data.data;
223
  var len = data.length;
224
  var d = [];
225

    
226
  while (len--) {
227
    var entry = data[len];
228
    var latlng = new google.maps.LatLng(entry[latField], entry[lngField]);
229
    var dataObj = { latlng: latlng };
230
    dataObj[valueField] = entry[valueField];
231
    if (entry.radius) {
232
      dataObj.radius = entry.radius;
233
    }
234
    d.push(dataObj);
235
  }
236
  this.data = d;
237
  this.update();
238
};
239
// experimential. not ready yet.
240
HeatmapOverlay.prototype.addData = function(pointOrArray) {
241
  if (pointOrArray.length > 0) {
242
      var len = pointOrArray.length;
243
      while(len--) {
244
        this.addData(pointOrArray[len]);
245
      }
246
    } else {
247
      var latField = this.cfg.latField || 'lat';
248
      var lngField = this.cfg.lngField || 'lng';
249
      var valueField = this.cfg.valueField || 'value';
250
      var entry = pointOrArray;
251
      var latlng = new google.maps.LatLng(entry[latField], entry[lngField]);
252
      var dataObj = { latlng: latlng };
253
      
254
      dataObj[valueField] = entry[valueField];
255
      if (entry.radius) {
256
        dataObj.radius = entry.radius;
257
      }
258
      this.max = Math.max(this.max, dataObj[valueField]);
259
      this.min = Math.min(this.min, dataObj[valueField]);
260
      this.data.push(dataObj);
261
      this.update();
262
    }
263
};
264