New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

visual-heatmap

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

visual-heatmap - npm Package Compare versions

Comparing version 2.0.1 to 2.1.0

dist/types/heatmap.d.ts

1490

dist/visualHeatmap.esm.js

@@ -6,709 +6,4 @@ /*!

*/
function Heatmap (context, config = {}) {
let ratio;
let buffer;
let posVec = [];
let buffer2;
let rVec = [];
let pLen = 0;
let maxTextureSize = null;
let imgWidth;
let imgHeight;
let hearmapExData;
let imageConfig;
let configMin = 0;
let configMax = 0;
function isNullUndefined (val) {
return val === null || val === undefined;
}
function isNotNumber (val) {
return typeof val !== 'number';
}
function isSortedAscending (arr) {
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i + 1].offset - arr[i].offset < 0) {
return false;
}
}
return true;
}
function gradientMapper (grad) {
if (grad.constructor !== Array) {
throw new Error('Invalid gradient: Wrong Gradient type, expected Array');
}
if (grad.length < 2) {
throw new Error('Invalid gradient: 2 or more values expected');
}
if (!isSortedAscending(grad)) {
throw new Error('Invalid gradient: Gradient is not sorted');
}
const gradLength = grad.length;
const values = new Float32Array(gradLength * 4);
const offsets = new Array(gradLength);
grad.forEach(function (d, i) {
const baseIndex = i * 4;
values[baseIndex] = d.color[0] / 255;
values[baseIndex + 1] = d.color[1] / 255;
values[baseIndex + 2] = d.color[2] / 255;
values[baseIndex + 3] = d.color[3] !== undefined ? d.color[3] : 1.0;
offsets[i] = d.offset;
});
return {
value: values,
length: gradLength,
offset: offsets
};
}
function createShader (ctx, type, src) {
var shader = ctx.createShader(ctx[type]);
ctx.shaderSource(shader, src);
ctx.compileShader(shader);
var compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
if (!compiled) {
var lastError = ctx.getShaderInfoLog(shader);
ctx.deleteShader(shader);
throw new Error("*** Error compiling shader '" + shader + "':" + lastError);
}
return shader;
}
function createProgram (ctx, shader) {
var vshader = createShader(ctx, 'VERTEX_SHADER', shader.vertex);
var fshader = createShader(ctx, 'FRAGMENT_SHADER', shader.fragment);
var program = ctx.createProgram();
ctx.attachShader(program, vshader);
ctx.attachShader(program, fshader);
ctx.linkProgram(program);
var linked = ctx.getProgramParameter(program, ctx.LINK_STATUS);
if (!linked) {
var lastError = ctx.getProgramInfoLog(program);
ctx.deleteProgram(program);
throw new Error('Error in program linking:' + lastError);
} else {
return program;
}
}
function createImageShader (ctx) {
var program = createProgram(ctx, imageShaders);
return {
program: program,
attr: [{
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_position'),
data: new Float32Array([])
}, {
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_texCoord'),
data: new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0])
}],
uniform: {
u_resolution: ctx.getUniformLocation(program, 'u_resolution'),
u_image: ctx.getUniformLocation(program, 'u_image'),
u_translate: ctx.getUniformLocation(program, 'u_translate'),
u_zoom: ctx.getUniformLocation(program, 'u_zoom'),
u_angle: ctx.getUniformLocation(program, 'u_angle'),
u_density: ctx.getUniformLocation(program, 'u_density')
}
};
}
function createGradiantShader (ctx) {
var program = createProgram(ctx, GradShaders);
return {
program: program,
attr: [{
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_position'),
data: new Float32Array([])
}, {
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 1,
attribute: ctx.getAttribLocation(program, 'a_intensity'),
data: new Float32Array([])
}],
uniform: {
u_resolution: ctx.getUniformLocation(program, 'u_resolution'),
u_max: ctx.getUniformLocation(program, 'u_max'),
u_min: ctx.getUniformLocation(program, 'u_min'),
u_size: ctx.getUniformLocation(program, 'u_size'),
u_intensity: ctx.getUniformLocation(program, 'u_intensity'),
u_translate: ctx.getUniformLocation(program, 'u_translate'),
u_zoom: ctx.getUniformLocation(program, 'u_zoom'),
u_angle: ctx.getUniformLocation(program, 'u_angle'),
u_density: ctx.getUniformLocation(program, 'u_density')
}
};
}
function createColorShader (ctx) {
var program = createProgram(ctx, ColorShader);
return {
program: program,
attr: [{
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_texCoord'),
data: new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0])
}],
uniform: {
u_framebuffer: ctx.getUniformLocation(program, 'u_framebuffer'),
u_colorArr: ctx.getUniformLocation(program, 'u_colorArr'),
u_colorCount: ctx.getUniformLocation(program, 'u_colorCount'),
u_opacity: ctx.getUniformLocation(program, 'u_opacity'),
u_offset: ctx.getUniformLocation(program, 'u_offset')
}
};
}
function extractData (data) {
const len = data.length;
if (pLen !== len) {
buffer = new ArrayBuffer(len * 8);
posVec = new Float32Array(buffer);
buffer2 = new ArrayBuffer(len * 4);
rVec = new Float32Array(buffer2);
pLen = len;
}
const dataMinMaxValue = {
min: Infinity,
max: -Infinity
};
for (let i = 0; i < len; i++) {
posVec[i * 2] = data[i].x;
posVec[(i * 2) + 1] = data[i].y;
rVec[i] = data[i].value;
if (dataMinMaxValue.min > data[i].value) {
dataMinMaxValue.min = data[i].value;
}
if (dataMinMaxValue.max < data[i].value) {
dataMinMaxValue.max = data[i].value;
}
}
return {
posVec: posVec,
rVec: rVec,
minMax: dataMinMaxValue
};
}
function Chart (context, config) {
try {
let res;
if (typeof context === 'string') {
res = document.querySelector(context);
} else if (context instanceof Element) {
res = context;
} else {
throw new Error('Context must be either a string or an Element');
}
const height = res.clientHeight;
const width = res.clientWidth;
const layer = document.createElement('canvas');
const ctx = layer.getContext('webgl2', {
premultipliedAlpha: false,
depth: false,
antialias: true,
alpha: true,
preserveDrawingBuffer: false
});
ratio = getPixlRatio(ctx);
ctx.clearColor(0, 0, 0, 0);
ctx.enable(ctx.BLEND);
ctx.blendEquation(ctx.FUNC_ADD);
ctx.blendFunc(ctx.ONE, ctx.ONE_MINUS_SRC_ALPHA);
ctx.depthMask(true);
layer.setAttribute('height', height * ratio);
layer.setAttribute('width', width * ratio);
layer.style.height = `${height}px`;
layer.style.width = `${width}px`;
layer.style.position = 'absolute';
res.appendChild(layer);
this.ctx = ctx;
this.width = width;
this.height = height;
this.layer = layer;
this.dom = res;
this.gradShadOP = createGradiantShader(this.ctx);
this.colorShadOP = createColorShader(this.ctx);
this.imageShaOP = createImageShader(this.ctx);
this.fbTexObj = ctx.createTexture();
this.fbo = ctx.createFramebuffer();
if (!isNullUndefined(config.size)) {
this.setSize(config.size);
} else {
this.size = 20.0;
}
if (!isNullUndefined(config.max)) {
this.setMax(config.max);
} else {
configMax = null;
}
if (!isNullUndefined(config.min)) {
this.setMin(config.min);
} else {
configMin = null;
}
if (!isNullUndefined(config.intensity)) {
this.setIntensity(config.intensity);
} else {
this.intensity = 1.0;
}
if (!isNullUndefined(config.translate)) {
this.setTranslate(config.translate);
} else {
this.translate = [0, 0];
}
if (!isNullUndefined(config.zoom)) {
this.setZoom(config.zoom);
} else {
this.zoom = 1.0;
}
if (!isNullUndefined(config.angle)) {
this.setRotationAngle(config.angle);
} else {
this.angle = 0.0;
}
if (!isNullUndefined(config.opacity)) {
this.setOpacity(config.opacity);
} else {
this.opacity = 1.0;
}
this.gradient = gradientMapper(config.gradient);
this.ratio = ratio;
if (config.backgroundImage && config.backgroundImage.url) {
this.setBackgroundImage(config.backgroundImage);
}
this.heatmapData = [];
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
} catch (error) {
console.error(error);
}
}
Chart.prototype.resize = function () {
const height = this.dom.clientHeight;
const width = this.dom.clientWidth;
this.layer.setAttribute('height', height * ratio);
this.layer.setAttribute('width', width * ratio);
this.layer.style.height = `${height}px`;
this.layer.style.width = `${width}px`;
this.width = width;
this.height = height;
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
/* Perform update */
this.render(hearmapExData);
};
Chart.prototype.clear = function () {
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
};
Chart.prototype.setMax = function (max) {
if (isNullUndefined(max) || isNotNumber(max)) {
throw new Error('Invalid max: Expected Number');
}
configMax = max;
return this;
};
Chart.prototype.setMin = function (min) {
if (isNullUndefined(min) || isNotNumber(min)) {
throw new Error('Invalid min: Expected Number');
}
configMin = min;
return this;
};
Chart.prototype.setGradient = function (gradient) {
this.gradient = gradientMapper(gradient);
return this;
};
Chart.prototype.setTranslate = function (translate) {
if (translate.constructor !== Array) {
throw new Error('Invalid Translate: Translate has to be of Array type');
}
if (translate.length !== 2) {
throw new Error('Translate has to be of length 2');
}
this.translate = translate;
return this;
};
Chart.prototype.setZoom = function (zoom) {
if (isNullUndefined(zoom) || isNotNumber(zoom)) {
throw new Error('Invalid zoom: Expected Number');
}
this.zoom = zoom;
return this;
};
Chart.prototype.setRotationAngle = function (angle) {
if (isNullUndefined(angle) || isNotNumber(angle)) {
throw new Error('Invalid Angle: Expected Number');
}
this.angle = angle;
return this;
};
Chart.prototype.setSize = function (size) {
if (isNullUndefined(size) || isNotNumber(size)) {
throw new Error('Invalid Size: Expected Number');
}
this.size = size;
return this;
};
Chart.prototype.setIntensity = function (intensity) {
if (isNullUndefined(intensity) || isNotNumber(intensity)) {
this.intensity = 1.0; // applying default intensity
throw new Error('Invalid Intensity: Expected Number');
}
if (intensity > 1 || intensity < 0) {
this.intensity = intensity > 1 ? 1 : 0; // Setting bound value
throw new Error('Invalid Intensity value ' + intensity);
}
this.intensity = intensity;
return this;
};
Chart.prototype.setOpacity = function (opacity) {
if (isNullUndefined(opacity) || isNotNumber(opacity)) {
throw new Error('Invalid Opacity: Expected Number');
}
if (opacity > 1 || opacity < 0) {
throw new Error('Invalid Opacity value ' + opacity);
}
this.opacity = opacity;
return this;
};
Chart.prototype.setBackgroundImage = function (config) {
const self = this;
if (!config.url) {
return;
}
maxTextureSize = this.ctx.getParameter(this.ctx.MAX_TEXTURE_SIZE);
this.imageTexture = this.ctx.createTexture();
this.type = 'TEXTURE_2D';
imageConfig = null;
imgWidth = config.width || this.width;
imgHeight = config.height || this.height;
imgWidth = imgWidth > maxTextureSize ? maxTextureSize : imgWidth;
imgHeight = imgHeight > maxTextureSize ? maxTextureSize : imgHeight;
imageInstance(config.url, function onUpdateCallBack () {
self.ctx.activeTexture(self.ctx.TEXTURE0);
self.ctx.bindTexture(self.ctx.TEXTURE_2D, self.imageTexture);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_S, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_T, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MIN_FILTER, self.ctx.LINEAR);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MAG_FILTER, self.ctx.LINEAR);
self.ctx.texImage2D(
self.ctx.TEXTURE_2D,
0,
self.ctx.RGBA,
this.naturalWidth,
this.naturalHeight,
0,
self.ctx.RGBA,
self.ctx.UNSIGNED_BYTE,
this
);
imageConfig = {
x: config.x || 0,
y: config.y || 0,
height: imgHeight,
width: imgWidth,
image: this
};
self.render();
}, function onErrorCallBack (error) {
throw new Error('Image Load Error', error);
});
return this;
};
Chart.prototype.clearData = function () {
this.heatmapData = [];
hearmapExData = {};
this.render();
};
Chart.prototype.addData = function (data, transIntactFlag) {
const self = this;
for (let i = 0; i < data.length; i++) {
if (transIntactFlag) {
transCoOr.call(self, data[i]);
}
this.heatmapData.push(data[i]);
}
this.renderData(this.heatmapData);
return this;
};
Chart.prototype.renderData = function (data) {
if (data.constructor !== Array) {
throw new Error('Expected Array type');
}
hearmapExData = extractData(data);
this.heatmapData = data;
this.render();
return this;
};
Chart.prototype.render = function () {
renderExec.call(this);
};
Chart.prototype.projection = function (data) {
// Pre-compute constants and repetitive calculations
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const translateX = this.translate[0];
const translateY = this.translate[1];
const angle = this.angle;
const aspect = this.width / this.height;
// Calculate the adjusted positions
let posX = (data.x + translateX - halfWidth) / (halfWidth * zoomFactor);
let posY = (data.y + translateY - halfHeight) / (halfHeight * zoomFactor);
posX *= aspect;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(-angle);
const sinAngle = Math.sin(-angle);
const xNew = (cosAngle * posX) - (sinAngle * posY);
posY = (sinAngle * posX) + (cosAngle * posY);
posX = xNew;
}
posX *= 1.0 / aspect;
// Scale back and adjust the position
posX = (posX * halfWidth) + halfWidth;
posY = (posY * halfHeight) + halfHeight;
return { x: posX, y: posY };
};
function renderExec () {
const ctx = this.ctx;
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);
ctx.bindTexture(ctx.TEXTURE_2D, this.fbTexObj);
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, this.width * this.ratio, this.height * this.ratio, 0, ctx.RGBA, ctx.UNSIGNED_BYTE, null);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR);
ctx.bindFramebuffer(ctx.FRAMEBUFFER, this.fbo);
ctx.framebufferTexture2D(ctx.FRAMEBUFFER, ctx.COLOR_ATTACHMENT0, ctx.TEXTURE_2D, this.fbTexObj, 0);
if (hearmapExData) {
renderHeatGrad.call(this, ctx, hearmapExData);
}
ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
if (imageConfig) {
renderImage.call(this, ctx, imageConfig);
}
renderColorGradiant.call(this, ctx);
}
function renderHeatGrad (ctx, exData) {
ctx.useProgram(this.gradShadOP.program);
this.min = configMin !== null ? configMin : exData?.minMax?.min ?? 0;
this.max = configMax !== null ? configMax : exData?.minMax?.max ?? 0;
this.gradShadOP.attr[0].data = exData.posVec || [];
this.gradShadOP.attr[1].data = exData.rVec || [];
ctx.uniform2fv(this.gradShadOP.uniform.u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(this.gradShadOP.uniform.u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(this.gradShadOP.uniform.u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(this.gradShadOP.uniform.u_angle, this.angle);
ctx.uniform1f(this.gradShadOP.uniform.u_density, this.ratio);
ctx.uniform1f(this.gradShadOP.uniform.u_max, this.max);
ctx.uniform1f(this.gradShadOP.uniform.u_min, this.min);
ctx.uniform1f(this.gradShadOP.uniform.u_size, this.size);
ctx.uniform1f(this.gradShadOP.uniform.u_intensity, this.intensity);
this.gradShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.drawArrays(ctx.POINTS, 0, (exData.posVec || []).length / 2);
}
function renderImage (ctx, imageConfig) {
const { x = 0, y = 0, width = 0, height = 0 } = imageConfig;
ctx.useProgram(this.imageShaOP.program);
ctx.uniform2fv(this.imageShaOP.uniform.u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(this.imageShaOP.uniform.u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(this.imageShaOP.uniform.u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(this.imageShaOP.uniform.u_angle, this.angle);
ctx.uniform1f(this.imageShaOP.uniform.u_density, this.ratio);
this.imageShaOP.attr[0].data = new Float32Array([x, y, x + width, y, x, y + height, x, y + height, x + width, y, x + width, y + height]);
this.imageShaOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(this.imageShaOP.uniform.u_image, 0);
ctx.activeTexture(this.ctx.TEXTURE0);
ctx.bindTexture(this.ctx.TEXTURE_2D, this.imageTexture);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function renderColorGradiant (ctx) {
ctx.useProgram(this.colorShadOP.program);
ctx.uniform4fv(this.colorShadOP.uniform.u_colorArr, this.gradient.value);
ctx.uniform1f(this.colorShadOP.uniform.u_colorCount, this.gradient.length);
ctx.uniform1fv(this.colorShadOP.uniform.u_offset, new Float32Array(this.gradient.offset));
ctx.uniform1f(this.colorShadOP.uniform.u_opacity, this.opacity);
this.colorShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(this.colorShadOP.uniform.u_framebuffer, 0);
ctx.activeTexture(ctx.TEXTURE0);
ctx.bindTexture(ctx.TEXTURE_2D, this.fbTexObj);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function transCoOr (data) {
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const angle = this.angle;
// Combine operations to reduce the number of arithmetic steps
let posX = (data.x - halfWidth) / halfWidth * zoomFactor;
let posY = (data.y - halfHeight) / halfHeight * zoomFactor;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(angle);
const sinAngle = Math.sin(angle);
const xNew = (cosAngle * posX) - (sinAngle * posY);
posY = (sinAngle * posX) + (cosAngle * posY);
posX = xNew;
}
// Scale back and adjust the position
posX = (posX * halfWidth) + halfWidth - this.translate[0];
posY = (posY * halfHeight) + halfHeight - this.translate[1];
data.x = posX;
data.y = posY;
return { x: posX, y: posY };
}
function imageInstance (url, onLoad, onError) {
const imageIns = new Image();
imageIns.crossOrigin = 'anonymous';
imageIns.onload = onLoad;
imageIns.onerror = onError;
imageIns.src = url;
return imageIns;
}
return new Chart(context, config);
}
function getPixlRatio (ctx) {
const dpr = window.devicePixelRatio || 1;
const bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
}
var GradShaders = {
vertex: `#version 300 es
const GradShader = {
vertex: `#version 300 es
in vec2 a_position;

@@ -743,3 +38,3 @@ in float a_intensity;

}`,
fragment: `#version 300 es
fragment: `#version 300 es
precision mediump float;

@@ -759,7 +54,6 @@ uniform float u_max;

}
}`
}`,
};
var ColorShader = {
vertex: `#version 300 es
const ColorShader = {
vertex: `#version 300 es
precision highp float;

@@ -774,3 +68,3 @@ in vec2 a_texCoord;

`,
fragment: `#version 300 es
fragment: `#version 300 es
precision mediump float;

@@ -816,7 +110,6 @@ in vec2 v_texCoord;

}
`
`,
};
var imageShaders = {
vertex: `#version 300 es
const ImageShader = {
vertex: `#version 300 es
precision highp float;

@@ -856,3 +149,3 @@ in vec2 a_position;

`,
fragment: `#version 300 es
fragment: `#version 300 es
precision mediump float;

@@ -865,5 +158,762 @@ uniform sampler2D u_image;

}
`
`,
};
export { Heatmap as default };
function createShader(ctx, type, src) {
const shader = ctx.createShader(ctx[type]);
if (!shader) {
throw new Error("Failed to create shader.");
}
ctx.shaderSource(shader, src);
ctx.compileShader(shader);
const compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
if (!compiled) {
const lastError = ctx.getShaderInfoLog(shader);
ctx.deleteShader(shader);
throw new Error("*** Error compiling shader '" + shader + "':" + lastError);
}
return shader;
}
function createProgram(ctx, shader) {
const vshader = createShader(ctx, "VERTEX_SHADER", shader.vertex);
const fshader = createShader(ctx, "FRAGMENT_SHADER", shader.fragment);
const program = ctx.createProgram();
if (!program) {
throw new Error("Failed to create program.");
}
ctx.attachShader(program, vshader);
ctx.attachShader(program, fshader);
ctx.linkProgram(program);
const linked = ctx.getProgramParameter(program, ctx.LINK_STATUS);
if (!linked) {
const lastError = ctx.getProgramInfoLog(program);
ctx.deleteProgram(program);
throw new Error("Error in program linking:" + lastError);
}
else {
return program;
}
}
const createImageShader = function (ctx, shader) {
const program = createProgram(ctx, shader);
const positionBuffer = ctx.createBuffer();
if (!positionBuffer) {
throw new Error("Failed to create position buffer.");
}
const texCoordBuffer = ctx.createBuffer();
if (!texCoordBuffer) {
throw new Error("Failed to create texture coordinate buffer.");
}
return {
program: program,
attr: [
{
bufferType: ctx.ARRAY_BUFFER,
buffer: positionBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_position"),
data: new Float32Array([]),
},
{
bufferType: ctx.ARRAY_BUFFER,
buffer: texCoordBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_texCoord"),
data: new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0,
]),
},
],
uniform: {
u_resolution: ctx.getUniformLocation(program, "u_resolution"),
u_image: ctx.getUniformLocation(program, "u_image"),
u_translate: ctx.getUniformLocation(program, "u_translate"),
u_zoom: ctx.getUniformLocation(program, "u_zoom"),
u_angle: ctx.getUniformLocation(program, "u_angle"),
u_density: ctx.getUniformLocation(program, "u_density"),
},
};
};
const createGradiantShader = function (ctx, shader) {
const program = createProgram(ctx, shader);
const positionBuffer = ctx.createBuffer();
if (!positionBuffer) {
throw new Error("Failed to create position buffer.");
}
const intensityBuffer = ctx.createBuffer();
if (!intensityBuffer) {
throw new Error("Failed to create intensity buffer.");
}
return {
program: program,
attr: [
{
bufferType: ctx.ARRAY_BUFFER,
buffer: positionBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_position"),
data: new Float32Array([]),
},
{
bufferType: ctx.ARRAY_BUFFER,
buffer: intensityBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 1,
attribute: ctx.getAttribLocation(program, "a_intensity"),
data: new Float32Array([]),
},
],
uniform: {
u_resolution: ctx.getUniformLocation(program, "u_resolution"),
u_max: ctx.getUniformLocation(program, "u_max"),
u_min: ctx.getUniformLocation(program, "u_min"),
u_size: ctx.getUniformLocation(program, "u_size"),
u_intensity: ctx.getUniformLocation(program, "u_intensity"),
u_translate: ctx.getUniformLocation(program, "u_translate"),
u_zoom: ctx.getUniformLocation(program, "u_zoom"),
u_angle: ctx.getUniformLocation(program, "u_angle"),
u_density: ctx.getUniformLocation(program, "u_density"),
},
};
};
const createColorShader = function (ctx, shader) {
const program = createProgram(ctx, shader);
const texCoordBuffer = ctx.createBuffer();
if (!texCoordBuffer) {
throw new Error("Failed to create texture coordinate buffer.");
}
return {
program: program,
attr: [
{
bufferType: ctx.ARRAY_BUFFER,
buffer: texCoordBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_texCoord"),
data: new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0,
]),
},
],
uniform: {
u_framebuffer: ctx.getUniformLocation(program, "u_framebuffer"),
u_colorArr: ctx.getUniformLocation(program, "u_colorArr"),
u_colorCount: ctx.getUniformLocation(program, "u_colorCount"),
u_opacity: ctx.getUniformLocation(program, "u_opacity"),
u_offset: ctx.getUniformLocation(program, "u_offset"),
},
};
};
function isNullUndefined(val) {
return val === null || val === undefined;
}
function isNotNumber(val) {
return typeof val !== "number";
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isSortedAscending(arr) {
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i + 1].offset - arr[i].offset < 0) {
return false;
}
}
return true;
}
/** @see https://codereview.chromium.org/156833002/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getPixelRatio(ctx) {
const dpr = window.devicePixelRatio || 1;
const bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
return dpr / bsr;
}
function gradientMapper(grad) {
if (!Array.isArray(grad) || grad.length < 2) {
throw new Error("Invalid gradient: Expected an array with at least 2 elements.");
}
if (!isSortedAscending(grad)) {
throw new Error("Invalid gradient: Gradient is not sorted");
}
const gradLength = grad.length;
const values = new Float32Array(gradLength * 4);
const offsets = new Array(gradLength);
grad.forEach(function (d, i) {
const baseIndex = i * 4;
values[baseIndex] = d.color[0] / 255;
values[baseIndex + 1] = d.color[1] / 255;
values[baseIndex + 2] = d.color[2] / 255;
values[baseIndex + 3] = d.color[3] !== undefined ? d.color[3] : 1.0;
offsets[i] = d.offset;
});
return {
value: values,
length: gradLength,
offset: offsets,
};
}
function extractData(data) {
const self = this;
const len = data.length;
let { posVec = new Float32Array(), rVec = new Float32Array() } = (self.hearmapExData || {});
if (self._pDataLength !== len) {
posVec = new Float32Array(new ArrayBuffer(len * 8));
rVec = new Float32Array(new ArrayBuffer(len * 4));
self._pDataLength = len;
}
const dataMinMaxValue = {
min: Infinity,
max: -Infinity,
};
for (let i = 0; i < len; i++) {
posVec[i * 2] = data[i].x;
posVec[i * 2 + 1] = data[i].y;
rVec[i] = data[i].value;
if (dataMinMaxValue.min > data[i].value) {
dataMinMaxValue.min = data[i].value;
}
if (dataMinMaxValue.max < data[i].value) {
dataMinMaxValue.max = data[i].value;
}
}
return {
posVec: posVec,
rVec: rVec,
minMax: dataMinMaxValue,
};
}
function transCoOr(data) {
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const { angle, translate } = this;
// Combine operations to reduce the number of arithmetic steps
let posX = ((data.x - halfWidth) / halfWidth) * zoomFactor;
let posY = ((data.y - halfHeight) / halfHeight) * zoomFactor;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(angle);
const sinAngle = Math.sin(angle);
posY = sinAngle * posX + cosAngle * posY;
posX = cosAngle * posX - sinAngle * posY;
}
// Scale back and adjust the position
posX = posX * halfWidth + halfWidth - translate[0];
posY = posY * halfHeight + halfHeight - translate[1];
data.x = posX;
data.y = posY;
return { x: posX, y: posY };
}
function renderExec() {
const ctx = this.ctx;
if (!ctx) {
return;
}
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);
ctx.bindTexture(ctx.TEXTURE_2D, this._fbTexObj);
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, this.width * this.ratio, this.height * this.ratio, 0, ctx.RGBA, ctx.UNSIGNED_BYTE, null);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR);
ctx.bindFramebuffer(ctx.FRAMEBUFFER, this._fbo);
ctx.framebufferTexture2D(ctx.FRAMEBUFFER, ctx.COLOR_ATTACHMENT0, ctx.TEXTURE_2D, this._fbTexObj, 0);
if (this.hearmapExData) {
renderHeatGrad.call(this, ctx, this.hearmapExData);
}
ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
if (this.imageConfig) {
renderImage.call(this, ctx, this.imageConfig);
}
renderColorGradiant.call(this, ctx);
}
function renderHeatGrad(ctx, exData) {
var _a, _b, _c, _d;
ctx.useProgram(this._gradShadOP.program);
const { u_resolution, u_translate, u_zoom, u_angle, u_density, u_max, u_min, u_size, u_intensity } = this._gradShadOP.uniform;
this.min =
this.configMin !== null ? this.configMin : (_b = (_a = exData === null || exData === void 0 ? void 0 : exData.minMax) === null || _a === void 0 ? void 0 : _a.min) !== null && _b !== void 0 ? _b : 0;
this.max =
this.configMax !== null ? this.configMax : (_d = (_c = exData === null || exData === void 0 ? void 0 : exData.minMax) === null || _c === void 0 ? void 0 : _c.max) !== null && _d !== void 0 ? _d : 0;
this._gradShadOP.attr[0].data = exData.posVec || [];
this._gradShadOP.attr[1].data = exData.rVec || [];
ctx.uniform2fv(u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(u_angle, this.angle);
ctx.uniform1f(u_density, this.ratio);
ctx.uniform1f(u_max, this.max);
ctx.uniform1f(u_min, this.min);
ctx.uniform1f(u_size, this.size);
ctx.uniform1f(u_intensity, this.intensity);
this._gradShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.drawArrays(ctx.POINTS, 0, (exData.posVec || []).length / 2);
}
function renderImage(ctx, imageConfig) {
const { x = 0, y = 0, width = 0, height = 0 } = imageConfig;
const { u_resolution, u_translate, u_zoom, u_angle, u_density, u_image } = this._imageShaOP.uniform;
ctx.useProgram(this._imageShaOP.program);
ctx.uniform2fv(u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(u_angle, this.angle);
ctx.uniform1f(u_density, this.ratio);
this._imageShaOP.attr[0].data = new Float32Array([
x,
y,
x + width,
y,
x,
y + height,
x,
y + height,
x + width,
y,
x + width,
y + height,
]);
this._imageShaOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(u_image, 0);
ctx.activeTexture(this.ctx.TEXTURE0);
ctx.bindTexture(this.ctx.TEXTURE_2D, this._imageTexture);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function renderColorGradiant(ctx) {
const { u_colorArr, u_colorCount, u_offset, u_opacity, u_framebuffer } = this._colorShadOP.uniform;
ctx.useProgram(this._colorShadOP.program);
ctx.uniform4fv(u_colorArr, this.gradient.value);
ctx.uniform1f(u_colorCount, this.gradient.length);
ctx.uniform1fv(u_offset, new Float32Array(this.gradient.offset));
ctx.uniform1f(u_opacity, this.opacity);
this._colorShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(u_framebuffer, 0);
ctx.activeTexture(ctx.TEXTURE0);
ctx.bindTexture(ctx.TEXTURE_2D, this._fbTexObj);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function imageInstance(url, onLoad, onError) {
const imageIns = new Image();
imageIns.crossOrigin = "anonymous";
imageIns.onload = onLoad;
imageIns.onerror = onError;
imageIns.src = url;
return imageIns;
}
class HeatmapRenderer {
constructor(container, config) {
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 = undefined;
this.imgWidth = 0;
this.imgHeight = 0;
this.heatmapData = [];
this.type = "";
try {
const res = typeof container === "string"
? document.querySelector(container)
: container instanceof HTMLElement
? container
: null;
if (!res) {
throw new Error("Context must be either a string or an Element");
}
const { clientHeight: height, clientWidth: width } = res;
const layer = document.createElement("canvas");
const ctx = layer.getContext("webgl2", {
premultipliedAlpha: false,
depth: false,
antialias: true,
alpha: true,
preserveDrawingBuffer: false,
});
this.ratio = getPixelRatio(ctx);
ctx.clearColor(0, 0, 0, 0);
ctx.enable(ctx.BLEND);
ctx.blendEquation(ctx.FUNC_ADD);
ctx.blendFunc(ctx.ONE, ctx.ONE_MINUS_SRC_ALPHA);
ctx.depthMask(true);
layer.setAttribute("height", (height * this.ratio).toString());
layer.setAttribute("width", (width * this.ratio).toString());
layer.style.height = `${height}px`;
layer.style.width = `${width}px`;
layer.style.position = "absolute";
res.appendChild(layer);
this.ctx = ctx;
this.width = width;
this.height = height;
this.imageConfig = null;
this.configMin = null;
this.configMax = null;
this.hearmapExData = {};
this.layer = layer;
this.dom = res;
this._gradShadOP = createGradiantShader(this.ctx, GradShader);
this._colorShadOP = createColorShader(this.ctx, ColorShader);
this._imageShaOP = createImageShader(this.ctx, ImageShader);
this._fbTexObj = ctx.createTexture();
this._fbo = ctx.createFramebuffer();
if (!isNullUndefined(config.size)) {
this.setSize(config.size);
}
else {
this.size = 20.0;
}
if (!isNullUndefined(config.max)) {
this.setMax(config.max);
}
else {
this.configMax = null;
}
if (!isNullUndefined(config.min)) {
this.setMin(config.min);
}
else {
this.configMin = null;
}
if (!isNullUndefined(config.intensity)) {
this.setIntensity(config.intensity);
}
else {
this.intensity = 1.0;
}
if (!isNullUndefined(config.translate)) {
this.setTranslate(config.translate);
}
else {
this.translate = [0, 0];
}
if (!isNullUndefined(config.zoom)) {
this.setZoom(config.zoom);
}
else {
this.zoom = 1.0;
}
if (!isNullUndefined(config.angle)) {
this.setRotationAngle(config.angle);
}
else {
this.angle = 0.0;
}
if (!isNullUndefined(config.opacity)) {
this.setOpacity(config.opacity);
}
else {
this.opacity = 1.0;
}
this.gradient = gradientMapper(config.gradient);
if (config.backgroundImage && config.backgroundImage.url) {
this.setBackgroundImage(config.backgroundImage);
}
this.heatmapData = [];
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
}
catch (error) {
console.error(error);
}
}
/**
* Invoke resize method on container resize.
*/
resize() {
const height = this.dom.clientHeight;
const width = this.dom.clientWidth;
this.layer.setAttribute("height", (height * this.ratio).toString());
this.layer.setAttribute("width", (width * this.ratio).toString());
this.layer.style.height = `${height}px`;
this.layer.style.width = `${width}px`;
this.width = width;
this.height = height;
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
/* Perform update */
this.render();
}
clear() {
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
}
/**
* Set the maximum data value for relative gradient calculations
* @param max - number
* @returns instance
*/
setMax(max) {
if (isNullUndefined(max) || isNotNumber(max)) {
throw new Error("Invalid max: Expected Number");
}
this.configMax = max;
return this;
}
/**
* Set the minimum data value for relative gradient calculations
* @param min - number
* @returns instance
*/
setMin(min) {
if (isNullUndefined(min) || isNotNumber(min)) {
throw new Error("Invalid min: Expected Number");
}
this.configMin = min;
return this;
}
/**
* Accepts array of objects with color value and offset
* @param gradient - Color Gradient
* @returns instance
*/
setGradient(gradient) {
this.gradient = gradientMapper(gradient);
return this;
}
/**
* Set the translate on the Heatmap
* @param translate - Accepts array [x, y]
* @returns instance
*/
setTranslate(translate) {
if (translate.constructor !== Array) {
throw new Error("Invalid Translate: Translate has to be of Array type");
}
if (translate.length !== 2) {
throw new Error("Translate has to be of length 2");
}
this.translate = translate;
return this;
}
/**
* Set the zoom transformation on the Heatmap
* @param zoom - Accepts float value
* @returns instance
*/
setZoom(zoom) {
if (isNullUndefined(zoom) || isNotNumber(zoom)) {
throw new Error("Invalid zoom: Expected Number");
}
this.zoom = zoom;
return this;
}
/**
* Set the rotation transformation on the Heatmap
* @param angle - Accepts angle in radians
* @returns instance
*/
setRotationAngle(angle) {
if (isNullUndefined(angle) || isNotNumber(angle)) {
throw new Error("Invalid Angle: Expected Number");
}
this.angle = angle;
return this;
}
/**
* Set the point radius
* @param size - Accepts float value
* @returns instance
*/
setSize(size) {
if (isNullUndefined(size) || isNotNumber(size)) {
throw new Error("Invalid Size: Expected Number");
}
this.size = size;
return this;
}
/**
* Set the intensity factor
* @param intensity - Accepts float value
* @returns instance
*/
setIntensity(intensity) {
if (isNullUndefined(intensity) || isNotNumber(intensity)) {
this.intensity = 1.0; // applying default intensity
throw new Error("Invalid Intensity: Expected Number");
}
if (intensity > 1 || intensity < 0) {
this.intensity = intensity > 1 ? 1 : 0; // Setting bound value
throw new Error("Invalid Intensity value " + intensity);
}
this.intensity = intensity;
return this;
}
/**
* Set the opacity factor
* @param opacity - The opacity factor.
* @returns instance
*/
setOpacity(opacity) {
if (isNullUndefined(opacity) || isNotNumber(opacity)) {
throw new Error("Invalid Opacity: Expected Number");
}
if (opacity > 1 || opacity < 0) {
throw new Error("Invalid Opacity value " + opacity);
}
this.opacity = opacity;
return this;
}
/**
* Set the background image
* @param config - Accepts Object with { url, height, width, x, and y} properties
* @returns instance
*/
setBackgroundImage(config) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
if (!config.url) {
return;
}
const maxTextureSize = this.ctx.getParameter(this.ctx.MAX_TEXTURE_SIZE);
this._imageTexture = this.ctx.createTexture();
this.type = "TEXTURE_2D";
this.imageConfig = null;
this.imgWidth = config.width || this.width;
this.imgHeight = config.height || this.height;
this.imgWidth =
this.imgWidth > maxTextureSize ? maxTextureSize : this.imgWidth;
this.imgHeight =
this.imgHeight > maxTextureSize ? maxTextureSize : this.imgHeight;
imageInstance(config.url, function onUpdateCallBack() {
self.ctx.activeTexture(self.ctx.TEXTURE0);
self.ctx.bindTexture(self.ctx.TEXTURE_2D, self._imageTexture);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_S, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_T, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MIN_FILTER, self.ctx.LINEAR);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MAG_FILTER, self.ctx.LINEAR);
self.ctx.texImage2D(self.ctx.TEXTURE_2D, 0, self.ctx.RGBA, this.naturalWidth, this.naturalHeight, 0, self.ctx.RGBA, self.ctx.UNSIGNED_BYTE, this);
self.imageConfig = {
x: config.x || 0,
y: config.y || 0,
height: self.imgHeight,
width: self.imgWidth,
image: this,
};
self.render();
}, function onErrorCallBack(error) {
throw new Error(`Image Load Error, ${error}`);
});
return this;
}
/**
* Clear heatmap
*/
clearData() {
this.heatmapData = [];
this.hearmapExData = {};
this.render();
}
/**
* Method to append data points. This method automatically adds new data points to the existing dataset and the heatmap updates in immediately. no need to call the ".render" method separately.
* @param data - The data points with 'x', 'y' and 'value'
* @param transIntactFlag - Flag indicating whether to apply existing heatmap transformations on the newly added data points
* @returns instance
*/
addData(data, transIntactFlag) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
for (let i = 0; i < data.length; i++) {
if (transIntactFlag) {
transCoOr.call(self, data[i]);
}
this.heatmapData.push(data[i]);
}
this.renderData(this.heatmapData);
return this;
}
/**
* Method to load data. This will override any existing data.
* @param data - Accepts an array of data points with 'x', 'y' and 'value'
* @returns instance
*/
renderData(data) {
if (data.constructor !== Array) {
throw new Error("Expected Array type");
}
this.hearmapExData = extractData.call(this, data);
this.heatmapData = data;
this.render();
return this;
}
/**
* Method to update the heatmap. This method to be invoked on every change in configuration.
*/
render() {
renderExec.call(this);
}
/**
* Get projected co-ordinates relative to the heatmap
* @param data - The data point to project.
* @returns projected data point.
*/
projection(data) {
// Pre-compute constants and repetitive calculations
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const translateX = this.translate[0];
const translateY = this.translate[1];
const angle = this.angle;
const aspect = this.width / this.height;
// Calculate the adjusted positions
let posX = (data.x + translateX - halfWidth) / (halfWidth * zoomFactor);
let posY = (data.y + translateY - halfHeight) / (halfHeight * zoomFactor);
posX *= aspect;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(-angle);
const sinAngle = Math.sin(-angle);
const xNew = cosAngle * posX - sinAngle * posY;
posY = sinAngle * posX + cosAngle * posY;
posX = xNew;
}
posX *= 1.0 / aspect;
// Scale back and adjust the position
posX = posX * halfWidth + halfWidth;
posY = posY * halfHeight + halfHeight;
return { x: posX, y: posY };
}
}
function main (context, config) {
return new HeatmapRenderer(context, config);
}
export { main as default };

@@ -6,2 +6,2 @@ /*!

*/
function t(t,i={}){let n,a,s,u,f,h,c,l=[],m=[],_=0,d=null,g=0,T=0;function p(t){return null==t}function x(t){return"number"!=typeof t}function y(t){if(t.constructor!==Array)throw new Error("Invalid gradient: Wrong Gradient type, expected Array");if(t.length<2)throw new Error("Invalid gradient: 2 or more values expected");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,r=new Float32Array(4*e),o=new Array(e);return t.forEach((function(t,e){const i=4*e;r[i]=t.color[0]/255,r[i+1]=t.color[1]/255,r[i+2]=t.color[2]/255,r[i+3]=void 0!==t.color[3]?t.color[3]:1,o[e]=t.offset})),{value:r,length:e,offset:o}}function E(t,e,r){var o=t.createShader(t[e]);if(t.shaderSource(o,r),t.compileShader(o),!t.getShaderParameter(o,t.COMPILE_STATUS)){var i=t.getShaderInfoLog(o);throw t.deleteShader(o),new Error("*** Error compiling shader '"+o+"':"+i)}return o}function v(t,e){var r=E(t,"VERTEX_SHADER",e.vertex),o=E(t,"FRAGMENT_SHADER",e.fragment),i=t.createProgram();if(t.attachShader(i,r),t.attachShader(i,o),t.linkProgram(i),t.getProgramParameter(i,t.LINK_STATUS))return i;var n=t.getProgramInfoLog(i);throw t.deleteProgram(i),new Error("Error in program linking:"+n)}function A(t,i){try{let a;if("string"==typeof t)a=document.querySelector(t);else{if(!(t instanceof Element))throw new Error("Context must be either a string or an Element");a=t}const s=a.clientHeight,u=a.clientWidth,f=document.createElement("canvas"),h=f.getContext("webgl2",{premultipliedAlpha:!1,depth:!1,antialias:!0,alpha:!0,preserveDrawingBuffer:!1});n=function(t){const e=window.devicePixelRatio||1,r=t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1;return e/r}(h),h.clearColor(0,0,0,0),h.enable(h.BLEND),h.blendEquation(h.FUNC_ADD),h.blendFunc(h.ONE,h.ONE_MINUS_SRC_ALPHA),h.depthMask(!0),f.setAttribute("height",s*n),f.setAttribute("width",u*n),f.style.height=`${s}px`,f.style.width=`${u}px`,f.style.position="absolute",a.appendChild(f),this.ctx=h,this.width=u,this.height=s,this.layer=f,this.dom=a,this.gradShadOP=function(t){var r=v(t,e);return{program:r,attr:[{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(r,"a_position"),data:new Float32Array([])},{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:1,attribute:t.getAttribLocation(r,"a_intensity"),data:new Float32Array([])}],uniform:{u_resolution:t.getUniformLocation(r,"u_resolution"),u_max:t.getUniformLocation(r,"u_max"),u_min:t.getUniformLocation(r,"u_min"),u_size:t.getUniformLocation(r,"u_size"),u_intensity:t.getUniformLocation(r,"u_intensity"),u_translate:t.getUniformLocation(r,"u_translate"),u_zoom:t.getUniformLocation(r,"u_zoom"),u_angle:t.getUniformLocation(r,"u_angle"),u_density:t.getUniformLocation(r,"u_density")}}}(this.ctx),this.colorShadOP=function(t){var e=v(t,r);return{program:e,attr:[{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(e,"a_texCoord"),data:new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1])}],uniform:{u_framebuffer:t.getUniformLocation(e,"u_framebuffer"),u_colorArr:t.getUniformLocation(e,"u_colorArr"),u_colorCount:t.getUniformLocation(e,"u_colorCount"),u_opacity:t.getUniformLocation(e,"u_opacity"),u_offset:t.getUniformLocation(e,"u_offset")}}}(this.ctx),this.imageShaOP=function(t){var e=v(t,o);return{program:e,attr:[{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(e,"a_position"),data:new Float32Array([])},{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(e,"a_texCoord"),data:new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1])}],uniform:{u_resolution:t.getUniformLocation(e,"u_resolution"),u_image:t.getUniformLocation(e,"u_image"),u_translate:t.getUniformLocation(e,"u_translate"),u_zoom:t.getUniformLocation(e,"u_zoom"),u_angle:t.getUniformLocation(e,"u_angle"),u_density:t.getUniformLocation(e,"u_density")}}}(this.ctx),this.fbTexObj=h.createTexture(),this.fbo=h.createFramebuffer(),p(i.size)?this.size=20:this.setSize(i.size),p(i.max)?T=null:this.setMax(i.max),p(i.min)?g=null:this.setMin(i.min),p(i.intensity)?this.intensity=1:this.setIntensity(i.intensity),p(i.translate)?this.translate=[0,0]:this.setTranslate(i.translate),p(i.zoom)?this.zoom=1:this.setZoom(i.zoom),p(i.angle)?this.angle=0:this.setRotationAngle(i.angle),p(i.opacity)?this.opacity=1:this.setOpacity(i.opacity),this.gradient=y(i.gradient),this.ratio=n,i.backgroundImage&&i.backgroundImage.url&&this.setBackgroundImage(i.backgroundImage),this.heatmapData=[],this.ctx.viewport(0,0,this.ctx.canvas.width,this.ctx.canvas.height)}catch(t){console.error(t)}}function w(){const t=this.ctx;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),h&&b.call(this,t,h),t.bindFramebuffer(t.FRAMEBUFFER,null),c&&R.call(this,t,c),P.call(this,t)}function b(t,e){t.useProgram(this.gradShadOP.program),this.min=null!==g?g:e?.minMax?.min??0,this.max=null!==T?T:e?.minMax?.max??0,this.gradShadOP.attr[0].data=e.posVec||[],this.gradShadOP.attr[1].data=e.rVec||[],t.uniform2fv(this.gradShadOP.uniform.u_resolution,new Float32Array([this.width*this.ratio,this.height*this.ratio])),t.uniform2fv(this.gradShadOP.uniform.u_translate,new Float32Array([this.translate[0],this.translate[1]])),t.uniform1f(this.gradShadOP.uniform.u_zoom,this.zoom?this.zoom:.01),t.uniform1f(this.gradShadOP.uniform.u_angle,this.angle),t.uniform1f(this.gradShadOP.uniform.u_density,this.ratio),t.uniform1f(this.gradShadOP.uniform.u_max,this.max),t.uniform1f(this.gradShadOP.uniform.u_min,this.min),t.uniform1f(this.gradShadOP.uniform.u_size,this.size),t.uniform1f(this.gradShadOP.uniform.u_intensity,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 R(t,e){const{x:r=0,y:o=0,width:i=0,height:n=0}=e;t.useProgram(this.imageShaOP.program),t.uniform2fv(this.imageShaOP.uniform.u_resolution,new Float32Array([this.width*this.ratio,this.height*this.ratio])),t.uniform2fv(this.imageShaOP.uniform.u_translate,new Float32Array([this.translate[0],this.translate[1]])),t.uniform1f(this.imageShaOP.uniform.u_zoom,this.zoom?this.zoom:.01),t.uniform1f(this.imageShaOP.uniform.u_angle,this.angle),t.uniform1f(this.imageShaOP.uniform.u_density,this.ratio),this.imageShaOP.attr[0].data=new Float32Array([r,o,r+i,o,r,o+n,r,o+n,r+i,o,r+i,o+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(this.imageShaOP.uniform.u_image,0),t.activeTexture(this.ctx.TEXTURE0),t.bindTexture(this.ctx.TEXTURE_2D,this.imageTexture),t.drawArrays(t.TRIANGLES,0,6)}function P(t){t.useProgram(this.colorShadOP.program),t.uniform4fv(this.colorShadOP.uniform.u_colorArr,this.gradient.value),t.uniform1f(this.colorShadOP.uniform.u_colorCount,this.gradient.length),t.uniform1fv(this.colorShadOP.uniform.u_offset,new Float32Array(this.gradient.offset)),t.uniform1f(this.colorShadOP.uniform.u_opacity,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(this.colorShadOP.uniform.u_framebuffer,0),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.fbTexObj),t.drawArrays(t.TRIANGLES,0,6)}function S(t){const e=this.zoom||.1,r=this.width/2,o=this.height/2,i=this.angle;let n=(t.x-r)/r*e,a=(t.y-o)/o*e;if(0!==i){const t=Math.cos(i),e=Math.sin(i),r=t*n-e*a;a=e*n+t*a,n=r}return n=n*r+r-this.translate[0],a=a*o+o-this.translate[1],t.x=n,t.y=a,{x:n,y:a}}return A.prototype.resize=function(){const t=this.dom.clientHeight,e=this.dom.clientWidth;this.layer.setAttribute("height",t*n),this.layer.setAttribute("width",e*n),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(h)},A.prototype.clear=function(){this.ctx.clear(this.ctx.COLOR_BUFFER_BIT|this.ctx.DEPTH_BUFFER_BIT)},A.prototype.setMax=function(t){if(p(t)||x(t))throw new Error("Invalid max: Expected Number");return T=t,this},A.prototype.setMin=function(t){if(p(t)||x(t))throw new Error("Invalid min: Expected Number");return g=t,this},A.prototype.setGradient=function(t){return this.gradient=y(t),this},A.prototype.setTranslate=function(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},A.prototype.setZoom=function(t){if(p(t)||x(t))throw new Error("Invalid zoom: Expected Number");return this.zoom=t,this},A.prototype.setRotationAngle=function(t){if(p(t)||x(t))throw new Error("Invalid Angle: Expected Number");return this.angle=t,this},A.prototype.setSize=function(t){if(p(t)||x(t))throw new Error("Invalid Size: Expected Number");return this.size=t,this},A.prototype.setIntensity=function(t){if(p(t)||x(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},A.prototype.setOpacity=function(t){if(p(t)||x(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},A.prototype.setBackgroundImage=function(t){const e=this;if(t.url)return d=this.ctx.getParameter(this.ctx.MAX_TEXTURE_SIZE),this.imageTexture=this.ctx.createTexture(),this.type="TEXTURE_2D",c=null,u=t.width||this.width,f=t.height||this.height,u=u>d?d:u,f=f>d?d:f,function(t,e,r){const o=new Image;o.crossOrigin="anonymous",o.onload=e,o.onerror=r,o.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),c={x:t.x||0,y:t.y||0,height:f,width:u,image:this},e.render()}),(function(t){throw new Error("Image Load Error",t)})),this},A.prototype.clearData=function(){this.heatmapData=[],h={},this.render()},A.prototype.addData=function(t,e){const r=this;for(let o=0;o<t.length;o++)e&&S.call(r,t[o]),this.heatmapData.push(t[o]);return this.renderData(this.heatmapData),this},A.prototype.renderData=function(t){if(t.constructor!==Array)throw new Error("Expected Array type");return h=function(t){const e=t.length;_!==e&&(a=new ArrayBuffer(8*e),l=new Float32Array(a),s=new ArrayBuffer(4*e),m=new Float32Array(s),_=e);const r={min:1/0,max:-1/0};for(let o=0;o<e;o++)l[2*o]=t[o].x,l[2*o+1]=t[o].y,m[o]=t[o].value,r.min>t[o].value&&(r.min=t[o].value),r.max<t[o].value&&(r.max=t[o].value);return{posVec:l,rVec:m,minMax:r}}(t),this.heatmapData=t,this.render(),this},A.prototype.render=function(){w.call(this)},A.prototype.projection=function(t){const e=this.zoom||.1,r=this.width/2,o=this.height/2,i=this.translate[0],n=this.translate[1],a=this.angle,s=this.width/this.height;let u=(t.x+i-r)/(r*e),f=(t.y+n-o)/(o*e);if(u*=s,0!==a){const t=Math.cos(-a),e=Math.sin(-a),r=t*u-e*f;f=e*u+t*f,u=r}return u*=1/s,u=u*r+r,f=f*o+o,{x:u,y:f}},new A(t,i)}var e={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}"},r={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"},o={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 "};export{t as default};
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};

@@ -12,709 +12,4 @@ /*!

function Heatmap (context, config = {}) {
let ratio;
let buffer;
let posVec = [];
let buffer2;
let rVec = [];
let pLen = 0;
let maxTextureSize = null;
let imgWidth;
let imgHeight;
let hearmapExData;
let imageConfig;
let configMin = 0;
let configMax = 0;
function isNullUndefined (val) {
return val === null || val === undefined;
}
function isNotNumber (val) {
return typeof val !== 'number';
}
function isSortedAscending (arr) {
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i + 1].offset - arr[i].offset < 0) {
return false;
}
}
return true;
}
function gradientMapper (grad) {
if (grad.constructor !== Array) {
throw new Error('Invalid gradient: Wrong Gradient type, expected Array');
}
if (grad.length < 2) {
throw new Error('Invalid gradient: 2 or more values expected');
}
if (!isSortedAscending(grad)) {
throw new Error('Invalid gradient: Gradient is not sorted');
}
const gradLength = grad.length;
const values = new Float32Array(gradLength * 4);
const offsets = new Array(gradLength);
grad.forEach(function (d, i) {
const baseIndex = i * 4;
values[baseIndex] = d.color[0] / 255;
values[baseIndex + 1] = d.color[1] / 255;
values[baseIndex + 2] = d.color[2] / 255;
values[baseIndex + 3] = d.color[3] !== undefined ? d.color[3] : 1.0;
offsets[i] = d.offset;
});
return {
value: values,
length: gradLength,
offset: offsets
};
}
function createShader (ctx, type, src) {
var shader = ctx.createShader(ctx[type]);
ctx.shaderSource(shader, src);
ctx.compileShader(shader);
var compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
if (!compiled) {
var lastError = ctx.getShaderInfoLog(shader);
ctx.deleteShader(shader);
throw new Error("*** Error compiling shader '" + shader + "':" + lastError);
}
return shader;
}
function createProgram (ctx, shader) {
var vshader = createShader(ctx, 'VERTEX_SHADER', shader.vertex);
var fshader = createShader(ctx, 'FRAGMENT_SHADER', shader.fragment);
var program = ctx.createProgram();
ctx.attachShader(program, vshader);
ctx.attachShader(program, fshader);
ctx.linkProgram(program);
var linked = ctx.getProgramParameter(program, ctx.LINK_STATUS);
if (!linked) {
var lastError = ctx.getProgramInfoLog(program);
ctx.deleteProgram(program);
throw new Error('Error in program linking:' + lastError);
} else {
return program;
}
}
function createImageShader (ctx) {
var program = createProgram(ctx, imageShaders);
return {
program: program,
attr: [{
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_position'),
data: new Float32Array([])
}, {
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_texCoord'),
data: new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0])
}],
uniform: {
u_resolution: ctx.getUniformLocation(program, 'u_resolution'),
u_image: ctx.getUniformLocation(program, 'u_image'),
u_translate: ctx.getUniformLocation(program, 'u_translate'),
u_zoom: ctx.getUniformLocation(program, 'u_zoom'),
u_angle: ctx.getUniformLocation(program, 'u_angle'),
u_density: ctx.getUniformLocation(program, 'u_density')
}
};
}
function createGradiantShader (ctx) {
var program = createProgram(ctx, GradShaders);
return {
program: program,
attr: [{
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_position'),
data: new Float32Array([])
}, {
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 1,
attribute: ctx.getAttribLocation(program, 'a_intensity'),
data: new Float32Array([])
}],
uniform: {
u_resolution: ctx.getUniformLocation(program, 'u_resolution'),
u_max: ctx.getUniformLocation(program, 'u_max'),
u_min: ctx.getUniformLocation(program, 'u_min'),
u_size: ctx.getUniformLocation(program, 'u_size'),
u_intensity: ctx.getUniformLocation(program, 'u_intensity'),
u_translate: ctx.getUniformLocation(program, 'u_translate'),
u_zoom: ctx.getUniformLocation(program, 'u_zoom'),
u_angle: ctx.getUniformLocation(program, 'u_angle'),
u_density: ctx.getUniformLocation(program, 'u_density')
}
};
}
function createColorShader (ctx) {
var program = createProgram(ctx, ColorShader);
return {
program: program,
attr: [{
bufferType: ctx.ARRAY_BUFFER,
buffer: ctx.createBuffer(),
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, 'a_texCoord'),
data: new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0])
}],
uniform: {
u_framebuffer: ctx.getUniformLocation(program, 'u_framebuffer'),
u_colorArr: ctx.getUniformLocation(program, 'u_colorArr'),
u_colorCount: ctx.getUniformLocation(program, 'u_colorCount'),
u_opacity: ctx.getUniformLocation(program, 'u_opacity'),
u_offset: ctx.getUniformLocation(program, 'u_offset')
}
};
}
function extractData (data) {
const len = data.length;
if (pLen !== len) {
buffer = new ArrayBuffer(len * 8);
posVec = new Float32Array(buffer);
buffer2 = new ArrayBuffer(len * 4);
rVec = new Float32Array(buffer2);
pLen = len;
}
const dataMinMaxValue = {
min: Infinity,
max: -Infinity
};
for (let i = 0; i < len; i++) {
posVec[i * 2] = data[i].x;
posVec[(i * 2) + 1] = data[i].y;
rVec[i] = data[i].value;
if (dataMinMaxValue.min > data[i].value) {
dataMinMaxValue.min = data[i].value;
}
if (dataMinMaxValue.max < data[i].value) {
dataMinMaxValue.max = data[i].value;
}
}
return {
posVec: posVec,
rVec: rVec,
minMax: dataMinMaxValue
};
}
function Chart (context, config) {
try {
let res;
if (typeof context === 'string') {
res = document.querySelector(context);
} else if (context instanceof Element) {
res = context;
} else {
throw new Error('Context must be either a string or an Element');
}
const height = res.clientHeight;
const width = res.clientWidth;
const layer = document.createElement('canvas');
const ctx = layer.getContext('webgl2', {
premultipliedAlpha: false,
depth: false,
antialias: true,
alpha: true,
preserveDrawingBuffer: false
});
ratio = getPixlRatio(ctx);
ctx.clearColor(0, 0, 0, 0);
ctx.enable(ctx.BLEND);
ctx.blendEquation(ctx.FUNC_ADD);
ctx.blendFunc(ctx.ONE, ctx.ONE_MINUS_SRC_ALPHA);
ctx.depthMask(true);
layer.setAttribute('height', height * ratio);
layer.setAttribute('width', width * ratio);
layer.style.height = `${height}px`;
layer.style.width = `${width}px`;
layer.style.position = 'absolute';
res.appendChild(layer);
this.ctx = ctx;
this.width = width;
this.height = height;
this.layer = layer;
this.dom = res;
this.gradShadOP = createGradiantShader(this.ctx);
this.colorShadOP = createColorShader(this.ctx);
this.imageShaOP = createImageShader(this.ctx);
this.fbTexObj = ctx.createTexture();
this.fbo = ctx.createFramebuffer();
if (!isNullUndefined(config.size)) {
this.setSize(config.size);
} else {
this.size = 20.0;
}
if (!isNullUndefined(config.max)) {
this.setMax(config.max);
} else {
configMax = null;
}
if (!isNullUndefined(config.min)) {
this.setMin(config.min);
} else {
configMin = null;
}
if (!isNullUndefined(config.intensity)) {
this.setIntensity(config.intensity);
} else {
this.intensity = 1.0;
}
if (!isNullUndefined(config.translate)) {
this.setTranslate(config.translate);
} else {
this.translate = [0, 0];
}
if (!isNullUndefined(config.zoom)) {
this.setZoom(config.zoom);
} else {
this.zoom = 1.0;
}
if (!isNullUndefined(config.angle)) {
this.setRotationAngle(config.angle);
} else {
this.angle = 0.0;
}
if (!isNullUndefined(config.opacity)) {
this.setOpacity(config.opacity);
} else {
this.opacity = 1.0;
}
this.gradient = gradientMapper(config.gradient);
this.ratio = ratio;
if (config.backgroundImage && config.backgroundImage.url) {
this.setBackgroundImage(config.backgroundImage);
}
this.heatmapData = [];
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
} catch (error) {
console.error(error);
}
}
Chart.prototype.resize = function () {
const height = this.dom.clientHeight;
const width = this.dom.clientWidth;
this.layer.setAttribute('height', height * ratio);
this.layer.setAttribute('width', width * ratio);
this.layer.style.height = `${height}px`;
this.layer.style.width = `${width}px`;
this.width = width;
this.height = height;
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
/* Perform update */
this.render(hearmapExData);
};
Chart.prototype.clear = function () {
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
};
Chart.prototype.setMax = function (max) {
if (isNullUndefined(max) || isNotNumber(max)) {
throw new Error('Invalid max: Expected Number');
}
configMax = max;
return this;
};
Chart.prototype.setMin = function (min) {
if (isNullUndefined(min) || isNotNumber(min)) {
throw new Error('Invalid min: Expected Number');
}
configMin = min;
return this;
};
Chart.prototype.setGradient = function (gradient) {
this.gradient = gradientMapper(gradient);
return this;
};
Chart.prototype.setTranslate = function (translate) {
if (translate.constructor !== Array) {
throw new Error('Invalid Translate: Translate has to be of Array type');
}
if (translate.length !== 2) {
throw new Error('Translate has to be of length 2');
}
this.translate = translate;
return this;
};
Chart.prototype.setZoom = function (zoom) {
if (isNullUndefined(zoom) || isNotNumber(zoom)) {
throw new Error('Invalid zoom: Expected Number');
}
this.zoom = zoom;
return this;
};
Chart.prototype.setRotationAngle = function (angle) {
if (isNullUndefined(angle) || isNotNumber(angle)) {
throw new Error('Invalid Angle: Expected Number');
}
this.angle = angle;
return this;
};
Chart.prototype.setSize = function (size) {
if (isNullUndefined(size) || isNotNumber(size)) {
throw new Error('Invalid Size: Expected Number');
}
this.size = size;
return this;
};
Chart.prototype.setIntensity = function (intensity) {
if (isNullUndefined(intensity) || isNotNumber(intensity)) {
this.intensity = 1.0; // applying default intensity
throw new Error('Invalid Intensity: Expected Number');
}
if (intensity > 1 || intensity < 0) {
this.intensity = intensity > 1 ? 1 : 0; // Setting bound value
throw new Error('Invalid Intensity value ' + intensity);
}
this.intensity = intensity;
return this;
};
Chart.prototype.setOpacity = function (opacity) {
if (isNullUndefined(opacity) || isNotNumber(opacity)) {
throw new Error('Invalid Opacity: Expected Number');
}
if (opacity > 1 || opacity < 0) {
throw new Error('Invalid Opacity value ' + opacity);
}
this.opacity = opacity;
return this;
};
Chart.prototype.setBackgroundImage = function (config) {
const self = this;
if (!config.url) {
return;
}
maxTextureSize = this.ctx.getParameter(this.ctx.MAX_TEXTURE_SIZE);
this.imageTexture = this.ctx.createTexture();
this.type = 'TEXTURE_2D';
imageConfig = null;
imgWidth = config.width || this.width;
imgHeight = config.height || this.height;
imgWidth = imgWidth > maxTextureSize ? maxTextureSize : imgWidth;
imgHeight = imgHeight > maxTextureSize ? maxTextureSize : imgHeight;
imageInstance(config.url, function onUpdateCallBack () {
self.ctx.activeTexture(self.ctx.TEXTURE0);
self.ctx.bindTexture(self.ctx.TEXTURE_2D, self.imageTexture);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_S, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_T, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MIN_FILTER, self.ctx.LINEAR);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MAG_FILTER, self.ctx.LINEAR);
self.ctx.texImage2D(
self.ctx.TEXTURE_2D,
0,
self.ctx.RGBA,
this.naturalWidth,
this.naturalHeight,
0,
self.ctx.RGBA,
self.ctx.UNSIGNED_BYTE,
this
);
imageConfig = {
x: config.x || 0,
y: config.y || 0,
height: imgHeight,
width: imgWidth,
image: this
};
self.render();
}, function onErrorCallBack (error) {
throw new Error('Image Load Error', error);
});
return this;
};
Chart.prototype.clearData = function () {
this.heatmapData = [];
hearmapExData = {};
this.render();
};
Chart.prototype.addData = function (data, transIntactFlag) {
const self = this;
for (let i = 0; i < data.length; i++) {
if (transIntactFlag) {
transCoOr.call(self, data[i]);
}
this.heatmapData.push(data[i]);
}
this.renderData(this.heatmapData);
return this;
};
Chart.prototype.renderData = function (data) {
if (data.constructor !== Array) {
throw new Error('Expected Array type');
}
hearmapExData = extractData(data);
this.heatmapData = data;
this.render();
return this;
};
Chart.prototype.render = function () {
renderExec.call(this);
};
Chart.prototype.projection = function (data) {
// Pre-compute constants and repetitive calculations
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const translateX = this.translate[0];
const translateY = this.translate[1];
const angle = this.angle;
const aspect = this.width / this.height;
// Calculate the adjusted positions
let posX = (data.x + translateX - halfWidth) / (halfWidth * zoomFactor);
let posY = (data.y + translateY - halfHeight) / (halfHeight * zoomFactor);
posX *= aspect;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(-angle);
const sinAngle = Math.sin(-angle);
const xNew = (cosAngle * posX) - (sinAngle * posY);
posY = (sinAngle * posX) + (cosAngle * posY);
posX = xNew;
}
posX *= 1.0 / aspect;
// Scale back and adjust the position
posX = (posX * halfWidth) + halfWidth;
posY = (posY * halfHeight) + halfHeight;
return { x: posX, y: posY };
};
function renderExec () {
const ctx = this.ctx;
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);
ctx.bindTexture(ctx.TEXTURE_2D, this.fbTexObj);
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, this.width * this.ratio, this.height * this.ratio, 0, ctx.RGBA, ctx.UNSIGNED_BYTE, null);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR);
ctx.bindFramebuffer(ctx.FRAMEBUFFER, this.fbo);
ctx.framebufferTexture2D(ctx.FRAMEBUFFER, ctx.COLOR_ATTACHMENT0, ctx.TEXTURE_2D, this.fbTexObj, 0);
if (hearmapExData) {
renderHeatGrad.call(this, ctx, hearmapExData);
}
ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
if (imageConfig) {
renderImage.call(this, ctx, imageConfig);
}
renderColorGradiant.call(this, ctx);
}
function renderHeatGrad (ctx, exData) {
ctx.useProgram(this.gradShadOP.program);
this.min = configMin !== null ? configMin : exData?.minMax?.min ?? 0;
this.max = configMax !== null ? configMax : exData?.minMax?.max ?? 0;
this.gradShadOP.attr[0].data = exData.posVec || [];
this.gradShadOP.attr[1].data = exData.rVec || [];
ctx.uniform2fv(this.gradShadOP.uniform.u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(this.gradShadOP.uniform.u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(this.gradShadOP.uniform.u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(this.gradShadOP.uniform.u_angle, this.angle);
ctx.uniform1f(this.gradShadOP.uniform.u_density, this.ratio);
ctx.uniform1f(this.gradShadOP.uniform.u_max, this.max);
ctx.uniform1f(this.gradShadOP.uniform.u_min, this.min);
ctx.uniform1f(this.gradShadOP.uniform.u_size, this.size);
ctx.uniform1f(this.gradShadOP.uniform.u_intensity, this.intensity);
this.gradShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.drawArrays(ctx.POINTS, 0, (exData.posVec || []).length / 2);
}
function renderImage (ctx, imageConfig) {
const { x = 0, y = 0, width = 0, height = 0 } = imageConfig;
ctx.useProgram(this.imageShaOP.program);
ctx.uniform2fv(this.imageShaOP.uniform.u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(this.imageShaOP.uniform.u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(this.imageShaOP.uniform.u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(this.imageShaOP.uniform.u_angle, this.angle);
ctx.uniform1f(this.imageShaOP.uniform.u_density, this.ratio);
this.imageShaOP.attr[0].data = new Float32Array([x, y, x + width, y, x, y + height, x, y + height, x + width, y, x + width, y + height]);
this.imageShaOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(this.imageShaOP.uniform.u_image, 0);
ctx.activeTexture(this.ctx.TEXTURE0);
ctx.bindTexture(this.ctx.TEXTURE_2D, this.imageTexture);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function renderColorGradiant (ctx) {
ctx.useProgram(this.colorShadOP.program);
ctx.uniform4fv(this.colorShadOP.uniform.u_colorArr, this.gradient.value);
ctx.uniform1f(this.colorShadOP.uniform.u_colorCount, this.gradient.length);
ctx.uniform1fv(this.colorShadOP.uniform.u_offset, new Float32Array(this.gradient.offset));
ctx.uniform1f(this.colorShadOP.uniform.u_opacity, this.opacity);
this.colorShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(this.colorShadOP.uniform.u_framebuffer, 0);
ctx.activeTexture(ctx.TEXTURE0);
ctx.bindTexture(ctx.TEXTURE_2D, this.fbTexObj);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function transCoOr (data) {
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const angle = this.angle;
// Combine operations to reduce the number of arithmetic steps
let posX = (data.x - halfWidth) / halfWidth * zoomFactor;
let posY = (data.y - halfHeight) / halfHeight * zoomFactor;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(angle);
const sinAngle = Math.sin(angle);
const xNew = (cosAngle * posX) - (sinAngle * posY);
posY = (sinAngle * posX) + (cosAngle * posY);
posX = xNew;
}
// Scale back and adjust the position
posX = (posX * halfWidth) + halfWidth - this.translate[0];
posY = (posY * halfHeight) + halfHeight - this.translate[1];
data.x = posX;
data.y = posY;
return { x: posX, y: posY };
}
function imageInstance (url, onLoad, onError) {
const imageIns = new Image();
imageIns.crossOrigin = 'anonymous';
imageIns.onload = onLoad;
imageIns.onerror = onError;
imageIns.src = url;
return imageIns;
}
return new Chart(context, config);
}
function getPixlRatio (ctx) {
const dpr = window.devicePixelRatio || 1;
const bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
}
var GradShaders = {
vertex: `#version 300 es
const GradShader = {
vertex: `#version 300 es
in vec2 a_position;

@@ -749,3 +44,3 @@ in float a_intensity;

}`,
fragment: `#version 300 es
fragment: `#version 300 es
precision mediump float;

@@ -765,7 +60,6 @@ uniform float u_max;

}
}`
}`,
};
var ColorShader = {
vertex: `#version 300 es
const ColorShader = {
vertex: `#version 300 es
precision highp float;

@@ -780,3 +74,3 @@ in vec2 a_texCoord;

`,
fragment: `#version 300 es
fragment: `#version 300 es
precision mediump float;

@@ -822,7 +116,6 @@ in vec2 v_texCoord;

}
`
`,
};
var imageShaders = {
vertex: `#version 300 es
const ImageShader = {
vertex: `#version 300 es
precision highp float;

@@ -862,3 +155,3 @@ in vec2 a_position;

`,
fragment: `#version 300 es
fragment: `#version 300 es
precision mediump float;

@@ -871,7 +164,764 @@ uniform sampler2D u_image;

}
`
`,
};
return Heatmap;
function createShader(ctx, type, src) {
const shader = ctx.createShader(ctx[type]);
if (!shader) {
throw new Error("Failed to create shader.");
}
ctx.shaderSource(shader, src);
ctx.compileShader(shader);
const compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
if (!compiled) {
const lastError = ctx.getShaderInfoLog(shader);
ctx.deleteShader(shader);
throw new Error("*** Error compiling shader '" + shader + "':" + lastError);
}
return shader;
}
function createProgram(ctx, shader) {
const vshader = createShader(ctx, "VERTEX_SHADER", shader.vertex);
const fshader = createShader(ctx, "FRAGMENT_SHADER", shader.fragment);
const program = ctx.createProgram();
if (!program) {
throw new Error("Failed to create program.");
}
ctx.attachShader(program, vshader);
ctx.attachShader(program, fshader);
ctx.linkProgram(program);
const linked = ctx.getProgramParameter(program, ctx.LINK_STATUS);
if (!linked) {
const lastError = ctx.getProgramInfoLog(program);
ctx.deleteProgram(program);
throw new Error("Error in program linking:" + lastError);
}
else {
return program;
}
}
const createImageShader = function (ctx, shader) {
const program = createProgram(ctx, shader);
const positionBuffer = ctx.createBuffer();
if (!positionBuffer) {
throw new Error("Failed to create position buffer.");
}
const texCoordBuffer = ctx.createBuffer();
if (!texCoordBuffer) {
throw new Error("Failed to create texture coordinate buffer.");
}
return {
program: program,
attr: [
{
bufferType: ctx.ARRAY_BUFFER,
buffer: positionBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_position"),
data: new Float32Array([]),
},
{
bufferType: ctx.ARRAY_BUFFER,
buffer: texCoordBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_texCoord"),
data: new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0,
]),
},
],
uniform: {
u_resolution: ctx.getUniformLocation(program, "u_resolution"),
u_image: ctx.getUniformLocation(program, "u_image"),
u_translate: ctx.getUniformLocation(program, "u_translate"),
u_zoom: ctx.getUniformLocation(program, "u_zoom"),
u_angle: ctx.getUniformLocation(program, "u_angle"),
u_density: ctx.getUniformLocation(program, "u_density"),
},
};
};
const createGradiantShader = function (ctx, shader) {
const program = createProgram(ctx, shader);
const positionBuffer = ctx.createBuffer();
if (!positionBuffer) {
throw new Error("Failed to create position buffer.");
}
const intensityBuffer = ctx.createBuffer();
if (!intensityBuffer) {
throw new Error("Failed to create intensity buffer.");
}
return {
program: program,
attr: [
{
bufferType: ctx.ARRAY_BUFFER,
buffer: positionBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_position"),
data: new Float32Array([]),
},
{
bufferType: ctx.ARRAY_BUFFER,
buffer: intensityBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 1,
attribute: ctx.getAttribLocation(program, "a_intensity"),
data: new Float32Array([]),
},
],
uniform: {
u_resolution: ctx.getUniformLocation(program, "u_resolution"),
u_max: ctx.getUniformLocation(program, "u_max"),
u_min: ctx.getUniformLocation(program, "u_min"),
u_size: ctx.getUniformLocation(program, "u_size"),
u_intensity: ctx.getUniformLocation(program, "u_intensity"),
u_translate: ctx.getUniformLocation(program, "u_translate"),
u_zoom: ctx.getUniformLocation(program, "u_zoom"),
u_angle: ctx.getUniformLocation(program, "u_angle"),
u_density: ctx.getUniformLocation(program, "u_density"),
},
};
};
const createColorShader = function (ctx, shader) {
const program = createProgram(ctx, shader);
const texCoordBuffer = ctx.createBuffer();
if (!texCoordBuffer) {
throw new Error("Failed to create texture coordinate buffer.");
}
return {
program: program,
attr: [
{
bufferType: ctx.ARRAY_BUFFER,
buffer: texCoordBuffer,
drawType: ctx.STATIC_DRAW,
valueType: ctx.FLOAT,
size: 2,
attribute: ctx.getAttribLocation(program, "a_texCoord"),
data: new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0,
]),
},
],
uniform: {
u_framebuffer: ctx.getUniformLocation(program, "u_framebuffer"),
u_colorArr: ctx.getUniformLocation(program, "u_colorArr"),
u_colorCount: ctx.getUniformLocation(program, "u_colorCount"),
u_opacity: ctx.getUniformLocation(program, "u_opacity"),
u_offset: ctx.getUniformLocation(program, "u_offset"),
},
};
};
function isNullUndefined(val) {
return val === null || val === undefined;
}
function isNotNumber(val) {
return typeof val !== "number";
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isSortedAscending(arr) {
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i + 1].offset - arr[i].offset < 0) {
return false;
}
}
return true;
}
/** @see https://codereview.chromium.org/156833002/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getPixelRatio(ctx) {
const dpr = window.devicePixelRatio || 1;
const bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
return dpr / bsr;
}
function gradientMapper(grad) {
if (!Array.isArray(grad) || grad.length < 2) {
throw new Error("Invalid gradient: Expected an array with at least 2 elements.");
}
if (!isSortedAscending(grad)) {
throw new Error("Invalid gradient: Gradient is not sorted");
}
const gradLength = grad.length;
const values = new Float32Array(gradLength * 4);
const offsets = new Array(gradLength);
grad.forEach(function (d, i) {
const baseIndex = i * 4;
values[baseIndex] = d.color[0] / 255;
values[baseIndex + 1] = d.color[1] / 255;
values[baseIndex + 2] = d.color[2] / 255;
values[baseIndex + 3] = d.color[3] !== undefined ? d.color[3] : 1.0;
offsets[i] = d.offset;
});
return {
value: values,
length: gradLength,
offset: offsets,
};
}
function extractData(data) {
const self = this;
const len = data.length;
let { posVec = new Float32Array(), rVec = new Float32Array() } = (self.hearmapExData || {});
if (self._pDataLength !== len) {
posVec = new Float32Array(new ArrayBuffer(len * 8));
rVec = new Float32Array(new ArrayBuffer(len * 4));
self._pDataLength = len;
}
const dataMinMaxValue = {
min: Infinity,
max: -Infinity,
};
for (let i = 0; i < len; i++) {
posVec[i * 2] = data[i].x;
posVec[i * 2 + 1] = data[i].y;
rVec[i] = data[i].value;
if (dataMinMaxValue.min > data[i].value) {
dataMinMaxValue.min = data[i].value;
}
if (dataMinMaxValue.max < data[i].value) {
dataMinMaxValue.max = data[i].value;
}
}
return {
posVec: posVec,
rVec: rVec,
minMax: dataMinMaxValue,
};
}
function transCoOr(data) {
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const { angle, translate } = this;
// Combine operations to reduce the number of arithmetic steps
let posX = ((data.x - halfWidth) / halfWidth) * zoomFactor;
let posY = ((data.y - halfHeight) / halfHeight) * zoomFactor;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(angle);
const sinAngle = Math.sin(angle);
posY = sinAngle * posX + cosAngle * posY;
posX = cosAngle * posX - sinAngle * posY;
}
// Scale back and adjust the position
posX = posX * halfWidth + halfWidth - translate[0];
posY = posY * halfHeight + halfHeight - translate[1];
data.x = posX;
data.y = posY;
return { x: posX, y: posY };
}
function renderExec() {
const ctx = this.ctx;
if (!ctx) {
return;
}
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);
ctx.bindTexture(ctx.TEXTURE_2D, this._fbTexObj);
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, this.width * this.ratio, this.height * this.ratio, 0, ctx.RGBA, ctx.UNSIGNED_BYTE, null);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR);
ctx.bindFramebuffer(ctx.FRAMEBUFFER, this._fbo);
ctx.framebufferTexture2D(ctx.FRAMEBUFFER, ctx.COLOR_ATTACHMENT0, ctx.TEXTURE_2D, this._fbTexObj, 0);
if (this.hearmapExData) {
renderHeatGrad.call(this, ctx, this.hearmapExData);
}
ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
if (this.imageConfig) {
renderImage.call(this, ctx, this.imageConfig);
}
renderColorGradiant.call(this, ctx);
}
function renderHeatGrad(ctx, exData) {
var _a, _b, _c, _d;
ctx.useProgram(this._gradShadOP.program);
const { u_resolution, u_translate, u_zoom, u_angle, u_density, u_max, u_min, u_size, u_intensity } = this._gradShadOP.uniform;
this.min =
this.configMin !== null ? this.configMin : (_b = (_a = exData === null || exData === void 0 ? void 0 : exData.minMax) === null || _a === void 0 ? void 0 : _a.min) !== null && _b !== void 0 ? _b : 0;
this.max =
this.configMax !== null ? this.configMax : (_d = (_c = exData === null || exData === void 0 ? void 0 : exData.minMax) === null || _c === void 0 ? void 0 : _c.max) !== null && _d !== void 0 ? _d : 0;
this._gradShadOP.attr[0].data = exData.posVec || [];
this._gradShadOP.attr[1].data = exData.rVec || [];
ctx.uniform2fv(u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(u_angle, this.angle);
ctx.uniform1f(u_density, this.ratio);
ctx.uniform1f(u_max, this.max);
ctx.uniform1f(u_min, this.min);
ctx.uniform1f(u_size, this.size);
ctx.uniform1f(u_intensity, this.intensity);
this._gradShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.drawArrays(ctx.POINTS, 0, (exData.posVec || []).length / 2);
}
function renderImage(ctx, imageConfig) {
const { x = 0, y = 0, width = 0, height = 0 } = imageConfig;
const { u_resolution, u_translate, u_zoom, u_angle, u_density, u_image } = this._imageShaOP.uniform;
ctx.useProgram(this._imageShaOP.program);
ctx.uniform2fv(u_resolution, new Float32Array([this.width * this.ratio, this.height * this.ratio]));
ctx.uniform2fv(u_translate, new Float32Array([this.translate[0], this.translate[1]]));
ctx.uniform1f(u_zoom, this.zoom ? this.zoom : 0.01);
ctx.uniform1f(u_angle, this.angle);
ctx.uniform1f(u_density, this.ratio);
this._imageShaOP.attr[0].data = new Float32Array([
x,
y,
x + width,
y,
x,
y + height,
x,
y + height,
x + width,
y,
x + width,
y + height,
]);
this._imageShaOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(u_image, 0);
ctx.activeTexture(this.ctx.TEXTURE0);
ctx.bindTexture(this.ctx.TEXTURE_2D, this._imageTexture);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function renderColorGradiant(ctx) {
const { u_colorArr, u_colorCount, u_offset, u_opacity, u_framebuffer } = this._colorShadOP.uniform;
ctx.useProgram(this._colorShadOP.program);
ctx.uniform4fv(u_colorArr, this.gradient.value);
ctx.uniform1f(u_colorCount, this.gradient.length);
ctx.uniform1fv(u_offset, new Float32Array(this.gradient.offset));
ctx.uniform1f(u_opacity, this.opacity);
this._colorShadOP.attr.forEach(function (d) {
ctx.bindBuffer(d.bufferType, d.buffer);
ctx.bufferData(d.bufferType, d.data, d.drawType);
ctx.enableVertexAttribArray(d.attribute);
ctx.vertexAttribPointer(d.attribute, d.size, d.valueType, true, 0, 0);
});
ctx.uniform1i(u_framebuffer, 0);
ctx.activeTexture(ctx.TEXTURE0);
ctx.bindTexture(ctx.TEXTURE_2D, this._fbTexObj);
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
function imageInstance(url, onLoad, onError) {
const imageIns = new Image();
imageIns.crossOrigin = "anonymous";
imageIns.onload = onLoad;
imageIns.onerror = onError;
imageIns.src = url;
return imageIns;
}
class HeatmapRenderer {
constructor(container, config) {
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 = undefined;
this.imgWidth = 0;
this.imgHeight = 0;
this.heatmapData = [];
this.type = "";
try {
const res = typeof container === "string"
? document.querySelector(container)
: container instanceof HTMLElement
? container
: null;
if (!res) {
throw new Error("Context must be either a string or an Element");
}
const { clientHeight: height, clientWidth: width } = res;
const layer = document.createElement("canvas");
const ctx = layer.getContext("webgl2", {
premultipliedAlpha: false,
depth: false,
antialias: true,
alpha: true,
preserveDrawingBuffer: false,
});
this.ratio = getPixelRatio(ctx);
ctx.clearColor(0, 0, 0, 0);
ctx.enable(ctx.BLEND);
ctx.blendEquation(ctx.FUNC_ADD);
ctx.blendFunc(ctx.ONE, ctx.ONE_MINUS_SRC_ALPHA);
ctx.depthMask(true);
layer.setAttribute("height", (height * this.ratio).toString());
layer.setAttribute("width", (width * this.ratio).toString());
layer.style.height = `${height}px`;
layer.style.width = `${width}px`;
layer.style.position = "absolute";
res.appendChild(layer);
this.ctx = ctx;
this.width = width;
this.height = height;
this.imageConfig = null;
this.configMin = null;
this.configMax = null;
this.hearmapExData = {};
this.layer = layer;
this.dom = res;
this._gradShadOP = createGradiantShader(this.ctx, GradShader);
this._colorShadOP = createColorShader(this.ctx, ColorShader);
this._imageShaOP = createImageShader(this.ctx, ImageShader);
this._fbTexObj = ctx.createTexture();
this._fbo = ctx.createFramebuffer();
if (!isNullUndefined(config.size)) {
this.setSize(config.size);
}
else {
this.size = 20.0;
}
if (!isNullUndefined(config.max)) {
this.setMax(config.max);
}
else {
this.configMax = null;
}
if (!isNullUndefined(config.min)) {
this.setMin(config.min);
}
else {
this.configMin = null;
}
if (!isNullUndefined(config.intensity)) {
this.setIntensity(config.intensity);
}
else {
this.intensity = 1.0;
}
if (!isNullUndefined(config.translate)) {
this.setTranslate(config.translate);
}
else {
this.translate = [0, 0];
}
if (!isNullUndefined(config.zoom)) {
this.setZoom(config.zoom);
}
else {
this.zoom = 1.0;
}
if (!isNullUndefined(config.angle)) {
this.setRotationAngle(config.angle);
}
else {
this.angle = 0.0;
}
if (!isNullUndefined(config.opacity)) {
this.setOpacity(config.opacity);
}
else {
this.opacity = 1.0;
}
this.gradient = gradientMapper(config.gradient);
if (config.backgroundImage && config.backgroundImage.url) {
this.setBackgroundImage(config.backgroundImage);
}
this.heatmapData = [];
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
}
catch (error) {
console.error(error);
}
}
/**
* Invoke resize method on container resize.
*/
resize() {
const height = this.dom.clientHeight;
const width = this.dom.clientWidth;
this.layer.setAttribute("height", (height * this.ratio).toString());
this.layer.setAttribute("width", (width * this.ratio).toString());
this.layer.style.height = `${height}px`;
this.layer.style.width = `${width}px`;
this.width = width;
this.height = height;
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
/* Perform update */
this.render();
}
clear() {
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
}
/**
* Set the maximum data value for relative gradient calculations
* @param max - number
* @returns instance
*/
setMax(max) {
if (isNullUndefined(max) || isNotNumber(max)) {
throw new Error("Invalid max: Expected Number");
}
this.configMax = max;
return this;
}
/**
* Set the minimum data value for relative gradient calculations
* @param min - number
* @returns instance
*/
setMin(min) {
if (isNullUndefined(min) || isNotNumber(min)) {
throw new Error("Invalid min: Expected Number");
}
this.configMin = min;
return this;
}
/**
* Accepts array of objects with color value and offset
* @param gradient - Color Gradient
* @returns instance
*/
setGradient(gradient) {
this.gradient = gradientMapper(gradient);
return this;
}
/**
* Set the translate on the Heatmap
* @param translate - Accepts array [x, y]
* @returns instance
*/
setTranslate(translate) {
if (translate.constructor !== Array) {
throw new Error("Invalid Translate: Translate has to be of Array type");
}
if (translate.length !== 2) {
throw new Error("Translate has to be of length 2");
}
this.translate = translate;
return this;
}
/**
* Set the zoom transformation on the Heatmap
* @param zoom - Accepts float value
* @returns instance
*/
setZoom(zoom) {
if (isNullUndefined(zoom) || isNotNumber(zoom)) {
throw new Error("Invalid zoom: Expected Number");
}
this.zoom = zoom;
return this;
}
/**
* Set the rotation transformation on the Heatmap
* @param angle - Accepts angle in radians
* @returns instance
*/
setRotationAngle(angle) {
if (isNullUndefined(angle) || isNotNumber(angle)) {
throw new Error("Invalid Angle: Expected Number");
}
this.angle = angle;
return this;
}
/**
* Set the point radius
* @param size - Accepts float value
* @returns instance
*/
setSize(size) {
if (isNullUndefined(size) || isNotNumber(size)) {
throw new Error("Invalid Size: Expected Number");
}
this.size = size;
return this;
}
/**
* Set the intensity factor
* @param intensity - Accepts float value
* @returns instance
*/
setIntensity(intensity) {
if (isNullUndefined(intensity) || isNotNumber(intensity)) {
this.intensity = 1.0; // applying default intensity
throw new Error("Invalid Intensity: Expected Number");
}
if (intensity > 1 || intensity < 0) {
this.intensity = intensity > 1 ? 1 : 0; // Setting bound value
throw new Error("Invalid Intensity value " + intensity);
}
this.intensity = intensity;
return this;
}
/**
* Set the opacity factor
* @param opacity - The opacity factor.
* @returns instance
*/
setOpacity(opacity) {
if (isNullUndefined(opacity) || isNotNumber(opacity)) {
throw new Error("Invalid Opacity: Expected Number");
}
if (opacity > 1 || opacity < 0) {
throw new Error("Invalid Opacity value " + opacity);
}
this.opacity = opacity;
return this;
}
/**
* Set the background image
* @param config - Accepts Object with { url, height, width, x, and y} properties
* @returns instance
*/
setBackgroundImage(config) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
if (!config.url) {
return;
}
const maxTextureSize = this.ctx.getParameter(this.ctx.MAX_TEXTURE_SIZE);
this._imageTexture = this.ctx.createTexture();
this.type = "TEXTURE_2D";
this.imageConfig = null;
this.imgWidth = config.width || this.width;
this.imgHeight = config.height || this.height;
this.imgWidth =
this.imgWidth > maxTextureSize ? maxTextureSize : this.imgWidth;
this.imgHeight =
this.imgHeight > maxTextureSize ? maxTextureSize : this.imgHeight;
imageInstance(config.url, function onUpdateCallBack() {
self.ctx.activeTexture(self.ctx.TEXTURE0);
self.ctx.bindTexture(self.ctx.TEXTURE_2D, self._imageTexture);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_S, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_WRAP_T, self.ctx.CLAMP_TO_EDGE);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MIN_FILTER, self.ctx.LINEAR);
self.ctx.texParameteri(self.ctx.TEXTURE_2D, self.ctx.TEXTURE_MAG_FILTER, self.ctx.LINEAR);
self.ctx.texImage2D(self.ctx.TEXTURE_2D, 0, self.ctx.RGBA, this.naturalWidth, this.naturalHeight, 0, self.ctx.RGBA, self.ctx.UNSIGNED_BYTE, this);
self.imageConfig = {
x: config.x || 0,
y: config.y || 0,
height: self.imgHeight,
width: self.imgWidth,
image: this,
};
self.render();
}, function onErrorCallBack(error) {
throw new Error(`Image Load Error, ${error}`);
});
return this;
}
/**
* Clear heatmap
*/
clearData() {
this.heatmapData = [];
this.hearmapExData = {};
this.render();
}
/**
* Method to append data points. This method automatically adds new data points to the existing dataset and the heatmap updates in immediately. no need to call the ".render" method separately.
* @param data - The data points with 'x', 'y' and 'value'
* @param transIntactFlag - Flag indicating whether to apply existing heatmap transformations on the newly added data points
* @returns instance
*/
addData(data, transIntactFlag) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
for (let i = 0; i < data.length; i++) {
if (transIntactFlag) {
transCoOr.call(self, data[i]);
}
this.heatmapData.push(data[i]);
}
this.renderData(this.heatmapData);
return this;
}
/**
* Method to load data. This will override any existing data.
* @param data - Accepts an array of data points with 'x', 'y' and 'value'
* @returns instance
*/
renderData(data) {
if (data.constructor !== Array) {
throw new Error("Expected Array type");
}
this.hearmapExData = extractData.call(this, data);
this.heatmapData = data;
this.render();
return this;
}
/**
* Method to update the heatmap. This method to be invoked on every change in configuration.
*/
render() {
renderExec.call(this);
}
/**
* Get projected co-ordinates relative to the heatmap
* @param data - The data point to project.
* @returns projected data point.
*/
projection(data) {
// Pre-compute constants and repetitive calculations
const zoomFactor = this.zoom || 0.1;
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const translateX = this.translate[0];
const translateY = this.translate[1];
const angle = this.angle;
const aspect = this.width / this.height;
// Calculate the adjusted positions
let posX = (data.x + translateX - halfWidth) / (halfWidth * zoomFactor);
let posY = (data.y + translateY - halfHeight) / (halfHeight * zoomFactor);
posX *= aspect;
// Rotate the point if there's an angle
if (angle !== 0.0) {
const cosAngle = Math.cos(-angle);
const sinAngle = Math.sin(-angle);
const xNew = cosAngle * posX - sinAngle * posY;
posY = sinAngle * posX + cosAngle * posY;
posX = xNew;
}
posX *= 1.0 / aspect;
// Scale back and adjust the position
posX = posX * halfWidth + halfWidth;
posY = posY * halfHeight + halfHeight;
return { x: posX, y: posY };
}
}
function main (context, config) {
return new HeatmapRenderer(context, config);
}
return main;
}));

