123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- "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
- */
- const CanvasComponents = {
- 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);
- }
- },
- };
- export default CanvasComponents;
|