CyberChef/src/core/lib/canvascomponents.js

185 lines
6.4 KiB
JavaScript
Executable File

"use strict";
/**
* Various components for drawing diagrams on an HTML5 canvas.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*
* @constant
* @namespace
*/
var CanvasComponents = module.exports = {
drawLine: function(ctx, startX, startY, endX, endY) {
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.closePath();
ctx.stroke();
},
drawBarChart: function(canvas, scores, xAxisLabel, yAxisLabel, numXLabels, numYLabels, fontSize) {
fontSize = fontSize || 15;
if (!numXLabels || numXLabels > Math.round(canvas.width / 50)) {
numXLabels = Math.round(canvas.width / 50);
}
if (!numYLabels || numYLabels > Math.round(canvas.width / 50)) {
numYLabels = Math.round(canvas.height / 50);
}
// Graph properties
var ctx = canvas.getContext("2d"),
leftPadding = canvas.width * 0.08,
rightPadding = canvas.width * 0.03,
topPadding = canvas.height * 0.08,
bottomPadding = canvas.height * 0.15,
graphHeight = canvas.height - topPadding - bottomPadding,
graphWidth = canvas.width - leftPadding - rightPadding,
base = topPadding + graphHeight,
ceil = topPadding;
ctx.font = fontSize + "px Arial";
// Draw axis
ctx.lineWidth = "1.0";
ctx.strokeStyle = "#444";
CanvasComponents.drawLine(ctx, leftPadding, base, graphWidth + leftPadding, base); // x
CanvasComponents.drawLine(ctx, leftPadding, base, leftPadding, ceil); // y
// Bar properties
var barPadding = graphWidth * 0.003,
barWidth = (graphWidth - (barPadding * scores.length)) / scores.length,
currX = leftPadding + barPadding,
max = Math.max.apply(Math, scores);
// Draw bars
ctx.fillStyle = "green";
for (var i = 0; i < scores.length; i++) {
var h = scores[i] / max * graphHeight;
ctx.fillRect(currX, base - h, barWidth, h);
currX += barWidth + barPadding;
}
// Mark x axis
ctx.fillStyle = "black";
ctx.textAlign = "center";
currX = leftPadding + barPadding;
if (numXLabels >= scores.length) {
// Mark every score
for (i = 0; i <= scores.length; i++) {
ctx.fillText(i, currX, base + (bottomPadding * 0.3));
currX += barWidth + barPadding;
}
} else {
// Mark some scores
for (i = 0; i <= numXLabels; i++) {
var val = Math.ceil((scores.length / numXLabels) * i);
currX = (graphWidth / numXLabels) * i + leftPadding;
ctx.fillText(val, currX, base + (bottomPadding * 0.3));
}
}
// Mark y axis
ctx.textAlign = "right";
var currY;
if (numYLabels >= max) {
// Mark every increment
for (i = 0; i <= max; i++) {
currY = base - (i / max * graphHeight) + fontSize / 3;
ctx.fillText(i, leftPadding * 0.8, currY);
}
} else {
// Mark some increments
for (i = 0; i <= numYLabels; i++) {
val = Math.ceil((max / numYLabels) * i);
currY = base - (val / max * graphHeight) + fontSize / 3;
ctx.fillText(val, leftPadding * 0.8, currY);
}
}
// Label x axis
if (xAxisLabel) {
ctx.textAlign = "center";
ctx.fillText(xAxisLabel, graphWidth / 2 + leftPadding, base + bottomPadding * 0.8);
}
// Label y axis
if (yAxisLabel) {
ctx.save();
var x = leftPadding * 0.3,
y = graphHeight / 2 + topPadding;
ctx.translate(x, y);
ctx.rotate(-Math.PI / 2);
ctx.textAlign = "center";
ctx.fillText(yAxisLabel, 0, 0);
ctx.restore();
}
},
drawScaleBar: function(canvas, score, max, markings) {
// Bar properties
var ctx = canvas.getContext("2d"),
leftPadding = canvas.width * 0.01,
rightPadding = canvas.width * 0.01,
topPadding = canvas.height * 0.1,
bottomPadding = canvas.height * 0.3,
barHeight = canvas.height - topPadding - bottomPadding,
barWidth = canvas.width - leftPadding - rightPadding;
// Scale properties
var proportion = score / max;
// Draw bar outline
ctx.strokeRect(leftPadding, topPadding, barWidth, barHeight);
// Shade in up to proportion
var grad = ctx.createLinearGradient(leftPadding, 0, barWidth + leftPadding, 0);
grad.addColorStop(0, "green");
grad.addColorStop(0.5, "gold");
grad.addColorStop(1, "red");
ctx.fillStyle = grad;
ctx.fillRect(leftPadding, topPadding, barWidth * proportion, barHeight);
// Add markings
var x0, y0, x1, y1;
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.font = "13px Arial";
for (var i = 0; i < markings.length; i++) {
// Draw min line down
x0 = barWidth / max * markings[i].min + leftPadding;
y0 = topPadding + barHeight + (bottomPadding * 0.1);
x1 = x0;
y1 = topPadding + barHeight + (bottomPadding * 0.3);
CanvasComponents.drawLine(ctx, x0, y0, x1, y1);
// Draw max line down
x0 = barWidth / max * markings[i].max + leftPadding;
x1 = x0;
CanvasComponents.drawLine(ctx, x0, y0, x1, y1);
// Join min and max lines
x0 = barWidth / max * markings[i].min + leftPadding;
y0 = topPadding + barHeight + (bottomPadding * 0.3);
x1 = barWidth / max * markings[i].max + leftPadding;
y1 = y0;
CanvasComponents.drawLine(ctx, x0, y0, x1, y1);
// Add label
if (markings[i].max >= max * 0.9) {
ctx.textAlign = "right";
x0 = x1;
} else if (markings[i].max <= max * 0.1) {
ctx.textAlign = "left";
} else {
x0 = x0 + (x1 - x0) / 2;
}
y0 = topPadding + barHeight + (bottomPadding * 0.8);
ctx.fillText(markings[i].label, x0, y0);
}
},
};