The following code is enhanced Graph class with axis labels, legend and possibility to draw multiple values on one graph:
<!DOCTYPE html><meta charset="utf-8"><!-- University of Maribor --><!-- Cybernetics & Decision Support Systems Laboratory --><!-- Faculty of Organizational Sciences --><!-- Andrej Škraba 2019 --><html><head><title> Example with graph </title> </head> <body onload="load();">Example with graph<br><canvas id="canvas1" width="200" height="100" style="border:1px dashed #00c3c3"></canvas><br><canvas id="canvas2" width="200" height="100" style="border:1px dashed #00c3c3"></canvas><br><canvas id="canvas3" width="200" height="100" style="border:1px dashed #00c3c3"></canvas><br><script type="text/javascript">"use strict"; // enable classes var graph1; // variable for first graph objectvar graph2; // variable for second graph objectvar graph3; // variable for third graph object var yValue1 = new Array(); // array for variables that we will plotvar yValue2 = new Array(); // array for variables that we will plotvar yValue3 = new Array(); // array for variables that we will plot class Graph { constructor(canvasId, minGraphX, maxGraphX, minGraphY, maxGraphY, color, legend, axisDescription) { // pri konstruktorju moramo podati ID platna, ki ga sicer ustvarimo v html-ju this.canvas = document.getElementById(canvasId); this.ctx = this.canvas.getContext("2d"); this.canvasWidth = this.canvas.width; // mind capital W at Width this.canvasHeight = this.canvas.height; // mind capital H at Height this.x = new Array(); // create new Array x this.y = new Array(); this.rangeX = maxGraphX - minGraphX; this.rangeY = maxGraphY - minGraphY; // create y array (size) according to the color vector (could have multiple rows i.e. 2d) for( var i=0; i<color.length; i++ ) { this.y.push([]); // example of three row array init. would be: this.y = [[],[],[]]; } this.minGraphX = minGraphX; this.maxGraphX = maxGraphX; this.minGraphY = minGraphY; this.maxGraphY = maxGraphY; this.color = color; // color of the graph this.legend = legend; this.axisDescription = axisDescription; // fill x vector; vector y is filled in real-time for (var i=0; i<this.maxGraphX+1; i++) { this.x[i] = i; // values for the x coordinate; 0, 1, 2, ... } } addValueOrCutAndAdd(yValue) { if (this.y[0].length == this.maxGraphX+1) { // if canvas size is 10x10 we have 11x11 points (starting with 0 and ending with 10) for (var i = 0; i < yValue.length; i++) { // v zanki gremo po polju yInput in na mestu 0 eno vrednost odrežemo, na koncu pa eno mesto dodamo - zapišemo novo vrednost yInput this.y[i].splice(0, 1); // on the position 0 in the vector y we cut one value this.y[i][this.maxGraphX] = yValue[i]; // at the end of the array the new value is added } } else { for (var i = 0; i < yValue.length; i++) { // z zanko gremo po vseh vrsticah za matrike y this.y[i].push(yValue[i]); // if the array is not yet full, we push the new value in the array / vrednost v oklepaju [] t.j. index je za ena večji; npr., če imamo eno vrednost je indeks [0], length pa 1 } } } plot(yValue) { this.addValueOrCutAndAdd(yValue); this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); // clear the canvas for (var i=0; i < yValue.length; i++) { // zanka, ki gre po vrsticah y matrike this.ctx.strokeStyle = this.color[i]; // determine color this.ctx.beginPath(); // for the start of the line for (var j=0; j<this.y[0].length; j++) { this.ctx.lineTo(this.x[j]/this.rangeX*this.canvasWidth, (this.canvasHeight - ((this.y[i][j]-this.minGraphY)/this.rangeY) * this.canvasHeight)); // for y values we multiply with canas height, eg. 0.25 * 100 = 25 } this.ctx.stroke(); } // add legend for( var i=0; i<this.legend.length; i++ ) { // legend and color should be of the same size this.ctx.font = "11px Arial"; this.ctx.fillText(this.legend[i], 49+i*54, 10); this.ctx.strokeStyle = this.color[i]; this.ctx.beginPath(); // beginning of the short line for the legend this.ctx.lineTo(37+i*54, 6); this.ctx.lineTo(46+i*54, 6); this.ctx.stroke(); } // add axis descritions this.ctx.fillText("<-" + this.axisDescription[0] + "|" + this.axisDescription[1] + "->", 150, 95) this.ctx.fillText(this.axisDescription[2], 5, 95); this.ctx.fillText(this.axisDescription[3], 5, 11); }} function loop() { yValue1[0] = Math.random()*0.1+0.8; yValue1[1] = Math.random()*0.2; yValue1[2] = Math.random()*0.5+0.25; graph1.plot(yValue1); var RND = -Math.random()*2+Math.random(); graph2.plot([RND]); graph2.ctx.fillText(RND.toFixed(2),150,17); graph3.plot([Math.random()*0.10+0.70, 0.2*Math.random()+0.2]); var timerVar = setTimeout(loop, 10); // each 10 ms function loop is repeated} function load () { graph1 = new Graph("canvas1", 0, 200, 0, 1, ["red", "green", "blue"], ["desired", "actual", "bRND"], ["0", "200", "0", "1"]); // arguments: Arg1: canvasId, Arg2: maxX, Arg3: maxY, Arg4: [vector of colors]; this determines the size of yValue matrix (if we state one color as eg. ["red"], we assume only one time series, ["red", "green", "blue"] -> three time series) graph2 = new Graph("canvas2", 0, 200, -2, 1, ["blue"], ["blue RND"], ["0", "200", "-2", "1"]); graph3 = new Graph("canvas3", 0, 200, 0, 1, ["yellow", "orange"], ["yRND", "oRND"], ["0", "200", "0", "1"]); loop(); }</script></body> </html>The result in browser is:
Add two new graphs, one with one time series and another with two. The result should be: