From 3b9242e2878507911fdfa33ce4b01e8e0264d903 Mon Sep 17 00:00:00 2001 From: linarphy Date: Thu, 25 Jan 2024 16:26:48 +0100 Subject: [PATCH] Add marker style and update drawing step --- lichartee.js | 300 +++++++++++++++++++++++++++++++++++++-------------- test.js | 23 ++-- 2 files changed, 233 insertions(+), 90 deletions(-) diff --git a/lichartee.js b/lichartee.js index 596bd01..b9a7b45 100644 --- a/lichartee.js +++ b/lichartee.js @@ -197,25 +197,42 @@ class Axes } /** - * plot y versus x as lines + * plot y versus x as line * * @param 1darray x x data * @param 1darray y y data - * @param object linestyle Object defining a style for a line. The - * structure of the object should be: - * { - * color: color - * style: style - * } - * where color is a string containing - * "rgb(x,y,z)", "#abcdef" or a name of - * a color, and style is "solid", "dotted", - * "dashdot" or "dashed". Default value is - * color = "black" and style = "solid" + * @param String linestyle style of the line (can be "solid", + * "dotted", "dashdot", "dashed" or "" + * for no line) + * @param String linecolor color of the line (can be "#abcdef", + * "rgb(x,y,z)" or a name of a color. + * @param String markerstyle style of the marker used for each + * point (can be "circle", "point", + * "small", "cross" or "" for no + * marker) + * @param String markercolor color of the marker (same + * definition than linecolor) + * @param Number markersize size of the marker */ - plot(x, y, linestyle = {color: "black", style: "solid"}) + plot( + x , + y , + linestyle = 'solid' , + linecolor = 'black' , + markerstyle = 'circle', + markercolor = 'black' , + markersize = 5 , + ) { - let line = new Line(x, y, linestyle); + let line = new Line( + x , + y , + linestyle = linestyle , + linecolor = linecolor , + markerstyle = markerstyle, + markercolor = markercolor, + markersize = markersize , + ); this.lines.push(line); } @@ -223,9 +240,9 @@ class Axes * render the axes to the canvas * * @param ctx CanvasRenderingContext2D Context of the canvas - * @param window 2darray Window where to draw the canvas + * @param view 2darray Window where to draw the canvas */ - draw(ctx, window) + draw(ctx, view) { const x_min = get_ext_array( this.lines.map( @@ -263,20 +280,20 @@ class Axes ) ) ); - let n_window = this.title.draw( + let n_view = this.title.draw( ctx , - window, + view, ); - n_window = this.axis.draw( + n_view = this.axis.draw( ctx , - n_window, + n_view, [ [x_min, y_min], [x_max, y_max] ], ); for (const index_line in this.lines) { this.lines[index_line].draw( ctx , - n_window, + n_view, [ [x_min, y_min], [x_max, y_max], @@ -287,9 +304,9 @@ class Axes ctx.strokeStyle = 'black'; ctx.setLineDash([]); ctx.strokeRect( - n_window[0][0], n_window[0][1], - n_window[1][0] - n_window[0][0], - n_window[1][1] - n_window[0][1], + n_view[0][0], n_view[0][1], + n_view[1][0] - n_view[0][0], + n_view[1][1] - n_view[0][1], ); } @@ -317,52 +334,62 @@ class Axes * * @property 1darray x xdata * @property 1darray y ydata - * @property object linestyle Object defining a style for a line. The - * structure of the object should be: - * { - * color: color - * style: style - * } - * where color is a string containing - * "rgb(x,y,z)", "#abcdef" or a name of - * a color, and style is "solid", "dotted", - * "dashdot" or "dashed". Default value is - * color = "black" and style = "solid" + * @property String linestyle style of the line (can be "solid", + * "dotted", "dashdot", "dashed" or "" + * for no line) + * @property String linecolor color of the line (can be "#abcdef", + * "rgb(x,y,z)" or a name of a color. + * @property String markerstyle style of the marker used for each + * point (can be "circle", "point", + * "small", "cross" or "" for no + * marker) + * @property String markercolor color of the marker (same + * definition than linecolor) + * @property Number markersize size of the marker */ class Line { /** * @param 1darray x xdata * @param 1darray y ydata - * @param object linestyle Object defining a style for a line. The - * structure of the object should be: - * { - * color: color - * style: style - * } - * where color is a string containing - * "rgb(x,y,z)", "#abcdef" or a name of - * a color, and style is "solid", "dotted", - * "dashdot" or "dashed". Default value is - * color = "black" and style = "solid" + * @param string linestyle style of the line (can be "solid", + * "dotted", "dashdot", "dashed" or "" + * for no line) + * @param string linecolor color of the line (can be "#abcdef", + * "rgb(x,y,z)" or a name of a color. + * @param string markerstyle style of the marker used for each + * point (can be "circle", "point", + * "small", "cross" or "" for no + * marker) + * @param string markercolor color of the marker (same + * definition than linecolor) + * @param Number markersize size of the marker */ constructor( - x , - y , - linestyle = {color: "black", style: "solid"}, + x , + y , + linestyle = 'solid' , + linecolor = 'black' , + markerstyle = 'circle' , + markercolor = 'black' , + markersize = 5 , ) { - this.x = x ; - this.y = y ; - this.linestyle = linestyle ; + this.x = x ; + this.y = y ; + this.linestyle = linestyle ; + this.linecolor = linecolor ; + this.markerstyle = markerstyle; + this.markercolor = markercolor; + this.markersize = markersize ; } /** * draw the line in the box coordinate * - * @param CanvasRenderingContext2d ctx Context of the canvas - * @param 2dlist box Box where to draw the line - * @param 2dlist view Scale of the box (link value <-> + * @param CanvasRenderingContext2d ctx context of the canvas + * @param 2dlist box box where to draw the line + * @param 2dlist view scale of the box (link value <-> * coordinate */ draw(ctx, box, view) @@ -390,19 +417,52 @@ class Line ); } ); - if (this.linestyle.style === 'solid') + if (this.linestyle != '') + { + this.drawLine( + ctx, + x_coordinates, + y_coordinates, + ); + } + if (this.markerstyle != '') + { + this.drawPoints( + ctx , + x_coordinates, + y_coordinates, + ); + } + } + + /** + * draw a line in the given context at the given positions + * + * @param CanvasRenderingContext2d ctx context of the canvas + * @param 1darray x_coordinates X coordinates of the point + * @param 1darray y_coordinates Y coordinates of the point + */ + drawLine(ctx, x_coordinates, y_coordinates) + { + ctx.beginPath(); + ctx.strokeStyle = this.linecolor; + ctx.moveTo( + x_coordinates[0], + y_coordinates[0], + ); + if (this.linestyle === 'solid') { ctx.setLineDash([]); } - else if (this.linestyle.style === 'dashed') + else if (this.linestyle === 'dashed') { ctx.setLineDash([15, 5]); } - else if (this.linestyle.style === 'dotted') + else if (this.linestyle === 'dotted') { ctx.setLineDash([2,2]); } - else if (this.linestyle.style === 'dashdot') + else if (this.linestyle === 'dashdot') { ctx.setLineDash([15,2,2,2]); } @@ -410,21 +470,102 @@ class Line { throw _('the style of the line is not correctly defined'); } - ctx.strokeStyle = this.linestyle.color; - ctx.beginPath(); - ctx.moveTo( - x_coordinates[0], - y_coordinates[0] - ); for (const index in x_coordinates) { ctx.lineTo( x_coordinates[index], - y_coordinates[index] + y_coordinates[index], ); } ctx.stroke(); } + + /** + * draw points in the given context at the given positions + * + * @param CanvasRenderingContext2d ctx context of the canvas + * @param 1darray x_coordinates x coordinate of the point + * @param 1darray y_coordinates y coordinate of the point + */ + drawPoints(ctx, x_coordinates, y_coordinates) + { + for (const index in x_coordinates) + { + let x = x_coordinates[index]; + let y = y_coordinates[index]; + ctx.beginPath(); + if (this.markerstyle == 'circle') + { + ctx.fillStyle = this.markercolor; + ctx.ellipse( + x , + y , + this.markersize, + this.markersize, + 0 , + 0 , + 2*Math.PI , + ); + ctx.fill(); + } + else if (this.markerstyle == 'point') + { + ctx.fillStyle = this.markercolor; + ctx.ellipse( + x , + y , + 0.5*this.markersize, + 0.5*this.markersize, + 0 , + 0 , + 2*Math.PI , + ); + ctx.fill(); + } + else if (this.markerstyle == 'small') + { + ctx.fillStyle = this.markercolor; + ctx.ellipse( + x , + y , + 0.1*this.markersize, + 0.1*this.markersize, + 0 , + 0 , + 2*Math.PI , + ); + ctx.fill(); + } + else if (this.markerstyle == 'cross') + { + ctx.setLineDash([]); + ctx.strokeStyle = this.markercolor; + ctx.moveTo( + x - this.markersize, + y - this.markersize, + ); + ctx.lineTo( + x + this.markersize, + y + this.markersize, + ); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo( + x + this.markersize, + y - this.markersize, + ); + ctx.lineTo( + x - this.markersize, + y + this.markersize, + ); + ctx.stroke(); + } + else + { + throw _('the style of the marker is not correctly defined'); + } + } + } } /** @@ -494,27 +635,29 @@ class Title * draw the title in the given windows * * @param ctx CanvasRenderingContext2D Context of the canvas - * @param window int Window where to write the title on + * @param box int Window where to write the title on * - * @return plot_windows int New windows for the plot + * @return plot_box int New windows for the plot */ - draw(ctx, window) + draw(ctx, box) { ctx.font = this.font.toString(); + ctx.fillStyle = 'black'; + ctx.strokeStyle = 'black'; let width = ctx.measureText(this.content).width; - if (width > window[1][0] - window[0][0] + 2 * this.margin) + if (width > box[1][0] - box[0][0] + 2 * this.margin) { ctx.fillText( this.content , - window[0][0] , + box[0][0] , this.font.size + this.margin, - window[1][0] - window[0][0], + box[1][0] - box[0][0], ); } else { - let text_position = window[0][0] + ( - window[1][0] - window[0][0] - width + let text_position = box[0][0] + ( + box[1][0] - box[0][0] - width ) / 2 ctx.fillText( this.content, @@ -524,10 +667,10 @@ class Title } return [ [ - window[0][0], - window[0][1] + this.font.size + 2 * this.margin, + box[0][0], + box[0][1] + this.font.size + 2 * this.margin, ], - [window[1][0], window[1][1]], + [box[1][0], box[1][1]], ]; } } @@ -574,6 +717,8 @@ class Axis */ draw(ctx, window, view) { + ctx.strokeStyle = 'black'; + ctx.fillStyle = 'black'; let index = 0; let start_pos = window[0][1]; let padding = ( @@ -588,7 +733,6 @@ class Axis view[1][1] - index * step ).toString().slice(0,3); let text_position = current_y + this.text_height / 2 - ctx.strokeStyle = 'black'; ctx.beginPath(); ctx.moveTo( window[0][0] + this.margin + width, diff --git a/test.js b/test.js index f2ed22f..4cae009 100644 --- a/test.js +++ b/test.js @@ -3,12 +3,11 @@ let manager = new Manager( ); manager.add_canvas(1000, 500); manager.add_canvas(1000, 500).figure.add_axes().plot( - [0,1,2,3,4,5] , - [0,1,4,9,16,25], - { - color: 'rgb(255,0,0)', - style: 'dashed' - } + [0,1,2,3,4,5] , + [0,1,4,9,16,25] , + linestyle = 'dashed' , + linecolor = 'rgb(255,0,0)', + markerstyle = 'cross' , ); manager.list_canvas[0].figure.list_axes[0].title = 'squared and x2'; manager.list_canvas[0].figure.list_axes[0].plot( @@ -16,12 +15,12 @@ manager.list_canvas[0].figure.list_axes[0].plot( [0,2,4,6,8,10] ); manager.list_canvas[0].figure.add_axes().plot( - [2,4,6,8,10], - [1/2,1/4,1/6,1/8,1/10], - { - color: 'rgb(0,255,0)', - style: 'dashdot' - } + [2,4,6,8,10] , + [1/2,1/4,1/6,1/8,1/10] , + linestyle = 'dashdot' , + linecolor = 'rgb(0,255,0)', + markerstyle = 'circle' , + markercolor = 'rgb(0,0,255)', ); manager.list_canvas[0].figure.list_axes[0].title = '1/x'; manager.draw();