/src/heatmap-gmaps.js

https://github.com/devinblais/heatmaps · JavaScript · 160 lines · 117 code · 30 blank · 13 comment · 3 complexity · e4fe1343f9a4c23de6d3cdc477cc01a1 MD5 · raw file

  1. /*
  2. * heatmap.js GMaps overlay
  3. *
  4. * Copyright (c) 2011, 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. function HeatmapOverlay(map, cfg){
  9. this.heatmap = null;
  10. this.conf = cfg;
  11. this.latlngs = [];
  12. this.bounds = null;
  13. this.setMap(map);
  14. var me = this;
  15. google.maps.event.addListener(map, 'idle', function() { me.draw() });
  16. }
  17. HeatmapOverlay.prototype = new google.maps.OverlayView();
  18. HeatmapOverlay.prototype.onAdd = function(){
  19. var panes = this.getPanes();
  20. var w = this.getMap().getDiv().clientWidth;
  21. var h = this.getMap().getDiv().clientHeight;
  22. var el = document.createElement("div");
  23. el.style.position = "absolute";
  24. el.style.top = 0;
  25. el.style.left = 0;
  26. el.style.width = w + "px";
  27. el.style.height = h + "px";
  28. el.style.border = 0;
  29. this.conf.element = el;
  30. panes.overlayLayer.appendChild(el);
  31. this.heatmap = h337.create(this.conf);
  32. }
  33. HeatmapOverlay.prototype.onRemove = function(){
  34. // Empty for now.
  35. }
  36. HeatmapOverlay.prototype.draw = function(){
  37. console.log("drawing");
  38. var overlayProjection = this.getProjection();
  39. var currentBounds = this.map.getBounds();
  40. if (currentBounds.equals(this.bounds)) {
  41. return;
  42. }
  43. this.bounds = currentBounds;
  44. var ne = overlayProjection.fromLatLngToDivPixel(currentBounds.getNorthEast());
  45. var sw = overlayProjection.fromLatLngToDivPixel(currentBounds.getSouthWest());
  46. var topY = ne.y;
  47. var leftX = sw.x;
  48. var h = sw.y - ne.y;
  49. var w = ne.x - sw.x;
  50. this.conf.element.style.left = leftX + 'px';
  51. this.conf.element.style.top = topY + 'px';
  52. this.conf.element.style.width = w + 'px';
  53. this.conf.element.style.height = h + 'px';
  54. this.heatmap.store.get("heatmap").resize();
  55. if(this.latlngs.length > 0){
  56. this.heatmap.clear();
  57. var len = this.latlngs.length,
  58. projection = this.getProjection();
  59. var c = 0;
  60. var d = {
  61. //max: this.heatmap.store.max,
  62. data: []
  63. };
  64. while(len--){
  65. var latlng = this.latlngs[len].latlng;
  66. if(!currentBounds.contains(latlng)) { continue; }
  67. c++;
  68. // DivPixel is pixel in overlay pixel coordinates... we need
  69. // to transform to screen coordinates so it'll match the canvas
  70. // which is continually repositioned to follow the screen.
  71. var divPixel = projection.fromLatLngToDivPixel(latlng);
  72. var screenPixel = new google.maps.Point(
  73. divPixel.x - leftX,
  74. divPixel.y - topY);
  75. var roundedPoint = this.pixelTransform(screenPixel);
  76. d.data.push({
  77. x: roundedPoint.x,
  78. y: roundedPoint.y,
  79. count: this.latlngs[len].c
  80. });
  81. }
  82. d.max = Math.log(c)/Math.log(10);
  83. console.log("adding " + d.data.length + " datapoints");
  84. console.log("d max is " + d.max);
  85. this.heatmap.store.setDataSet(d);
  86. }
  87. }
  88. HeatmapOverlay.prototype.pixelTransform = function(p){
  89. var w = this.heatmap.get("width"),
  90. h = this.heatmap.get("height");
  91. while(p.x < 0)
  92. p.x+=w;
  93. while(p.x > w)
  94. p.x-=w;
  95. while(p.y < 0)
  96. p.y+=h;
  97. while(p.y > h)
  98. p.y-=h;
  99. // fast rounding - thanks to Seb Lee-Delisle for this neat hack
  100. p.x = ~~ (p.x+0.5);
  101. p.y = ~~ (p.y+0.5);
  102. return p;
  103. }
  104. HeatmapOverlay.prototype.setDataSet = function(data){
  105. var mapdata = {
  106. max: data.max,
  107. data: []
  108. };
  109. var d = data.data;
  110. var dlen = d.length;
  111. var projection = this.getProjection();
  112. while(dlen--){
  113. var latlng = new google.maps.LatLng(d[dlen].lat, d[dlen].lng);
  114. this.latlngs.push({latlng: latlng, c: d[dlen].count});
  115. var point = this.pixelTransform(projection.fromLatLngToDivPixel(latlng));
  116. mapdata.data.push({x: point.x, y: point.y, count: d[dlen].count});
  117. }
  118. this.heatmap.clear();
  119. this.heatmap.store.setDataSet(mapdata);
  120. }
  121. HeatmapOverlay.prototype.addDataPoint = function(lat, lng, count){
  122. var projection = this.getProjection(),
  123. latlng = new google.maps.LatLng(lat, lng),
  124. point = this.pixelTransform(projection.fromLatLngToDivPixel(latlng));
  125. this.heatmap.store.addDataPoint(point.x, point.y, count);
  126. this.latlngs.push({ latlng: latlng, c: count });
  127. }
  128. HeatmapOverlay.prototype.toggle = function(){
  129. this.heatmap.toggleDisplay();
  130. }