UNPKG

visual-heatmap

Version:

"Advanced Visual Heatmap - High Scale webGL based rendering."

6 lines 18.8 kB
/*! * Heatmap * (c) 2024 Narayana Swamy (narayanaswamy14@gmail.com) * @license BSD-3-Clause */ const t={vertex:"#version 300 es\n\t\t\t\tin vec2 a_position;\n\t\t\t\tin float a_intensity;\n\t\t\t\tuniform float u_size;\n\t\t\t\tuniform vec2 u_resolution;\n\t\t\t\tuniform vec2 u_translate; \n\t\t\t\tuniform float u_zoom; \n\t\t\t\tuniform float u_angle; \n\t\t\t\tuniform float u_density;\n\t\t\t\tout float v_i;\n\n\t\t\t\tvec2 rotation(vec2 v, float a, float aspect) {\n\t\t\t\t\tfloat s = sin(a); float c = cos(a); mat2 rotationMat = mat2(c, -s, s, c); \n\t\t\t\t\tmat2 scaleMat = mat2(aspect, 0.0, 0.0, 1.0);\n\t\t\t\t\tmat2 scaleMatInv = mat2(1.0/aspect, 0.0, 0.0, 1.0);\n\t\t\t\t\treturn scaleMatInv * rotationMat * scaleMat * v;\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec2 zeroToOne = (a_position * u_density + u_translate * u_density) / (u_resolution);\n\t\t\t\t\tvec2 zeroToTwo = zeroToOne * 2.0 - 1.0;\n\t\t\t\t\tfloat zoomFactor = max(u_zoom, 0.1);\n\t\t\t\t\tzeroToTwo = zeroToTwo / zoomFactor;\n\t\t\t\t\tif (u_angle != 0.0) {\n\t\t\t\t\t\tzeroToTwo = rotation(zeroToTwo, u_angle, u_resolution.x / u_resolution.y);\n\t\t\t\t\t}\n\t\t\t\t\tgl_Position = vec4(zeroToTwo , 0, 1);\n\t\t\t\t\tgl_PointSize = u_size * u_density;\n\t\t\t\t\tv_i = a_intensity;\n\t\t\t\t}",fragment:"#version 300 es\n\t\t\t\tprecision mediump float;\n\t\t\t\tuniform float u_max;\n\t\t\t\tuniform float u_min;\n\t\t\t\tuniform float u_intensity;\n\t\t\t\tin float v_i;\n\t\t\t\tout vec4 fragColor;\n\t\t\t\tvoid main() {\n\t\t\t\t\tfloat r = 0.0; \n\t\t\t\t\tvec2 cxy = 2.0 * gl_PointCoord - 1.0;\n\t\t\t\t\tr = dot(cxy, cxy);\n\t\t\t\t\tfloat deno = max(u_max - u_min, 1.0);\n\t\t\t\t\tif(r <= 1.0) {\n\t\t\t\t\t\tfragColor = vec4(0, 0, 0, ((v_i - u_min) / (deno)) * u_intensity * (1.0 - sqrt(r)));\n\t\t\t\t\t}\n\t\t\t\t}"},e={vertex:"#version 300 es\n\t\t\t\tprecision highp float;\n\t\t\t\tin vec2 a_texCoord;\n\t\t\t\tout vec2 v_texCoord;\n\t\t\t\tvoid main() {\n\t\t\t\t\tvec2 clipSpace = a_texCoord * 2.0 - 1.0;\n\t\t\t\t\tgl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\n\t\t\t\t\tv_texCoord = a_texCoord;\n\t\t\t\t}\n\t",fragment:"#version 300 es\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t\tin vec2 v_texCoord;\n\t\t\t\t\tout vec4 fragColor;\n\t\t\t\t\tuniform sampler2D u_framebuffer;\n\t\t\t\t\tuniform vec4 u_colorArr[20];\n\t\t\t\t\tuniform float u_colorCount;\n\t\t\t\t\tuniform float u_opacity;\n\t\t\t\t\tuniform float u_offset[20];\n\n\t\t\t\t\tfloat remap ( float minval, float maxval, float curval ) {\n\t\t\t\t\t\treturn ( curval - minval ) / ( maxval - minval );\n\t\t\t\t\t}\n\n\t\t\t\t\tvoid main() {\n\t\t\t\t\t\tfloat alpha = texture(u_framebuffer, v_texCoord.xy).a;\n\t\t\t\t\t\tif (alpha > 0.0 && alpha <= 1.0) {\n\t\t\t\t\t\t\tvec4 color_;\n\n\t\t\t\t\t\t\tif (alpha <= u_offset[0]) {\n\t\t\t\t\t\t\t\tcolor_ = u_colorArr[0];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfor (int i = 1; i <= 20; ++i) {\n\t\t\t\t\t\t\t\t\tif (alpha <= u_offset[i]) {\n\t\t\t\t\t\t\t\t\t\tcolor_ = mix( u_colorArr[i - 1], u_colorArr[i], remap( u_offset[i - 1], u_offset[i], alpha ) );\n\t\t\t\t\t\t\t\t\t\tcolor_ = color_ * mix( u_colorArr[i - 1][3], u_colorArr[i][3], remap( u_offset[i - 1], u_offset[i], alpha ));\n\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcolor_ = color_ * u_opacity;\n\t\t\t\t\t\t\tif (color_.a < 0.0) {\n\t\t\t\t\t\t\t\tcolor_.a = 0.0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfragColor = color_;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t"},i={vertex:"#version 300 es\n precision highp float;\n in vec2 a_position;\n in vec2 a_texCoord;\n uniform vec2 u_resolution;\n\t\t\t\t\tuniform vec2 u_translate; \n\t\t\t\t\tuniform float u_zoom; \n\t\t\t\t\tuniform float u_angle; \n\t\t\t\t\tuniform float u_density;\n out vec2 v_texCoord;\n\n vec2 rotation(vec2 v, float a, float aspect) {\n\t\t\t\t\t\tfloat s = sin(a); float c = cos(a); mat2 m = mat2(c, -s, s, c);\n\t\t\t\t\t\tmat2 scaleMat = mat2(aspect, 0.0, 0.0, 1.0);\n\t\t\t\t\t\tmat2 scaleMatInv = mat2(1.0/aspect, 0.0, 0.0, 1.0);\n\t\t\t\t\t\treturn scaleMatInv * m * scaleMat * v;\n\t\t\t\t\t}\n\n void main() {\n \tvec2 zeroToOne = (a_position * u_density + u_translate * u_density) / (u_resolution);\n \tzeroToOne.y = 1.0 - zeroToOne.y;\n\t\t\t\t\t\tvec2 zeroToTwo = zeroToOne * 2.0 - 1.0;\n\t\t\t\t\t\tfloat zoomFactor = u_zoom;\n\t\t\t\t\t\tif (zoomFactor == 0.0) {\n\t\t\t\t\t\t\tzoomFactor = 0.1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tzeroToTwo = zeroToTwo / zoomFactor;\n\t\t\t\t\t\tif (u_angle != 0.0) {\n\t\t\t\t\t\t\tzeroToTwo = rotation(zeroToTwo, u_angle * -1.0, u_resolution.x / u_resolution.y);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tgl_Position = vec4(zeroToTwo , 0, 1);\n\t\t\t\t\t\tv_texCoord = a_texCoord;\n }\n \t\t",fragment:"#version 300 es\n precision mediump float;\n uniform sampler2D u_image;\n in vec2 v_texCoord;\n out vec4 fragColor;\n void main() {\n fragColor = texture(u_image, v_texCoord);\n }\n "};function r(t,e,i){const r=t.createShader(t[e]);if(!r)throw new Error("Failed to create shader.");t.shaderSource(r,i),t.compileShader(r);if(!t.getShaderParameter(r,t.COMPILE_STATUS)){const e=t.getShaderInfoLog(r);throw t.deleteShader(r),new Error("*** Error compiling shader '"+r+"':"+e)}return r}function o(t,e){const i=r(t,"VERTEX_SHADER",e.vertex),o=r(t,"FRAGMENT_SHADER",e.fragment),n=t.createProgram();if(!n)throw new Error("Failed to create program.");t.attachShader(n,i),t.attachShader(n,o),t.linkProgram(n);if(t.getProgramParameter(n,t.LINK_STATUS))return n;{const e=t.getProgramInfoLog(n);throw t.deleteProgram(n),new Error("Error in program linking:"+e)}}function n(t){return null==t}function a(t){return"number"!=typeof t}function s(t){if(!Array.isArray(t)||t.length<2)throw new Error("Invalid gradient: Expected an array with at least 2 elements.");if(!function(t){for(let e=0;e<t.length-1;e++)if(t[e+1].offset-t[e].offset<0)return!1;return!0}(t))throw new Error("Invalid gradient: Gradient is not sorted");const e=t.length,i=new Float32Array(4*e),r=new Array(e);return t.forEach((function(t,e){const o=4*e;i[o]=t.color[0]/255,i[o+1]=t.color[1]/255,i[o+2]=t.color[2]/255,i[o+3]=void 0!==t.color[3]?t.color[3]:1,r[e]=t.offset})),{value:i,length:e,offset:r}}function u(t){const e=this,i=t.length;let{posVec:r=new Float32Array,rVec:o=new Float32Array}=e.hearmapExData||{};e._pDataLength!==i&&(r=new Float32Array(new ArrayBuffer(8*i)),o=new Float32Array(new ArrayBuffer(4*i)),e._pDataLength=i);const n={min:1/0,max:-1/0};for(let e=0;e<i;e++)r[2*e]=t[e].x,r[2*e+1]=t[e].y,o[e]=t[e].value,n.min>t[e].value&&(n.min=t[e].value),n.max<t[e].value&&(n.max=t[e].value);return{posVec:r,rVec:o,minMax:n}}function h(t){const e=this.zoom||.1,i=this.width/2,r=this.height/2,{angle:o,translate:n}=this;let a=(t.x-i)/i*e,s=(t.y-r)/r*e;if(0!==o){const t=Math.cos(o),e=Math.sin(o);s=e*a+t*s,a=t*a-e*s}return a=a*i+i-n[0],s=s*r+r-n[1],t.x=a,t.y=s,{x:a,y:s}}function l(){const t=this.ctx;t&&(t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT),t.bindTexture(t.TEXTURE_2D,this._fbTexObj),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.width*this.ratio,this.height*this.ratio,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.bindFramebuffer(t.FRAMEBUFFER,this._fbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,this._fbTexObj,0),this.hearmapExData&&f.call(this,t,this.hearmapExData),t.bindFramebuffer(t.FRAMEBUFFER,null),this.imageConfig&&c.call(this,t,this.imageConfig),m.call(this,t))}function f(t,e){var i,r,o,n;t.useProgram(this._gradShadOP.program);const{u_resolution:a,u_translate:s,u_zoom:u,u_angle:h,u_density:l,u_max:f,u_min:c,u_size:m,u_intensity:_}=this._gradShadOP.uniform;this.min=null!==this.configMin?this.configMin:null!==(r=null===(i=null==e?void 0:e.minMax)||void 0===i?void 0:i.min)&&void 0!==r?r:0,this.max=null!==this.configMax?this.configMax:null!==(n=null===(o=null==e?void 0:e.minMax)||void 0===o?void 0:o.max)&&void 0!==n?n:0,this._gradShadOP.attr[0].data=e.posVec||[],this._gradShadOP.attr[1].data=e.rVec||[],t.uniform2fv(a,new Float32Array([this.width*this.ratio,this.height*this.ratio])),t.uniform2fv(s,new Float32Array([this.translate[0],this.translate[1]])),t.uniform1f(u,this.zoom?this.zoom:.01),t.uniform1f(h,this.angle),t.uniform1f(l,this.ratio),t.uniform1f(f,this.max),t.uniform1f(c,this.min),t.uniform1f(m,this.size),t.uniform1f(_,this.intensity),this._gradShadOP.attr.forEach((function(e){t.bindBuffer(e.bufferType,e.buffer),t.bufferData(e.bufferType,e.data,e.drawType),t.enableVertexAttribArray(e.attribute),t.vertexAttribPointer(e.attribute,e.size,e.valueType,!0,0,0)})),t.drawArrays(t.POINTS,0,(e.posVec||[]).length/2)}function c(t,e){const{x:i=0,y:r=0,width:o=0,height:n=0}=e,{u_resolution:a,u_translate:s,u_zoom:u,u_angle:h,u_density:l,u_image:f}=this._imageShaOP.uniform;t.useProgram(this._imageShaOP.program),t.uniform2fv(a,new Float32Array([this.width*this.ratio,this.height*this.ratio])),t.uniform2fv(s,new Float32Array([this.translate[0],this.translate[1]])),t.uniform1f(u,this.zoom?this.zoom:.01),t.uniform1f(h,this.angle),t.uniform1f(l,this.ratio),this._imageShaOP.attr[0].data=new Float32Array([i,r,i+o,r,i,r+n,i,r+n,i+o,r,i+o,r+n]),this._imageShaOP.attr.forEach((function(e){t.bindBuffer(e.bufferType,e.buffer),t.bufferData(e.bufferType,e.data,e.drawType),t.enableVertexAttribArray(e.attribute),t.vertexAttribPointer(e.attribute,e.size,e.valueType,!0,0,0)})),t.uniform1i(f,0),t.activeTexture(this.ctx.TEXTURE0),t.bindTexture(this.ctx.TEXTURE_2D,this._imageTexture),t.drawArrays(t.TRIANGLES,0,6)}function m(t){const{u_colorArr:e,u_colorCount:i,u_offset:r,u_opacity:o,u_framebuffer:n}=this._colorShadOP.uniform;t.useProgram(this._colorShadOP.program),t.uniform4fv(e,this.gradient.value),t.uniform1f(i,this.gradient.length),t.uniform1fv(r,new Float32Array(this.gradient.offset)),t.uniform1f(o,this.opacity),this._colorShadOP.attr.forEach((function(e){t.bindBuffer(e.bufferType,e.buffer),t.bufferData(e.bufferType,e.data,e.drawType),t.enableVertexAttribArray(e.attribute),t.vertexAttribPointer(e.attribute,e.size,e.valueType,!0,0,0)})),t.uniform1i(n,0),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this._fbTexObj),t.drawArrays(t.TRIANGLES,0,6)}class _{constructor(r,a){this.ctx=null,this.ratio=1,this.width=0,this.height=0,this.imageConfig=null,this.configMin=null,this.configMax=null,this.min=0,this.max=0,this.size=0,this.zoom=0,this.angle=0,this.intensity=0,this.translate=[0,0],this.opacity=0,this.hearmapExData={},this.gradient=null,this._imageTexture=null,this._pDataLength=void 0,this.imgWidth=0,this.imgHeight=0,this.heatmapData=[],this.type="";try{const u="string"==typeof r?document.querySelector(r):r instanceof HTMLElement?r:null;if(!u)throw new Error("Context must be either a string or an Element");const{clientHeight:h,clientWidth:l}=u,f=document.createElement("canvas"),c=f.getContext("webgl2",{premultipliedAlpha:!1,depth:!1,antialias:!0,alpha:!0,preserveDrawingBuffer:!1});this.ratio=function(t){return(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)}(c),c.clearColor(0,0,0,0),c.enable(c.BLEND),c.blendEquation(c.FUNC_ADD),c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA),c.depthMask(!0),f.setAttribute("height",(h*this.ratio).toString()),f.setAttribute("width",(l*this.ratio).toString()),f.style.height=`${h}px`,f.style.width=`${l}px`,f.style.position="absolute",u.appendChild(f),this.ctx=c,this.width=l,this.height=h,this.imageConfig=null,this.configMin=null,this.configMax=null,this.hearmapExData={},this.layer=f,this.dom=u,this._gradShadOP=function(t,e){const i=o(t,e),r=t.createBuffer();if(!r)throw new Error("Failed to create position buffer.");const n=t.createBuffer();if(!n)throw new Error("Failed to create intensity buffer.");return{program:i,attr:[{bufferType:t.ARRAY_BUFFER,buffer:r,drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(i,"a_position"),data:new Float32Array([])},{bufferType:t.ARRAY_BUFFER,buffer:n,drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:1,attribute:t.getAttribLocation(i,"a_intensity"),data:new Float32Array([])}],uniform:{u_resolution:t.getUniformLocation(i,"u_resolution"),u_max:t.getUniformLocation(i,"u_max"),u_min:t.getUniformLocation(i,"u_min"),u_size:t.getUniformLocation(i,"u_size"),u_intensity:t.getUniformLocation(i,"u_intensity"),u_translate:t.getUniformLocation(i,"u_translate"),u_zoom:t.getUniformLocation(i,"u_zoom"),u_angle:t.getUniformLocation(i,"u_angle"),u_density:t.getUniformLocation(i,"u_density")}}}(this.ctx,t),this._colorShadOP=function(t,e){const i=o(t,e),r=t.createBuffer();if(!r)throw new Error("Failed to create texture coordinate buffer.");return{program:i,attr:[{bufferType:t.ARRAY_BUFFER,buffer:r,drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(i,"a_texCoord"),data:new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1])}],uniform:{u_framebuffer:t.getUniformLocation(i,"u_framebuffer"),u_colorArr:t.getUniformLocation(i,"u_colorArr"),u_colorCount:t.getUniformLocation(i,"u_colorCount"),u_opacity:t.getUniformLocation(i,"u_opacity"),u_offset:t.getUniformLocation(i,"u_offset")}}}(this.ctx,e),this._imageShaOP=function(t,e){const i=o(t,e),r=t.createBuffer();if(!r)throw new Error("Failed to create position buffer.");const n=t.createBuffer();if(!n)throw new Error("Failed to create texture coordinate buffer.");return{program:i,attr:[{bufferType:t.ARRAY_BUFFER,buffer:r,drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(i,"a_position"),data:new Float32Array([])},{bufferType:t.ARRAY_BUFFER,buffer:n,drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(i,"a_texCoord"),data:new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1])}],uniform:{u_resolution:t.getUniformLocation(i,"u_resolution"),u_image:t.getUniformLocation(i,"u_image"),u_translate:t.getUniformLocation(i,"u_translate"),u_zoom:t.getUniformLocation(i,"u_zoom"),u_angle:t.getUniformLocation(i,"u_angle"),u_density:t.getUniformLocation(i,"u_density")}}}(this.ctx,i),this._fbTexObj=c.createTexture(),this._fbo=c.createFramebuffer(),n(a.size)?this.size=20:this.setSize(a.size),n(a.max)?this.configMax=null:this.setMax(a.max),n(a.min)?this.configMin=null:this.setMin(a.min),n(a.intensity)?this.intensity=1:this.setIntensity(a.intensity),n(a.translate)?this.translate=[0,0]:this.setTranslate(a.translate),n(a.zoom)?this.zoom=1:this.setZoom(a.zoom),n(a.angle)?this.angle=0:this.setRotationAngle(a.angle),n(a.opacity)?this.opacity=1:this.setOpacity(a.opacity),this.gradient=s(a.gradient),a.backgroundImage&&a.backgroundImage.url&&this.setBackgroundImage(a.backgroundImage),this.heatmapData=[],this.ctx.viewport(0,0,this.ctx.canvas.width,this.ctx.canvas.height)}catch(t){console.error(t)}}resize(){const t=this.dom.clientHeight,e=this.dom.clientWidth;this.layer.setAttribute("height",(t*this.ratio).toString()),this.layer.setAttribute("width",(e*this.ratio).toString()),this.layer.style.height=`${t}px`,this.layer.style.width=`${e}px`,this.width=e,this.height=t,this.ctx.viewport(0,0,this.ctx.canvas.width,this.ctx.canvas.height),this.render()}clear(){this.ctx.clear(this.ctx.COLOR_BUFFER_BIT|this.ctx.DEPTH_BUFFER_BIT)}setMax(t){if(n(t)||a(t))throw new Error("Invalid max: Expected Number");return this.configMax=t,this}setMin(t){if(n(t)||a(t))throw new Error("Invalid min: Expected Number");return this.configMin=t,this}setGradient(t){return this.gradient=s(t),this}setTranslate(t){if(t.constructor!==Array)throw new Error("Invalid Translate: Translate has to be of Array type");if(2!==t.length)throw new Error("Translate has to be of length 2");return this.translate=t,this}setZoom(t){if(n(t)||a(t))throw new Error("Invalid zoom: Expected Number");return this.zoom=t,this}setRotationAngle(t){if(n(t)||a(t))throw new Error("Invalid Angle: Expected Number");return this.angle=t,this}setSize(t){if(n(t)||a(t))throw new Error("Invalid Size: Expected Number");return this.size=t,this}setIntensity(t){if(n(t)||a(t))throw this.intensity=1,new Error("Invalid Intensity: Expected Number");if(t>1||t<0)throw this.intensity=t>1?1:0,new Error("Invalid Intensity value "+t);return this.intensity=t,this}setOpacity(t){if(n(t)||a(t))throw new Error("Invalid Opacity: Expected Number");if(t>1||t<0)throw new Error("Invalid Opacity value "+t);return this.opacity=t,this}setBackgroundImage(t){const e=this;if(!t.url)return;const i=this.ctx.getParameter(this.ctx.MAX_TEXTURE_SIZE);return this._imageTexture=this.ctx.createTexture(),this.type="TEXTURE_2D",this.imageConfig=null,this.imgWidth=t.width||this.width,this.imgHeight=t.height||this.height,this.imgWidth=this.imgWidth>i?i:this.imgWidth,this.imgHeight=this.imgHeight>i?i:this.imgHeight,function(t,e,i){const r=new Image;r.crossOrigin="anonymous",r.onload=e,r.onerror=i,r.src=t}(t.url,(function(){e.ctx.activeTexture(e.ctx.TEXTURE0),e.ctx.bindTexture(e.ctx.TEXTURE_2D,e._imageTexture),e.ctx.texParameteri(e.ctx.TEXTURE_2D,e.ctx.TEXTURE_WRAP_S,e.ctx.CLAMP_TO_EDGE),e.ctx.texParameteri(e.ctx.TEXTURE_2D,e.ctx.TEXTURE_WRAP_T,e.ctx.CLAMP_TO_EDGE),e.ctx.texParameteri(e.ctx.TEXTURE_2D,e.ctx.TEXTURE_MIN_FILTER,e.ctx.LINEAR),e.ctx.texParameteri(e.ctx.TEXTURE_2D,e.ctx.TEXTURE_MAG_FILTER,e.ctx.LINEAR),e.ctx.texImage2D(e.ctx.TEXTURE_2D,0,e.ctx.RGBA,this.naturalWidth,this.naturalHeight,0,e.ctx.RGBA,e.ctx.UNSIGNED_BYTE,this),e.imageConfig={x:t.x||0,y:t.y||0,height:e.imgHeight,width:e.imgWidth,image:this},e.render()}),(function(t){throw new Error(`Image Load Error, ${t}`)})),this}clearData(){this.heatmapData=[],this.hearmapExData={},this.render()}addData(t,e){const i=this;for(let r=0;r<t.length;r++)e&&h.call(i,t[r]),this.heatmapData.push(t[r]);return this.renderData(this.heatmapData),this}renderData(t){if(t.constructor!==Array)throw new Error("Expected Array type");return this.hearmapExData=u.call(this,t),this.heatmapData=t,this.render(),this}render(){l.call(this)}projection(t){const e=this.zoom||.1,i=this.width/2,r=this.height/2,o=this.translate[0],n=this.translate[1],a=this.angle,s=this.width/this.height;let u=(t.x+o-i)/(i*e),h=(t.y+n-r)/(r*e);if(u*=s,0!==a){const t=Math.cos(-a),e=Math.sin(-a),i=t*u-e*h;h=e*u+t*h,u=i}return u*=1/s,u=u*i+i,h=h*r+r,{x:u,y:h}}}function g(t,e){return new _(t,e)}export{g as default};