@@ -6,2 +6,2 @@ /*!

*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).visualHeatmap=e()}(this,(function(){"use strict";var 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"},r={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 "};return function(o,i={}){let n,a,s,u,f,h,c,l=[],m=[],_=0,d=null,g=0,T=0;function p(t){return null==t}function x(t){return"number"!=typeof t}function y(t){if(t.constructor!==Array)throw new Error("Invalid gradient: Wrong Gradient type, expected Array");if(t.length<2)throw new Error("Invalid gradient: 2 or more values expected");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,r=new Float32Array(4*e),o=new Array(e);return t.forEach((function(t,e){const i=4*e;r[i]=t.color[0]/255,r[i+1]=t.color[1]/255,r[i+2]=t.color[2]/255,r[i+3]=void 0!==t.color[3]?t.color[3]:1,o[e]=t.offset})),{value:r,length:e,offset:o}}function v(t,e,r){var o=t.createShader(t[e]);if(t.shaderSource(o,r),t.compileShader(o),!t.getShaderParameter(o,t.COMPILE_STATUS)){var i=t.getShaderInfoLog(o);throw t.deleteShader(o),new Error("*** Error compiling shader '"+o+"':"+i)}return o}function E(t,e){var r=v(t,"VERTEX_SHADER",e.vertex),o=v(t,"FRAGMENT_SHADER",e.fragment),i=t.createProgram();if(t.attachShader(i,r),t.attachShader(i,o),t.linkProgram(i),t.getProgramParameter(i,t.LINK_STATUS))return i;var n=t.getProgramInfoLog(i);throw t.deleteProgram(i),new Error("Error in program linking:"+n)}function A(o,i){try{let a;if("string"==typeof o)a=document.querySelector(o);else{if(!(o instanceof Element))throw new Error("Context must be either a string or an Element");a=o}const s=a.clientHeight,u=a.clientWidth,f=document.createElement("canvas"),h=f.getContext("webgl2",{premultipliedAlpha:!1,depth:!1,antialias:!0,alpha:!0,preserveDrawingBuffer:!1});n=function(t){const e=window.devicePixelRatio||1,r=t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1;return e/r}(h),h.clearColor(0,0,0,0),h.enable(h.BLEND),h.blendEquation(h.FUNC_ADD),h.blendFunc(h.ONE,h.ONE_MINUS_SRC_ALPHA),h.depthMask(!0),f.setAttribute("height",s*n),f.setAttribute("width",u*n),f.style.height=`${s}px`,f.style.width=`${u}px`,f.style.position="absolute",a.appendChild(f),this.ctx=h,this.width=u,this.height=s,this.layer=f,this.dom=a,this.gradShadOP=function(e){var r=E(e,t);return{program:r,attr:[{bufferType:e.ARRAY_BUFFER,buffer:e.createBuffer(),drawType:e.STATIC_DRAW,valueType:e.FLOAT,size:2,attribute:e.getAttribLocation(r,"a_position"),data:new Float32Array([])},{bufferType:e.ARRAY_BUFFER,buffer:e.createBuffer(),drawType:e.STATIC_DRAW,valueType:e.FLOAT,size:1,attribute:e.getAttribLocation(r,"a_intensity"),data:new Float32Array([])}],uniform:{u_resolution:e.getUniformLocation(r,"u_resolution"),u_max:e.getUniformLocation(r,"u_max"),u_min:e.getUniformLocation(r,"u_min"),u_size:e.getUniformLocation(r,"u_size"),u_intensity:e.getUniformLocation(r,"u_intensity"),u_translate:e.getUniformLocation(r,"u_translate"),u_zoom:e.getUniformLocation(r,"u_zoom"),u_angle:e.getUniformLocation(r,"u_angle"),u_density:e.getUniformLocation(r,"u_density")}}}(this.ctx),this.colorShadOP=function(t){var r=E(t,e);return{program:r,attr:[{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(r,"a_texCoord"),data:new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1])}],uniform:{u_framebuffer:t.getUniformLocation(r,"u_framebuffer"),u_colorArr:t.getUniformLocation(r,"u_colorArr"),u_colorCount:t.getUniformLocation(r,"u_colorCount"),u_opacity:t.getUniformLocation(r,"u_opacity"),u_offset:t.getUniformLocation(r,"u_offset")}}}(this.ctx),this.imageShaOP=function(t){var e=E(t,r);return{program:e,attr:[{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(e,"a_position"),data:new Float32Array([])},{bufferType:t.ARRAY_BUFFER,buffer:t.createBuffer(),drawType:t.STATIC_DRAW,valueType:t.FLOAT,size:2,attribute:t.getAttribLocation(e,"a_texCoord"),data:new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1])}],uniform:{u_resolution:t.getUniformLocation(e,"u_resolution"),u_image:t.getUniformLocation(e,"u_image"),u_translate:t.getUniformLocation(e,"u_translate"),u_zoom:t.getUniformLocation(e,"u_zoom"),u_angle:t.getUniformLocation(e,"u_angle"),u_density:t.getUniformLocation(e,"u_density")}}}(this.ctx),this.fbTexObj=h.createTexture(),this.fbo=h.createFramebuffer(),p(i.size)?this.size=20:this.setSize(i.size),p(i.max)?T=null:this.setMax(i.max),p(i.min)?g=null:this.setMin(i.min),p(i.intensity)?this.intensity=1:this.setIntensity(i.intensity),p(i.translate)?this.translate=[0,0]:this.setTranslate(i.translate),p(i.zoom)?this.zoom=1:this.setZoom(i.zoom),p(i.angle)?this.angle=0:this.setRotationAngle(i.angle),p(i.opacity)?this.opacity=1:this.setOpacity(i.opacity),this.gradient=y(i.gradient),this.ratio=n,i.backgroundImage&&i.backgroundImage.url&&this.setBackgroundImage(i.backgroundImage),this.heatmapData=[],this.ctx.viewport(0,0,this.ctx.canvas.width,this.ctx.canvas.height)}catch(t){console.error(t)}}function w(){const t=this.ctx;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),h&&b.call(this,t,h),t.bindFramebuffer(t.FRAMEBUFFER,null),c&&R.call(this,t,c),P.call(this,t)}function b(t,e){t.useProgram(this.gradShadOP.program),this.min=null!==g?g:e?.minMax?.min??0,this.max=null!==T?T:e?.minMax?.max??0,this.gradShadOP.attr[0].data=e.posVec||[],this.gradShadOP.attr[1].data=e.rVec||[],t.uniform2fv(this.gradShadOP.uniform.u_resolution,new Float32Array([this.width*this.ratio,this.height*this.ratio])),t.uniform2fv(this.gradShadOP.uniform.u_translate,new Float32Array([this.translate[0],this.translate[1]])),t.uniform1f(this.gradShadOP.uniform.u_zoom,this.zoom?this.zoom:.01),t.uniform1f(this.gradShadOP.uniform.u_angle,this.angle),t.uniform1f(this.gradShadOP.uniform.u_density,this.ratio),t.uniform1f(this.gradShadOP.uniform.u_max,this.max),t.uniform1f(this.gradShadOP.uniform.u_min,this.min),t.uniform1f(this.gradShadOP.uniform.u_size,this.size),t.uniform1f(this.gradShadOP.uniform.u_intensity,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 R(t,e){const{x:r=0,y:o=0,width:i=0,height:n=0}=e;t.useProgram(this.imageShaOP.program),t.uniform2fv(this.imageShaOP.uniform.u_resolution,new Float32Array([this.width*this.ratio,this.height*this.ratio])),t.uniform2fv(this.imageShaOP.uniform.u_translate,new Float32Array([this.translate[0],this.translate[1]])),t.uniform1f(this.imageShaOP.uniform.u_zoom,this.zoom?this.zoom:.01),t.uniform1f(this.imageShaOP.uniform.u_angle,this.angle),t.uniform1f(this.imageShaOP.uniform.u_density,this.ratio),this.imageShaOP.attr[0].data=new Float32Array([r,o,r+i,o,r,o+n,r,o+n,r+i,o,r+i,o+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(this.imageShaOP.uniform.u_image,0),t.activeTexture(this.ctx.TEXTURE0),t.bindTexture(this.ctx.TEXTURE_2D,this.imageTexture),t.drawArrays(t.TRIANGLES,0,6)}function P(t){t.useProgram(this.colorShadOP.program),t.uniform4fv(this.colorShadOP.uniform.u_colorArr,this.gradient.value),t.uniform1f(this.colorShadOP.uniform.u_colorCount,this.gradient.length),t.uniform1fv(this.colorShadOP.uniform.u_offset,new Float32Array(this.gradient.offset)),t.uniform1f(this.colorShadOP.uniform.u_opacity,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(this.colorShadOP.uniform.u_framebuffer,0),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.fbTexObj),t.drawArrays(t.TRIANGLES,0,6)}function S(t){const e=this.zoom||.1,r=this.width/2,o=this.height/2,i=this.angle;let n=(t.x-r)/r*e,a=(t.y-o)/o*e;if(0!==i){const t=Math.cos(i),e=Math.sin(i),r=t*n-e*a;a=e*n+t*a,n=r}return n=n*r+r-this.translate[0],a=a*o+o-this.translate[1],t.x=n,t.y=a,{x:n,y:a}}return A.prototype.resize=function(){const t=this.dom.clientHeight,e=this.dom.clientWidth;this.layer.setAttribute("height",t*n),this.layer.setAttribute("width",e*n),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(h)},A.prototype.clear=function(){this.ctx.clear(this.ctx.COLOR_BUFFER_BIT|this.ctx.DEPTH_BUFFER_BIT)},A.prototype.setMax=function(t){if(p(t)||x(t))throw new Error("Invalid max: Expected Number");return T=t,this},A.prototype.setMin=function(t){if(p(t)||x(t))throw new Error("Invalid min: Expected Number");return g=t,this},A.prototype.setGradient=function(t){return this.gradient=y(t),this},A.prototype.setTranslate=function(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},A.prototype.setZoom=function(t){if(p(t)||x(t))throw new Error("Invalid zoom: Expected Number");return this.zoom=t,this},A.prototype.setRotationAngle=function(t){if(p(t)||x(t))throw new Error("Invalid Angle: Expected Number");return this.angle=t,this},A.prototype.setSize=function(t){if(p(t)||x(t))throw new Error("Invalid Size: Expected Number");return this.size=t,this},A.prototype.setIntensity=function(t){if(p(t)||x(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},A.prototype.setOpacity=function(t){if(p(t)||x(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},A.prototype.setBackgroundImage=function(t){const e=this;if(t.url)return d=this.ctx.getParameter(this.ctx.MAX_TEXTURE_SIZE),this.imageTexture=this.ctx.createTexture(),this.type="TEXTURE_2D",c=null,u=t.width||this.width,f=t.height||this.height,u=u>d?d:u,f=f>d?d:f,function(t,e,r){const o=new Image;o.crossOrigin="anonymous",o.onload=e,o.onerror=r,o.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),c={x:t.x||0,y:t.y||0,height:f,width:u,image:this},e.render()}),(function(t){throw new Error("Image Load Error",t)})),this},A.prototype.clearData=function(){this.heatmapData=[],h={},this.render()},A.prototype.addData=function(t,e){const r=this;for(let o=0;o<t.length;o++)e&&S.call(r,t[o]),this.heatmapData.push(t[o]);return this.renderData(this.heatmapData),this},A.prototype.renderData=function(t){if(t.constructor!==Array)throw new Error("Expected Array type");return h=function(t){const e=t.length;_!==e&&(a=new ArrayBuffer(8*e),l=new Float32Array(a),s=new ArrayBuffer(4*e),m=new Float32Array(s),_=e);const r={min:1/0,max:-1/0};for(let o=0;o<e;o++)l[2*o]=t[o].x,l[2*o+1]=t[o].y,m[o]=t[o].value,r.min>t[o].value&&(r.min=t[o].value),r.max<t[o].value&&(r.max=t[o].value);return{posVec:l,rVec:m,minMax:r}}(t),this.heatmapData=t,this.render(),this},A.prototype.render=function(){w.call(this)},A.prototype.projection=function(t){const e=this.zoom||.1,r=this.width/2,o=this.height/2,i=this.translate[0],n=this.translate[1],a=this.angle,s=this.width/this.height;let u=(t.x+i-r)/(r*e),f=(t.y+n-o)/(o*e);if(u*=s,0!==a){const t=Math.cos(-a),e=Math.sin(-a),r=t*u-e*f;f=e*u+t*f,u=r}return u*=1/s,u=u*r+r,f=f*o+o,{x:u,y:f}},new A(o,i)}}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).visualHeatmap=e()}(this,(function(){"use strict";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 f(){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&&l.call(this,t,this.hearmapExData),t.bindFramebuffer(t.FRAMEBUFFER,null),this.imageConfig&&c.call(this,t,this.imageConfig),m.call(this,t))}function l(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:f,u_max:l,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(f,this.ratio),t.uniform1f(l,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:f,u_image:l}=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(f,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(l,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:f}=u,l=document.createElement("canvas"),c=l.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),l.setAttribute("height",(h*this.ratio).toString()),l.setAttribute("width",(f*this.ratio).toString()),l.style.height=`${h}px`,l.style.width=`${f}px`,l.style.position="absolute",u.appendChild(l),this.ctx=c,this.width=f,this.height=h,this.imageConfig=null,this.configMin=null,this.configMax=null,this.hearmapExData={},this.layer=l,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(){f.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}}}return function(t,e){return new _(t,e)}}));
{
"name": "visual-heatmap",
"version": "2.0.1",
"version": "2.1.0",
"description": "\"Advanced Visual Heatmap - High Scale webGL based rendering.\"",
"module": "./dist/visualHeatmap.esm.js",
"main": "./dist/visualHeatmap.js",
"types": "./dist/types/main.d.ts",
"scripts": {

@@ -29,2 +30,8 @@ "dev": "rollup -wm -c rollup.config.js",

"license": "BSD-3-Clause",
"contributors": [
{
"name": "Mohit Kumar Toshniwal",
"email": "mohitkrtoshniwal@gmail.com"
}
],
"bugs": {

@@ -35,11 +42,18 @@ "url": "https://github.com/nswamy14/visual-heatmap/issues"

"devDependencies": {
"@babel/core": "^7.24.4",
"@babel/preset-env": "^7.24.4",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-eslint": "^9.0.5",
"@rollup/plugin-commonjs": "^22.0.2",
"@rollup/plugin-node-resolve": "^13.3.0",
"eslint": "^7.32.0",
"@rollup/plugin-typescript": "^11.1.6",
"@typescript-eslint/eslint-plugin": "^7.7.0",
"@typescript-eslint/parser": "^7.7.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^6.15.0",
"eslint-config-standard": "^14.1.1",
"rollup": "^2.79.1",
"rollup-plugin-terser": "^7.0.0"
"rollup-plugin-terser": "^7.0.0",
"tslib": "^2.6.2",
"typescript": "^5.4.4"
}
}

@@ -131,2 +131,5 @@ # Visual-Heatmap Js [![npm](https://img.shields.io/npm/v/visual-heatmap.svg)](https://www.npmjs.com/package/visual-heatmap) [![Downloads](https://img.shields.io/npm/dm/visual-heatmap.svg)](https://www.npmjs.com/package/visual-heatmap)

### instance.setGradient(gradient)
Api to set color gradient. Accepts array of objects with color value and offset.
### instance.setIntensity(number)

@@ -148,4 +151,7 @@ Api to set Intensity factor. Accepts float value as an input.

### instance.resize()
Api to rerender heatmep on parent container resizes.
### instance.clear()
Api to clear canvas.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc