UNPKG

c8y-openlayer

Version:

This module is designed to help integrate Openlayer with Cumulocity IoT

294 lines (246 loc) 7.43 kB
import _ol_events_ from '../events.js'; import _ol_ from '../index.js'; import _ol_Object_ from '../object.js'; import _ol_dom_ from '../dom.js'; import _ol_layer_Vector_ from '../layer/vector.js'; import _ol_math_ from '../math.js'; import _ol_obj_ from '../obj.js'; import _ol_render_EventType_ from '../render/eventtype.js'; import _ol_style_Icon_ from '../style/icon.js'; import _ol_style_Style_ from '../style/style.js'; /** * @classdesc * Layer for rendering vector data as a heatmap. * Note that any property set in the options is set as a {@link ol.Object} * property on the layer object; for example, setting `title: 'My Title'` in the * options means that `title` is observable, and has get/set accessors. * * @constructor * @extends {ol.layer.Vector} * @fires ol.render.Event * @param {olx.layer.HeatmapOptions=} opt_options Options. * @api */ var _ol_layer_Heatmap_ = function(opt_options) { var options = opt_options ? opt_options : {}; var baseOptions = _ol_obj_.assign({}, options); delete baseOptions.gradient; delete baseOptions.radius; delete baseOptions.blur; delete baseOptions.shadow; delete baseOptions.weight; _ol_layer_Vector_.call(this, /** @type {olx.layer.VectorOptions} */ (baseOptions)); /** * @private * @type {Uint8ClampedArray} */ this.gradient_ = null; /** * @private * @type {number} */ this.shadow_ = options.shadow !== undefined ? options.shadow : 250; /** * @private * @type {string|undefined} */ this.circleImage_ = undefined; /** * @private * @type {Array.<Array.<ol.style.Style>>} */ this.styleCache_ = null; _ol_events_.listen(this, _ol_Object_.getChangeEventType(_ol_layer_Heatmap_.Property_.GRADIENT), this.handleGradientChanged_, this); this.setGradient(options.gradient ? options.gradient : _ol_layer_Heatmap_.DEFAULT_GRADIENT); this.setBlur(options.blur !== undefined ? options.blur : 15); this.setRadius(options.radius !== undefined ? options.radius : 8); _ol_events_.listen(this, _ol_Object_.getChangeEventType(_ol_layer_Heatmap_.Property_.BLUR), this.handleStyleChanged_, this); _ol_events_.listen(this, _ol_Object_.getChangeEventType(_ol_layer_Heatmap_.Property_.RADIUS), this.handleStyleChanged_, this); this.handleStyleChanged_(); var weight = options.weight ? options.weight : 'weight'; var weightFunction; if (typeof weight === 'string') { weightFunction = function(feature) { return feature.get(weight); }; } else { weightFunction = weight; } this.setStyle(function(feature, resolution) { var weight = weightFunction(feature); var opacity = weight !== undefined ? _ol_math_.clamp(weight, 0, 1) : 1; // cast to 8 bits var index = (255 * opacity) | 0; var style = this.styleCache_[index]; if (!style) { style = [ new _ol_style_Style_({ image: new _ol_style_Icon_({ opacity: opacity, src: this.circleImage_ }) }) ]; this.styleCache_[index] = style; } return style; }.bind(this)); // For performance reasons, don't sort the features before rendering. // The render order is not relevant for a heatmap representation. this.setRenderOrder(null); _ol_events_.listen(this, _ol_render_EventType_.RENDER, this.handleRender_, this); }; _ol_.inherits(_ol_layer_Heatmap_, _ol_layer_Vector_); /** * @const * @type {Array.<string>} */ _ol_layer_Heatmap_.DEFAULT_GRADIENT = ['#00f', '#0ff', '#0f0', '#ff0', '#f00']; /** * @param {Array.<string>} colors A list of colored. * @return {Uint8ClampedArray} An array. * @private */ _ol_layer_Heatmap_.createGradient_ = function(colors) { var width = 1; var height = 256; var context = _ol_dom_.createCanvasContext2D(width, height); var gradient = context.createLinearGradient(0, 0, width, height); var step = 1 / (colors.length - 1); for (var i = 0, ii = colors.length; i < ii; ++i) { gradient.addColorStop(i * step, colors[i]); } context.fillStyle = gradient; context.fillRect(0, 0, width, height); return context.getImageData(0, 0, width, height).data; }; /** * @return {string} Data URL for a circle. * @private */ _ol_layer_Heatmap_.prototype.createCircle_ = function() { var radius = this.getRadius(); var blur = this.getBlur(); var halfSize = radius + blur + 1; var size = 2 * halfSize; var context = _ol_dom_.createCanvasContext2D(size, size); context.shadowOffsetX = context.shadowOffsetY = this.shadow_; context.shadowBlur = blur; context.shadowColor = '#000'; context.beginPath(); var center = halfSize - this.shadow_; context.arc(center, center, radius, 0, Math.PI * 2, true); context.fill(); return context.canvas.toDataURL(); }; /** * Return the blur size in pixels. * @return {number} Blur size in pixels. * @api * @observable */ _ol_layer_Heatmap_.prototype.getBlur = function() { return ( /** @type {number} */ this.get(_ol_layer_Heatmap_.Property_.BLUR) ); }; /** * Return the gradient colors as array of strings. * @return {Array.<string>} Colors. * @api * @observable */ _ol_layer_Heatmap_.prototype.getGradient = function() { return ( /** @type {Array.<string>} */ this.get(_ol_layer_Heatmap_.Property_.GRADIENT) ); }; /** * Return the size of the radius in pixels. * @return {number} Radius size in pixel. * @api * @observable */ _ol_layer_Heatmap_.prototype.getRadius = function() { return ( /** @type {number} */ this.get(_ol_layer_Heatmap_.Property_.RADIUS) ); }; /** * @private */ _ol_layer_Heatmap_.prototype.handleGradientChanged_ = function() { this.gradient_ = _ol_layer_Heatmap_.createGradient_(this.getGradient()); }; /** * @private */ _ol_layer_Heatmap_.prototype.handleStyleChanged_ = function() { this.circleImage_ = this.createCircle_(); this.styleCache_ = new Array(256); this.changed(); }; /** * @param {ol.render.Event} event Post compose event * @private */ _ol_layer_Heatmap_.prototype.handleRender_ = function(event) { var context = event.context; var canvas = context.canvas; var image = context.getImageData(0, 0, canvas.width, canvas.height); var view8 = image.data; var i, ii, alpha; for (i = 0, ii = view8.length; i < ii; i += 4) { alpha = view8[i + 3] * 4; if (alpha) { view8[i] = this.gradient_[alpha]; view8[i + 1] = this.gradient_[alpha + 1]; view8[i + 2] = this.gradient_[alpha + 2]; } } context.putImageData(image, 0, 0); }; /** * Set the blur size in pixels. * @param {number} blur Blur size in pixels. * @api * @observable */ _ol_layer_Heatmap_.prototype.setBlur = function(blur) { this.set(_ol_layer_Heatmap_.Property_.BLUR, blur); }; /** * Set the gradient colors as array of strings. * @param {Array.<string>} colors Gradient. * @api * @observable */ _ol_layer_Heatmap_.prototype.setGradient = function(colors) { this.set(_ol_layer_Heatmap_.Property_.GRADIENT, colors); }; /** * Set the size of the radius in pixels. * @param {number} radius Radius size in pixel. * @api * @observable */ _ol_layer_Heatmap_.prototype.setRadius = function(radius) { this.set(_ol_layer_Heatmap_.Property_.RADIUS, radius); }; /** * @enum {string} * @private */ _ol_layer_Heatmap_.Property_ = { BLUR: 'blur', GRADIENT: 'gradient', RADIUS: 'radius' }; export default _ol_layer_Heatmap_;