/**
* This function sets the required properties to draw the heatmap.
* The heatmap itself is drawn by the javascript file "heatmap.js".
* This file needs a container of a canvas, where the heatmap-canvas is appended as a child.
* Furthermore a legend and a close-button are created.
* @param {Array} dataPoints contains the data in the following form:
<p>var nodes = [</p>
<p>x: 1</p>
<p>y: 0</p>
<p>comDistr: 0</p>
<p>]</p>
* @param {number} radius is the number which determines the radius of the drawn points in the heatmap
*/
function drawHeatMap(dataPoints,radius)
{
var normdataPoints = normalizeData(dataPoints);
console.log(normdataPoints)
var configObject = {
container: document.getElementById("svgContainer"),
maxOpacity: 0.8,
minOpacity: 0.0,
gradient: {
0.0: "#ffffff",
0.2: "#eff3ff",
0.4: "#c6dbef",
0.6: "#9ecae1",
0.8: "#6baed6",
1.0: "#3182bd"
},
radius: radius,
blur: 0.4,
};
var heatmapInstance = h337.create(configObject);
heatmapInstance.setData(normdataPoints);
// Add close Button to the heatmap-canvas
createCloseButton();
// Add gradient legend to the heatmap-canvas
createHeatmapLegend(configObject);
}
/**
* This functions normalizes the data, which means that all values are set between 0 and 100.
* @param {Array} dataP is the dataset which should be normalized
* @returns {{max: number, min: number, data: Array}} dataArray is the nomalized dataset
<p>var datapoint = [</p>
<p>x: 1</p>
<p>y: 0</p>
<p>value: 0</p>
<p>]</p>
The final data needed by heatmap.js is:
<p>var dataset = [</p>
<p>max: //maximum value</p>
<p>min: //minimum value</p>
<p>datapoint[]: /datapoint array</p>
<p>]</p>
*/
function normalizeData(dataP)
{
var max = -Infinity;
var min = Infinity;
var data = [];
//find min and max in data
for (var i = 0; i < dataP.length; i++)
{
if(dataP[i].comDistr > max)
{
max = dataP[i].comDistr;
}else if(dataP[i].comDistr < min)
{
min = dataP[i].comDistr;
}
}
//shift data betwenn 0 and 100
for (var i = 0; i < dataP.length; i++)
{
var newValue;
if(max != 0 && min !=0) //secure that no division through 0 happens
{
newValue = (1-0)*((dataP[i].comDistr-min)/(max-min))*100; //data itself between [0,1] but for drawing multiplied by 100
}else
{
newValue = dataP[i].comDistr;
}
data[i] = {
x: dataP[i].x,
y: dataP[i].y,
value: newValue
};
}
//calculate maximum value
var newMax = 0;
if(max=!0)
{
newMax = (1-0)*((max-min)/(max-min))*100;
}
//calculate minimum value
var newMin = 0;
if(max=!0)
{
newMin = Math.abs((1-0)*((min-min)/(max-min))*100);
}
var dataArray = {
max: newMax,
min: newMin,
data: data
}
return dataArray;
}
/**
* This function deletes all heatmap - canvases, which have been drawn.
* It searches the parent container of the heatmap and deletes all canvases which are labelled "heatmap-canvas"
*/
function deleteCanvas()
{
var canvasContainer = document.getElementById("svgContainer");
var canvasList = canvasContainer.childNodes;
var flagDelete = [];
//if a canvas is attached, delete it
for(var i = 0; i <canvasList.length; i++)
{
if(canvasList[i].className == "heatmap-canvas") {
flagDelete[i] = 1;
} else
{
flagDelete[i] = 0;
}
}
for(var i = 0; i <canvasList.length; i++)
{
if(flagDelete[i] == 1)
{
canvasContainer.removeChild(canvasList[i]);
}
if(canvasList[i].id == "closeButton") {
canvasContainer.removeChild(canvasList[i]);
}
if(canvasList[i].id == "heatMapLegend") {
canvasContainer.removeChild(canvasList[i]);
}
}
}
/**
* This function adds a close Button to the heatmap-canvas.
* Looks for the container of the canvas and creates a button in right corner.
* When pressed it deletes all heatmap-canvases, since it calls the function deleteCanvas().
*/
function createCloseButton()
{
var heatmapOverlay = document.getElementById("svgContainer");
// Button
var closeButton = document.createElement("SPAN");
closeButton.classList.add("w3-button");
closeButton.classList.add("w3-theme-l2");
closeButton.classList.add("w3-display-topright");
closeButton.setAttribute("id", "closeButton");
heatmapOverlay.appendChild(closeButton);
// Icon
var closeIcon = document.createElement("SPAN");
closeIcon.classList.add("fa");
closeIcon.classList.add("fa-remove");
closeIcon.classList.add("fa-lg");
closeButton.appendChild(closeIcon);
// Close function
closeButton.addEventListener("click", function() {deleteCanvas() });
}
/**
* This function adds a legend to the heatmap.
* It looks for the parent container of the heatmap and gives him a canvas as childNode.
* The canvas contains the gradient-color which is used in the heatmap.
*/
function createHeatmapLegend(configObject)
{
var heatmapOverlay = document.getElementById("svgContainer");
// Container
var legend = document.createElement("DIV");
legend.classList.add("w3-white");
legend.classList.add("w3-display-bottomleft");
legend.setAttribute("id", "heatMapLegend");
heatmapOverlay.appendChild(legend);
// Make Gradient Image
var legendCanvas = document.createElement('canvas');
legendCanvas.classList.add("w3-border");
legendCanvas.classList.add("w3-round-small");
legendCanvas.classList.add("w3-border-dark-grey");
legendCanvas.width = 100;
legendCanvas.height = 20;
var min = configObject.minOpacity;
var max = configObject.maxOpacity;
var legendCtx = legendCanvas.getContext('2d');
var gradientCfg = {};
gradientCfg = configObject.gradient;
var gradient = legendCtx.createLinearGradient(0, 0, 100, 1);
for (var key in gradientCfg) {
gradient.addColorStop(key, gradientCfg[key]);
}
legendCtx.fillStyle = gradient;
legendCtx.fillRect(0, 0, 100, 20);
//Append Image Container
var img = document.createElement("DIV");
legend.appendChild(img);
//Append Image
img.appendChild(legendCanvas);
//Append Text
var p_min=document.createElement("p");
p_min.classList.add("alignleft");
p_min.innerHTML = "0";
var p_max=document.createElement("p");
p_max.classList.add("alignright");
p_max.innerHTML = "1";
img.appendChild(p_min);
img.appendChild(p_max);
}