805 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			805 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /* | ||
|  |  *  CesiumHeatmap.js v0.1 | Cesium Heatmap Library | ||
|  |  *   | ||
|  |  *  Works with heatmap.js v2.0.0: http://www.patrick-wied.at/static/heatmapjs/
 | ||
|  |  */ | ||
|  | (function (window) { | ||
|  |   'use strict'; | ||
|  |   function define_CesiumHeatmap() { | ||
|  |     var CesiumHeatmap = { | ||
|  |       defaults: { | ||
|  |         useEntitiesIfAvailable: true, //whether to use entities if a Viewer is supplied or always use an ImageryProvider
 | ||
|  |         minCanvasSize: 700,           // minimum size (in pixels) for the heatmap canvas
 | ||
|  |         maxCanvasSize: 2000,          // maximum size (in pixels) for the heatmap canvas
 | ||
|  |         radiusFactor: 60,             // data point size factor used if no radius is given (the greater of height and width divided by this number yields the used radius)
 | ||
|  |         spacingFactor: 1.5,           // extra space around the borders (point radius multiplied by this number yields the spacing)
 | ||
|  |         maxOpacity: 0.8,              // the maximum opacity used if not given in the heatmap options object
 | ||
|  |         minOpacity: 0.1,              // the minimum opacity used if not given in the heatmap options object
 | ||
|  |         blur: 0.85,                   // the blur used if not given in the heatmap options object
 | ||
|  |         gradient: {                   // the gradient used if not given in the heatmap options object
 | ||
|  |           '.3': 'blue', | ||
|  |           '.65': 'yellow', | ||
|  |           '.8': 'orange', | ||
|  |           '.95': 'red' | ||
|  |         }, | ||
|  |       } | ||
|  |     }; | ||
|  | 
 | ||
|  |     /*  Create a CesiumHeatmap instance | ||
|  |      * | ||
|  |      *  cesium:  the CesiumWidget or Viewer instance | ||
|  |      *  bb:      the WGS84 bounding box like {north, east, south, west} | ||
|  |      *  options: a heatmap.js options object (see http://www.patrick-wied.at/static/heatmapjs/docs.html#h337-create)
 | ||
|  |      */ | ||
|  |     CesiumHeatmap.create = function (bb, options) { | ||
|  |       var instance = new CHInstance(bb, options); | ||
|  |       return instance; | ||
|  |     }; | ||
|  | 
 | ||
|  |     CesiumHeatmap._getContainer = function (width, height, id) { | ||
|  |       var c = document.createElement("div"); | ||
|  |       if (id) { | ||
|  |         c.setAttribute("id", id); | ||
|  |       } | ||
|  |       c.setAttribute("style", "width: " + width + "px; height: " + height + "px; margin: 0px; display: none;"); | ||
|  |       document.body.appendChild(c); | ||
|  |       setTimeout(() => { | ||
|  |         document.body.removeChild(c) | ||
|  |       }, 500); | ||
|  |       return c; | ||
|  |     }; | ||
|  | 
 | ||
|  |     CesiumHeatmap._getImageryProvider = function (instance) { | ||
|  |       //var n = (new Date()).getTime();
 | ||
|  |       var d = instance._heatmap.getDataURL(); | ||
|  |       //console.log("Create data URL: " + ((new Date()).getTime() - n));
 | ||
|  | 
 | ||
|  |       //var n = (new Date()).getTime();
 | ||
|  |       var imgprov = new Cesium.SingleTileImageryProvider({ | ||
|  |         url: d, | ||
|  |         rectangle: instance._rectangle | ||
|  |       }); | ||
|  |       //console.log("Create imageryprovider: " + ((new Date()).getTime() - n));
 | ||
|  | 
 | ||
|  |       imgprov._tilingScheme = new Cesium.WebMercatorTilingScheme({ | ||
|  |         rectangleSouthwestInMeters: new Cesium.Cartesian2(instance._mbounds.west, instance._mbounds.south), | ||
|  |         rectangleNortheastInMeters: new Cesium.Cartesian2(instance._mbounds.east, instance._mbounds.north) | ||
|  |       }); | ||
|  | 
 | ||
|  |       return imgprov; | ||
|  |     }; | ||
|  | 
 | ||
|  |     CesiumHeatmap._getID = function (len) { | ||
|  |       var text = ""; | ||
|  |       var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||
|  | 
 | ||
|  |       for (var i = 0; i < ((len) ? len : 8); i++) | ||
|  |         text += possible.charAt(Math.floor(Math.random() * possible.length)); | ||
|  | 
 | ||
|  |       return text; | ||
|  |     }; | ||
|  | 
 | ||
|  |     var WMP = new Cesium.WebMercatorProjection(); | ||
|  | 
 | ||
|  |     /*  Convert a WGS84 location into a mercator location | ||
|  |      * | ||
|  |      *  p: the WGS84 location like {x: lon, y: lat} | ||
|  |      */ | ||
|  |     CesiumHeatmap.wgs84ToMercator = function (p) { | ||
|  |       var mp = WMP.project(Cesium.Cartographic.fromDegrees(p.x, p.y)); | ||
|  |       return { | ||
|  |         x: mp.x, | ||
|  |         y: mp.y | ||
|  |       }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /*  Convert a WGS84 bounding box into a mercator bounding box | ||
|  |      * | ||
|  |      *  bb: the WGS84 bounding box like {north, east, south, west} | ||
|  |      */ | ||
|  |     CesiumHeatmap.wgs84ToMercatorBB = function (bb) { | ||
|  |       var sw = WMP.project(Cesium.Cartographic.fromDegrees(bb.west, bb.south)); | ||
|  |       var ne = WMP.project(Cesium.Cartographic.fromDegrees(bb.east, bb.north)); | ||
|  |       return { | ||
|  |         north: ne.y, | ||
|  |         east: ne.x, | ||
|  |         south: sw.y, | ||
|  |         west: sw.x | ||
|  |       }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /*  Convert a mercator location into a WGS84 location | ||
|  |      * | ||
|  |      *  p: the mercator lcation like {x, y} | ||
|  |      */ | ||
|  |     CesiumHeatmap.mercatorToWgs84 = function (p) { | ||
|  |       var wp = WMP.unproject(new Cesium.Cartesian3(p.x, p.y)); | ||
|  |       return { | ||
|  |         x: wp.longitude, | ||
|  |         y: wp.latitude | ||
|  |       }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /*  Convert a mercator bounding box into a WGS84 bounding box | ||
|  |      * | ||
|  |      *  bb: the mercator bounding box like {north, east, south, west} | ||
|  |      */ | ||
|  |     CesiumHeatmap.mercatorToWgs84BB = function (bb) { | ||
|  |       var sw = WMP.unproject(new Cesium.Cartesian3(bb.west, bb.south)); | ||
|  |       var ne = WMP.unproject(new Cesium.Cartesian3(bb.east, bb.north)); | ||
|  |       return { | ||
|  |         north: this.rad2deg(ne.latitude), | ||
|  |         east: this.rad2deg(ne.longitude), | ||
|  |         south: this.rad2deg(sw.latitude), | ||
|  |         west: this.rad2deg(sw.longitude) | ||
|  |       }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /*  Convert degrees into radians | ||
|  |      * | ||
|  |      *  d: the degrees to be converted to radians | ||
|  |      */ | ||
|  |     CesiumHeatmap.deg2rad = function (d) { | ||
|  |       var r = d * (Math.PI / 180.0); | ||
|  |       return r; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /*  Convert radians into degrees | ||
|  |      * | ||
|  |      *  r: the radians to be converted to degrees | ||
|  |      */ | ||
|  |     CesiumHeatmap.rad2deg = function (r) { | ||
|  |       var d = r / (Math.PI / 180.0); | ||
|  |       return d; | ||
|  |     }; | ||
|  | 
 | ||
|  |     return CesiumHeatmap; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (typeof (CesiumHeatmap) === 'undefined') { | ||
|  |     window.CesiumHeatmap = define_CesiumHeatmap(); | ||
|  |   } else { | ||
|  |     console.log("CesiumHeatmap already defined."); | ||
|  |   } | ||
|  | })(window); | ||
|  | 
 | ||
|  | /*  Initiate a CesiumHeatmap instance | ||
|  |  * | ||
|  |  *  c:  CesiumWidget instance | ||
|  |  *  bb: a WGS84 bounding box like {north, east, south, west} | ||
|  |  *  o:  a heatmap.js options object (see http://www.patrick-wied.at/static/heatmapjs/docs.html#h337-create)
 | ||
|  |  */ | ||
|  | function CHInstance(bb, o) { | ||
|  |   if (!bb) { | ||
|  |     return null; | ||
|  |   } | ||
|  |   if (!o) { | ||
|  |     o = {}; | ||
|  |   } | ||
|  | 
 | ||
|  |   this._options = o; | ||
|  |   this._id = CesiumHeatmap._getID(); | ||
|  | 
 | ||
|  |   this._options.gradient = ((this._options.gradient) ? this._options.gradient : CesiumHeatmap.defaults.gradient); | ||
|  |   this._options.maxOpacity = ((this._options.maxOpacity) ? this._options.maxOpacity : CesiumHeatmap.defaults.maxOpacity); | ||
|  |   this._options.minOpacity = ((this._options.minOpacity) ? this._options.minOpacity : CesiumHeatmap.defaults.minOpacity); | ||
|  |   this._options.blur = ((this._options.blur) ? this._options.blur : CesiumHeatmap.defaults.blur); | ||
|  | 
 | ||
|  |   this._mbounds = CesiumHeatmap.wgs84ToMercatorBB(bb); | ||
|  |   this._setWidthAndHeight(this._mbounds); | ||
|  | 
 | ||
|  |   this._options.radius = Math.round((this._options.radius) ? this._options.radius : ((this.width > this.height) ? this.width / CesiumHeatmap.defaults.radiusFactor : this.height / CesiumHeatmap.defaults.radiusFactor)); | ||
|  | 
 | ||
|  |   this._spacing = this._options.radius * CesiumHeatmap.defaults.spacingFactor; | ||
|  |   this._xoffset = this._mbounds.west; | ||
|  |   this._yoffset = this._mbounds.south; | ||
|  | 
 | ||
|  |   this.width = Math.round(this.width + this._spacing * 2); | ||
|  |   this.height = Math.round(this.height + this._spacing * 2); | ||
|  | 
 | ||
|  |   this._mbounds.west -= this._spacing * this._factor; | ||
|  |   this._mbounds.east += this._spacing * this._factor; | ||
|  |   this._mbounds.south -= this._spacing * this._factor; | ||
|  |   this._mbounds.north += this._spacing * this._factor; | ||
|  | 
 | ||
|  |   this.bounds = CesiumHeatmap.mercatorToWgs84BB(this._mbounds); | ||
|  | 
 | ||
|  |   this._rectangle = Cesium.Rectangle.fromDegrees(this.bounds.west, this.bounds.south, this.bounds.east, this.bounds.north); | ||
|  |   this._container = CesiumHeatmap._getContainer(this.width, this.height, this._id); | ||
|  |   this._options.container = this._container; | ||
|  |   this._heatmap = h337.create(this._options); | ||
|  |   this._container.children[0].setAttribute("id", this._id + "-hm"); | ||
|  | } | ||
|  | 
 | ||
|  | /*  Convert a WGS84 location to the corresponding heatmap location | ||
|  |  * | ||
|  |  *  p: a WGS84 location like {x:lon, y:lat} | ||
|  |  */ | ||
|  | CHInstance.prototype.wgs84PointToHeatmapPoint = function (p) { | ||
|  |   return this.mercatorPointToHeatmapPoint(CesiumHeatmap.wgs84ToMercator(p)); | ||
|  | }; | ||
|  | 
 | ||
|  | /*  Convert a mercator location to the corresponding heatmap location | ||
|  |  * | ||
|  |  *  p: a WGS84 location like {x: lon, y:lat} | ||
|  |  */ | ||
|  | CHInstance.prototype.mercatorPointToHeatmapPoint = function (p) { | ||
|  |   var pn = {}; | ||
|  | 
 | ||
|  |   pn.x = Math.round((p.x - this._xoffset) / this._factor + this._spacing); | ||
|  |   pn.y = Math.round((p.y - this._yoffset) / this._factor + this._spacing); | ||
|  |   pn.y = this.height - pn.y; | ||
|  | 
 | ||
|  |   return pn; | ||
|  | }; | ||
|  | 
 | ||
|  | CHInstance.prototype._setWidthAndHeight = function (mbb) { | ||
|  |   this.width = ((mbb.east > 0 && mbb.west < 0) ? mbb.east + Math.abs(mbb.west) : Math.abs(mbb.east - mbb.west)); | ||
|  |   this.height = ((mbb.north > 0 && mbb.south < 0) ? mbb.north + Math.abs(mbb.south) : Math.abs(mbb.north - mbb.south)); | ||
|  |   this._factor = 1; | ||
|  | 
 | ||
|  |   if (this.width > this.height && this.width > CesiumHeatmap.defaults.maxCanvasSize) { | ||
|  |     this._factor = this.width / CesiumHeatmap.defaults.maxCanvasSize; | ||
|  | 
 | ||
|  |     if (this.height / this._factor < CesiumHeatmap.defaults.minCanvasSize) { | ||
|  |       this._factor = this.height / CesiumHeatmap.defaults.minCanvasSize; | ||
|  |     } | ||
|  |   } else if (this.height > this.width && this.height > CesiumHeatmap.defaults.maxCanvasSize) { | ||
|  |     this._factor = this.height / CesiumHeatmap.defaults.maxCanvasSize; | ||
|  | 
 | ||
|  |     if (this.width / this._factor < CesiumHeatmap.defaults.minCanvasSize) { | ||
|  |       this._factor = this.width / CesiumHeatmap.defaults.minCanvasSize; | ||
|  |     } | ||
|  |   } else if (this.width < this.height && this.width < CesiumHeatmap.defaults.minCanvasSize) { | ||
|  |     this._factor = this.width / CesiumHeatmap.defaults.minCanvasSize; | ||
|  | 
 | ||
|  |     if (this.height / this._factor > CesiumHeatmap.defaults.maxCanvasSize) { | ||
|  |       this._factor = this.height / CesiumHeatmap.defaults.maxCanvasSize; | ||
|  |     } | ||
|  |   } else if (this.height < this.width && this.height < CesiumHeatmap.defaults.minCanvasSize) { | ||
|  |     this._factor = this.height / CesiumHeatmap.defaults.minCanvasSize; | ||
|  | 
 | ||
|  |     if (this.width / this._factor > CesiumHeatmap.defaults.maxCanvasSize) { | ||
|  |       this._factor = this.width / CesiumHeatmap.defaults.maxCanvasSize; | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   this.width = this.width / this._factor; | ||
|  |   this.height = this.height / this._factor; | ||
|  | }; | ||
|  | 
 | ||
|  | /*  Set an array of heatmap locations | ||
|  |  * | ||
|  |  *  min:  the minimum allowed value for the data values | ||
|  |  *  max:  the maximum allowed value for the data values | ||
|  |  *  data: an array of data points in heatmap coordinates and values like {x, y, value} | ||
|  |  */ | ||
|  | CHInstance.prototype.setData = function (min, max, data) { | ||
|  | 
 | ||
|  |   if (data && data.length > 0 && min !== null && min !== false && max !== null && max !== false) { | ||
|  |     this._heatmap.setData({ | ||
|  |       min: min, | ||
|  |       max: max, | ||
|  |       data: data | ||
|  |     }); | ||
|  |     return true; | ||
|  |   } | ||
|  | 
 | ||
|  |   return false; | ||
|  | }; | ||
|  | /*  Set an array of WGS84 locations | ||
|  |  * | ||
|  |  *  min:  the minimum allowed value for the data values | ||
|  |  *  max:  the maximum allowed value for the data values | ||
|  |  *  data: an array of data points in WGS84 coordinates and values like { x:lon, y:lat, value } | ||
|  |  */ | ||
|  | CHInstance.prototype.setWGS84Data = function (min, max, data) { | ||
|  | 
 | ||
|  |   if (data && data.length > 0 && min !== null && min !== false && max !== null && max !== false) { | ||
|  |     var convdata = []; | ||
|  | 
 | ||
|  |     for (var i = 0; i < data.length; i++) { | ||
|  |       var gp = data[i]; | ||
|  |       var hp = this.wgs84PointToHeatmapPoint(gp); | ||
|  |       if (gp.value || gp.value === 0) { | ||
|  |         hp.value = gp.value; | ||
|  |       } | ||
|  |       convdata.push(hp); | ||
|  |     } | ||
|  |     return this.setData(min, max, convdata); | ||
|  |   } | ||
|  | 
 | ||
|  |   return false; | ||
|  | }; | ||
|  | 
 | ||
|  | /*  Set whether or not the heatmap is shown on the map | ||
|  |  * | ||
|  |  *  s: true means the heatmap is shown, false means the heatmap is hidden | ||
|  |  */ | ||
|  | CHInstance.prototype.show = function (s) { | ||
|  |   if (this._layer) { | ||
|  |     this._layer.show = s; | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /*  DON'T TOUCH: | ||
|  |  * | ||
|  |  *  heatmap.js v2.0.0 | JavaScript Heatmap Library: http://www.patrick-wied.at/static/heatmapjs/
 | ||
|  |  * | ||
|  |  *  Copyright 2008-2014 Patrick Wied <heatmapjs@patrick-wied.at> - All rights reserved. | ||
|  |  *  Dual licensed under MIT and Beerware license | ||
|  |  * | ||
|  |  *  :: 2014-10-31 21:16 | ||
|  |  */ | ||
|  | (function (a, b, c) { | ||
|  |   if (typeof module !== "undefined" && module.exports) { | ||
|  |     module.exports = c() | ||
|  |   } else if (typeof define === "function" && define.amd) { | ||
|  |     define(c) | ||
|  |   } else { | ||
|  |     b[a] = c() | ||
|  |   } | ||
|  | })("h337", this, function () { | ||
|  |   var a = { | ||
|  |     defaultRadius: 40, | ||
|  |     defaultRenderer: "canvas2d", | ||
|  |     defaultGradient: { .25: "rgb(0,0,255)", .55: "rgb(0,255,0)", .85: "yellow", 1: "rgb(255,0,0)" }, | ||
|  |     defaultMaxOpacity: 1, | ||
|  |     defaultMinOpacity: 0, | ||
|  |     defaultBlur: .85, | ||
|  |     defaultXField: "x", | ||
|  |     defaultYField: "y", | ||
|  |     defaultValueField: "value", | ||
|  |     plugins: {} | ||
|  |   }; | ||
|  |   var b = function h() { | ||
|  |     var b = function d(a) { | ||
|  |       this._coordinator = {}; | ||
|  |       this._data = []; | ||
|  |       this._radi = []; | ||
|  |       this._min = 0; | ||
|  |       this._max = 1; | ||
|  |       this._xField = a["xField"] || a.defaultXField; | ||
|  |       this._yField = a["yField"] || a.defaultYField; | ||
|  |       this._valueField = a["valueField"] || a.defaultValueField; | ||
|  |       if (a["radius"]) { | ||
|  |         this._cfgRadius = a["radius"] | ||
|  |       } | ||
|  |     }; | ||
|  |     var c = a.defaultRadius; | ||
|  |     b.prototype = { | ||
|  |       _organiseData: function (a, b) { | ||
|  |         var d = a[this._xField]; | ||
|  |         var e = a[this._yField]; | ||
|  |         var f = this._radi; | ||
|  |         var g = this._data; | ||
|  |         var h = this._max; | ||
|  |         var i = this._min; | ||
|  |         var j = a[this._valueField] || 1; | ||
|  |         var k = a.radius || this._cfgRadius || c; | ||
|  |         if (!g[d]) { | ||
|  |           g[d] = []; | ||
|  |           f[d] = [] | ||
|  |         } | ||
|  |         if (!g[d][e]) { | ||
|  |           g[d][e] = j; | ||
|  |           f[d][e] = k | ||
|  |         } else { | ||
|  |           g[d][e] += j | ||
|  |         } | ||
|  |         if (g[d][e] > h) { | ||
|  |           if (!b) { | ||
|  |             this._max = g[d][e] | ||
|  |           } else { | ||
|  |             this.setDataMax(g[d][e]) | ||
|  |           } | ||
|  |           return false | ||
|  |         } else { | ||
|  |           return { x: d, y: e, value: j, radius: k, min: i, max: h } | ||
|  |         } | ||
|  |       }, _unOrganizeData: function () { | ||
|  |         var a = []; | ||
|  |         var b = this._data; | ||
|  |         var c = this._radi; | ||
|  |         for (var d in b) { | ||
|  |           for (var e in b[d]) { | ||
|  |             a.push({ x: d, y: e, radius: c[d][e], value: b[d][e] }) | ||
|  |           } | ||
|  |         } | ||
|  |         return { min: this._min, max: this._max, data: a } | ||
|  |       }, _onExtremaChange: function () { | ||
|  |         this._coordinator.emit("extremachange", { min: this._min, max: this._max }) | ||
|  |       }, addData: function () { | ||
|  |         if (arguments[0].length > 0) { | ||
|  |           var a = arguments[0]; | ||
|  |           var b = a.length; | ||
|  |           while (b--) { | ||
|  |             this.addData.call(this, a[b]) | ||
|  |           } | ||
|  |         } else { | ||
|  |           var c = this._organiseData(arguments[0], true); | ||
|  |           if (c) { | ||
|  |             this._coordinator.emit("renderpartial", { min: this._min, max: this._max, data: [c] }) | ||
|  |           } | ||
|  |         } | ||
|  |         return this | ||
|  |       }, setData: function (a) { | ||
|  |         var b = a.data; | ||
|  |         var c = b.length; | ||
|  |         this._data = []; | ||
|  |         this._radi = []; | ||
|  |         for (var d = 0; d < c; d++) { | ||
|  |           this._organiseData(b[d], false) | ||
|  |         } | ||
|  |         this._max = a.max; | ||
|  |         this._min = a.min || 0; | ||
|  |         this._onExtremaChange(); | ||
|  |         this._coordinator.emit("renderall", this._getInternalData()); | ||
|  |         return this | ||
|  |       }, removeData: function () { | ||
|  |       }, setDataMax: function (a) { | ||
|  |         this._max = a; | ||
|  |         this._onExtremaChange(); | ||
|  |         this._coordinator.emit("renderall", this._getInternalData()); | ||
|  |         return this | ||
|  |       }, setDataMin: function (a) { | ||
|  |         this._min = a; | ||
|  |         this._onExtremaChange(); | ||
|  |         this._coordinator.emit("renderall", this._getInternalData()); | ||
|  |         return this | ||
|  |       }, setCoordinator: function (a) { | ||
|  |         this._coordinator = a | ||
|  |       }, _getInternalData: function () { | ||
|  |         return { max: this._max, min: this._min, data: this._data, radi: this._radi } | ||
|  |       }, getData: function () { | ||
|  |         return this._unOrganizeData() | ||
|  |       } | ||
|  |     }; | ||
|  |     return b | ||
|  |   }(); | ||
|  |   var c = function i() { | ||
|  |     var a = function (a) { | ||
|  |       var b = a.gradient || a.defaultGradient; | ||
|  |       var c = document.createElement("canvas"); | ||
|  |       var d = c.getContext("2d"); | ||
|  |       c.width = 256; | ||
|  |       c.height = 1; | ||
|  |       var e = d.createLinearGradient(0, 0, 256, 1); | ||
|  |       for (var f in b) { | ||
|  |         e.addColorStop(f, b[f]) | ||
|  |       } | ||
|  |       d.fillStyle = e; | ||
|  |       d.fillRect(0, 0, 256, 1); | ||
|  |       return d.getImageData(0, 0, 256, 1).data | ||
|  |     }; | ||
|  |     var b = function (a, b) { | ||
|  |       var c = document.createElement("canvas"); | ||
|  |       var d = c.getContext("2d"); | ||
|  |       var e = a; | ||
|  |       var f = a; | ||
|  |       c.width = c.height = a * 2; | ||
|  |       if (b == 1) { | ||
|  |         d.beginPath(); | ||
|  |         d.arc(e, f, a, 0, 2 * Math.PI, false); | ||
|  |         d.fillStyle = "rgba(0,0,0,1)"; | ||
|  |         d.fill() | ||
|  |       } else { | ||
|  |         var g = d.createRadialGradient(e, f, a * b, e, f, a); | ||
|  |         g.addColorStop(0, "rgba(0,0,0,1)"); | ||
|  |         g.addColorStop(1, "rgba(0,0,0,0)"); | ||
|  |         d.fillStyle = g; | ||
|  |         d.fillRect(0, 0, 2 * a, 2 * a) | ||
|  |       } | ||
|  |       return c | ||
|  |     }; | ||
|  |     var c = function (a) { | ||
|  |       var b = []; | ||
|  |       var c = a.min; | ||
|  |       var d = a.max; | ||
|  |       var e = a.radi; | ||
|  |       var a = a.data; | ||
|  |       var f = Object.keys(a); | ||
|  |       var g = f.length; | ||
|  |       while (g--) { | ||
|  |         var h = f[g]; | ||
|  |         var i = Object.keys(a[h]); | ||
|  |         var j = i.length; | ||
|  |         while (j--) { | ||
|  |           var k = i[j]; | ||
|  |           var l = a[h][k]; | ||
|  |           var m = e[h][k]; | ||
|  |           b.push({ x: h, y: k, value: l, radius: m }) | ||
|  |         } | ||
|  |       } | ||
|  |       return { min: c, max: d, data: b } | ||
|  |     }; | ||
|  | 
 | ||
|  |     function d(b) { | ||
|  |       var c = b.container; | ||
|  |       var d = this.shadowCanvas = document.createElement("canvas"); | ||
|  |       var e = this.canvas = b.canvas || document.createElement("canvas"); | ||
|  |       var f = this._renderBoundaries = [1e4, 1e4, 0, 0]; | ||
|  |       var g = getComputedStyle(b.container) || {}; | ||
|  |       e.className = "heatmap-canvas"; | ||
|  |       this._width = e.width = d.width = +g.width.replace(/px/, ""); | ||
|  |       this._height = e.height = d.height = +g.height.replace(/px/, ""); | ||
|  |       this.shadowCtx = d.getContext("2d"); | ||
|  |       this.ctx = e.getContext("2d"); | ||
|  |       e.style.cssText = d.style.cssText = "position:absolute;left:0;top:0;"; | ||
|  |       c.style.position = "relative"; | ||
|  |       c.appendChild(e); | ||
|  |       this._palette = a(b); | ||
|  |       this._templates = {}; | ||
|  |       this._setStyles(b) | ||
|  |     } | ||
|  | 
 | ||
|  |     d.prototype = { | ||
|  |       renderPartial: function (a) { | ||
|  |         this._drawAlpha(a); | ||
|  |         this._colorize() | ||
|  |       }, renderAll: function (a) { | ||
|  |         this._clear(); | ||
|  |         this._drawAlpha(c(a)); | ||
|  |         this._colorize() | ||
|  |       }, _updateGradient: function (b) { | ||
|  |         this._palette = a(b) | ||
|  |       }, updateConfig: function (a) { | ||
|  |         if (a["gradient"]) { | ||
|  |           this._updateGradient(a) | ||
|  |         } | ||
|  |         this._setStyles(a) | ||
|  |       }, setDimensions: function (a, b) { | ||
|  |         this._width = a; | ||
|  |         this._height = b; | ||
|  |         this.canvas.width = this.shadowCanvas.width = a; | ||
|  |         this.canvas.height = this.shadowCanvas.height = b | ||
|  |       }, _clear: function () { | ||
|  |         this.shadowCtx.clearRect(0, 0, this._width, this._height); | ||
|  |         this.ctx.clearRect(0, 0, this._width, this._height) | ||
|  |       }, _setStyles: function (a) { | ||
|  |         this._blur = a.blur == 0 ? 0 : a.blur || a.defaultBlur; | ||
|  |         if (a.backgroundColor) { | ||
|  |           this.canvas.style.backgroundColor = a.backgroundColor | ||
|  |         } | ||
|  |         this._opacity = (a.opacity || 0) * 255; | ||
|  |         this._maxOpacity = (a.maxOpacity || a.defaultMaxOpacity) * 255; | ||
|  |         this._minOpacity = (a.minOpacity || a.defaultMinOpacity) * 255; | ||
|  |         this._useGradientOpacity = !!a.useGradientOpacity | ||
|  |       }, _drawAlpha: function (a) { | ||
|  |         var c = this._min = a.min; | ||
|  |         var d = this._max = a.max; | ||
|  |         var a = a.data || []; | ||
|  |         var e = a.length; | ||
|  |         var f = 1 - this._blur; | ||
|  |         while (e--) { | ||
|  |           var g = a[e]; | ||
|  |           var h = g.x; | ||
|  |           var i = g.y; | ||
|  |           var j = g.radius; | ||
|  |           var k = Math.min(g.value, d); | ||
|  |           var l = h - j; | ||
|  |           var m = i - j; | ||
|  |           var n = this.shadowCtx; | ||
|  |           var o; | ||
|  |           if (!this._templates[j]) { | ||
|  |             this._templates[j] = o = b(j, f) | ||
|  |           } else { | ||
|  |             o = this._templates[j] | ||
|  |           } | ||
|  |           n.globalAlpha = (k - c) / (d - c); | ||
|  |           n.drawImage(o, l, m); | ||
|  |           if (l < this._renderBoundaries[0]) { | ||
|  |             this._renderBoundaries[0] = l | ||
|  |           } | ||
|  |           if (m < this._renderBoundaries[1]) { | ||
|  |             this._renderBoundaries[1] = m | ||
|  |           } | ||
|  |           if (l + 2 * j > this._renderBoundaries[2]) { | ||
|  |             this._renderBoundaries[2] = l + 2 * j | ||
|  |           } | ||
|  |           if (m + 2 * j > this._renderBoundaries[3]) { | ||
|  |             this._renderBoundaries[3] = m + 2 * j | ||
|  |           } | ||
|  |         } | ||
|  |       }, _colorize: function () { | ||
|  |         var a = this._renderBoundaries[0]; | ||
|  |         var b = this._renderBoundaries[1]; | ||
|  |         var c = this._renderBoundaries[2] - a; | ||
|  |         var d = this._renderBoundaries[3] - b; | ||
|  |         var e = this._width; | ||
|  |         var f = this._height; | ||
|  |         var g = this._opacity; | ||
|  |         var h = this._maxOpacity; | ||
|  |         var i = this._minOpacity; | ||
|  |         var j = this._useGradientOpacity; | ||
|  |         if (a < 0) { | ||
|  |           a = 0 | ||
|  |         } | ||
|  |         if (b < 0) { | ||
|  |           b = 0 | ||
|  |         } | ||
|  |         if (a + c > e) { | ||
|  |           c = e - a | ||
|  |         } | ||
|  |         if (b + d > f) { | ||
|  |           d = f - b | ||
|  |         } | ||
|  |         var k = this.shadowCtx.getImageData(a, b, c, d); | ||
|  |         var l = k.data; | ||
|  |         var m = l.length; | ||
|  |         var n = this._palette; | ||
|  |         for (var o = 3; o < m; o += 4) { | ||
|  |           var p = l[o]; | ||
|  |           var q = p * 4; | ||
|  |           if (!q) { | ||
|  |             continue | ||
|  |           } | ||
|  |           var r; | ||
|  |           if (g > 0) { | ||
|  |             r = g | ||
|  |           } else { | ||
|  |             if (p < h) { | ||
|  |               if (p < i) { | ||
|  |                 r = i | ||
|  |               } else { | ||
|  |                 r = p | ||
|  |               } | ||
|  |             } else { | ||
|  |               r = h | ||
|  |             } | ||
|  |           } | ||
|  |           l[o - 3] = n[q]; | ||
|  |           l[o - 2] = n[q + 1]; | ||
|  |           l[o - 1] = n[q + 2]; | ||
|  |           l[o] = j ? n[q + 3] : r | ||
|  |         } | ||
|  |         k.data = l; | ||
|  |         this.ctx.putImageData(k, a, b); | ||
|  |         this._renderBoundaries = [1e3, 1e3, 0, 0] | ||
|  |       }, getValueAt: function (a) { | ||
|  |         var b; | ||
|  |         var c = this.shadowCtx; | ||
|  |         var d = c.getImageData(a.x, a.y, 1, 1); | ||
|  |         var e = d.data[3]; | ||
|  |         var f = this._max; | ||
|  |         var g = this._min; | ||
|  |         b = Math.abs(f - g) * (e / 255) >> 0; | ||
|  |         return b | ||
|  |       }, getDataURL: function () { | ||
|  |         return this.canvas.toDataURL() | ||
|  |       } | ||
|  |     }; | ||
|  |     return d | ||
|  |   }(); | ||
|  |   var d = function j() { | ||
|  |     var b = false; | ||
|  |     if (a["defaultRenderer"] === "canvas2d") { | ||
|  |       b = c | ||
|  |     } | ||
|  |     return b | ||
|  |   }(); | ||
|  |   var e = { | ||
|  |     merge: function () { | ||
|  |       var a = {}; | ||
|  |       var b = arguments.length; | ||
|  |       for (var c = 0; c < b; c++) { | ||
|  |         var d = arguments[c]; | ||
|  |         for (var e in d) { | ||
|  |           a[e] = d[e] | ||
|  |         } | ||
|  |       } | ||
|  |       return a | ||
|  |     } | ||
|  |   }; | ||
|  |   var f = function k() { | ||
|  |     var c = function h() { | ||
|  |       function a() { | ||
|  |         this.cStore = {} | ||
|  |       } | ||
|  | 
 | ||
|  |       a.prototype = { | ||
|  |         on: function (a, b, c) { | ||
|  |           var d = this.cStore; | ||
|  |           if (!d[a]) { | ||
|  |             d[a] = [] | ||
|  |           } | ||
|  |           d[a].push(function (a) { | ||
|  |             return b.call(c, a) | ||
|  |           }) | ||
|  |         }, emit: function (a, b) { | ||
|  |           var c = this.cStore; | ||
|  |           if (c[a]) { | ||
|  |             var d = c[a].length; | ||
|  |             for (var e = 0; e < d; e++) { | ||
|  |               var f = c[a][e]; | ||
|  |               f(b) | ||
|  |             } | ||
|  |           } | ||
|  |         } | ||
|  |       }; | ||
|  |       return a | ||
|  |     }(); | ||
|  |     var f = function (a) { | ||
|  |       var b = a._renderer; | ||
|  |       var c = a._coordinator; | ||
|  |       var d = a._store; | ||
|  |       c.on("renderpartial", b.renderPartial, b); | ||
|  |       c.on("renderall", b.renderAll, b); | ||
|  |       c.on("extremachange", function (b) { | ||
|  |         a._config.onExtremaChange && a._config.onExtremaChange({ | ||
|  |           min: b.min, | ||
|  |           max: b.max, | ||
|  |           gradient: a._config["gradient"] || a._config["defaultGradient"] | ||
|  |         }) | ||
|  |       }); | ||
|  |       d.setCoordinator(c) | ||
|  |     }; | ||
|  | 
 | ||
|  |     function g() { | ||
|  |       var g = this._config = e.merge(a, arguments[0] || {}); | ||
|  |       this._coordinator = new c; | ||
|  |       if (g["plugin"]) { | ||
|  |         var h = g["plugin"]; | ||
|  |         if (!a.plugins[h]) { | ||
|  |           throw new Error("Plugin '" + h + "' not found. Maybe it was not registered.") | ||
|  |         } else { | ||
|  |           var i = a.plugins[h]; | ||
|  |           this._renderer = new i.renderer(g); | ||
|  |           this._store = new i.store(g) | ||
|  |         } | ||
|  |       } else { | ||
|  |         this._renderer = new d(g); | ||
|  |         this._store = new b(g) | ||
|  |       } | ||
|  |       f(this) | ||
|  |     } | ||
|  | 
 | ||
|  |     g.prototype = { | ||
|  |       addData: function () { | ||
|  |         this._store.addData.apply(this._store, arguments); | ||
|  |         return this | ||
|  |       }, removeData: function () { | ||
|  |         this._store.removeData && this._store.removeData.apply(this._store, arguments); | ||
|  |         return this | ||
|  |       }, setData: function () { | ||
|  |         this._store.setData.apply(this._store, arguments); | ||
|  |         return this | ||
|  |       }, setDataMax: function () { | ||
|  |         this._store.setDataMax.apply(this._store, arguments); | ||
|  |         return this | ||
|  |       }, setDataMin: function () { | ||
|  |         this._store.setDataMin.apply(this._store, arguments); | ||
|  |         return this | ||
|  |       }, configure: function (a) { | ||
|  |         this._config = e.merge(this._config, a); | ||
|  |         this._renderer.updateConfig(this._config); | ||
|  |         this._coordinator.emit("renderall", this._store._getInternalData()); | ||
|  |         return this | ||
|  |       }, repaint: function () { | ||
|  |         this._coordinator.emit("renderall", this._store._getInternalData()); | ||
|  |         return this | ||
|  |       }, getData: function () { | ||
|  |         return this._store.getData() | ||
|  |       }, getDataURL: function () { | ||
|  |         return this._renderer.getDataURL() | ||
|  |       }, getValueAt: function (a) { | ||
|  |         if (this._store.getValueAt) { | ||
|  |           return this._store.getValueAt(a) | ||
|  |         } else if (this._renderer.getValueAt) { | ||
|  |           return this._renderer.getValueAt(a) | ||
|  |         } else { | ||
|  |           return null | ||
|  |         } | ||
|  |       } | ||
|  |     }; | ||
|  |     return g | ||
|  |   }(); | ||
|  |   var g = { | ||
|  |     create: function (a) { | ||
|  |       return new f(a) | ||
|  |     }, register: function (b, c) { | ||
|  |       a.plugins[b] = c | ||
|  |     } | ||
|  |   }; | ||
|  |   return g | ||
|  | }); |