A new example of a filled Line chart with alternating colors
Written by Richard Heyes, RGraph author, on 23rd July 2023Introduction
Here's a novel, if not terribly useful, example of a filledLine chart
where the fill color is different above the first line (the pink line) to the fill color below the line. The demo that the code produces is also adjustable so you can drag the lines up and down and the fill color changes appropriately. There's two demos available: one is angular (like the chart that you can see at the CodePen link) and the other is a spline
(smooth and curvy). This chart was requested on another Open Source charting library's support forum.
The code is not at all insubstantial and, at this time, does require a few new functions that are currently only available in unreleased versions of the RGraph libraries. These libraries are, however, available via GitHub so here's some links to them (and also the demo files) so that you can get hold of them:
The HTML markup
This is the html
code that's used to show the chart. Note that the html
includes label
and input
tags that you don't need if you don't want to allow people to switch between adjustable and static modes.
<!-- Include the relevant RGraph libraries --> <script src="RGraph.common.core.js"></script> <script src="RGraph.common.dynamic.js"></script> <script src="RGraph.line.js"></script> <!-- The canvas tag --> <canvas id="cvs" width="750" height="350" style="background-color: black">[No canvas support]</canvas><br /> <!-- The HTML tags for the checkbox underneath the chart. If you don't want the chart to be adjustable then these are not required --> <label for="checkboxAdjustable"> <span style="font-size: 30pt">Adjustable</span> </label> <input type="checkbox" value="1" id="checkboxAdjustable" onchange="line.set('adjustable', this.checked); RGraph.redraw()" style="width: 35px; height: 35px" checked />
The JavaScript code
This is the options
section) is quite straight-forward - all the magic happens in the draw
event.
<script> line = new RGraph.Line({ id: 'cvs', data: [ [200,300,200,300,350,250,200,225], [200,110,280,290,250,350,310,110] ], options: { shadow: false, yaxisScaleMax: 400, colors: ['pink', 'cyan'], textColor: '#ccc', xaxis: false, yaxis: false, linewidth: 3, tickmarkSize: 7, backgroundGridColor: '#666', backgroundGridDashed: true, marginLeft: 75, marginBottom: 50, yaxisScaleUnitsPost: 'k', xaxisLabels: ['Rich','Holly','Kevin','Bea','Gary','Pob','Luis','Jim'], xaxisLabelsOffsety: 5, textSize: 20, // Set this to false if you dson't want the chart to be adjustable adjustable: true } }).on('draw', function (obj) { // First, fill the bits which appear ABOVE the cyan // (the first) line obj.path('sa'); // Clip to the top bit of the canvas - above the first // line obj.path('b m % % l % %', obj.canvas.width - obj.properties.marginRight, obj.properties.marginTop, obj.properties.marginLeft, obj.properties.marginTop ); // Path the line - the RGraph.pathLine() function // is a shortcut function for creating a // path from an array of X/Y coordinate pairs RGraph.pathLine({ context: obj.context, coords: obj.coords2[0], moveto: false }); // Now clip the canvas to the path that has just // been created. obj.path('cl'); // Begin drawing the lines obj.path('b'); // Create a path from the first line RGraph.pathLine({ context: obj.context, coords: obj.coords2[0] }); // Add the second line to the path in reverse // order RGraph.pathLine({ context: obj.context, coords: obj.coords2[1], moveto: false, reverse: true }); // Set the globalAlpha and then fill the shape // that has just been drawn obj.path('ga 0.5 f purple'); // Reset the canvas obj.path('rs'); // Second, fill the bits which appear BELOW the cyan // (the first) line. obj.path('sa'); // Clip to the bottom bit of the canvas - below the // first line. obj.path('b m % % l % %', obj.canvas.width - obj.properties.marginRight, obj.canvas.height - obj.properties.marginBottom, obj.properties.marginLeft, obj.canvas.height - obj.properties.marginBottom ); RGraph.pathLine({ context: obj.context, coords: obj.coords2[0], moveto: false }); // Clip the canvas obj.path('cl'); // Draw both of the lines obj.path('b'); RGraph.pathLine({ context: obj.context, coords: obj.coords2[0] }); RGraph.pathLine({ context: obj.context, coords: obj.coords2[1], moveto: false, reverse: true }); // Set the globalAlpha and fill the shape in a green // color obj.path('ga 0.5 f green'); // Reset the canvas obj.path('rs'); // // Now, because the fills that were done above appear // a little bit over the lines, draw the lines again // along with the tickmarks. // // Add a custom tickmark - just a regular circle // with the center colored black for (var i=0; i<2; ++i) { var coords = obj.coords2[i]; // Redraw the lines RGraph.drawLine({ context: obj.context, coords: coords, linewidth: typeof obj.properties.linewidth === 'object' ? obj.properties.linewidth[i] : obj.properties.linewidth, stroke: obj.properties.colors[i] }); // Draw the tickmarks for the line for (var j=0; j<coords.length; ++j) { var x = coords[j][0]; var y = coords[j][1]; // Draw a big circle in the line color obj.path( "b a % % % % % false f %", x, y, obj.properties.tickmarkSize, 0, 6.29, obj.properties.colors[i] ); // Draw a smaller circle over the above circle // with a smaller radius so that it appears // like a donut shaped tickmark obj.path( "b a % % % % % false f %", x, y, obj.properties.tickmarkSize - 3, 0, 6.29, 'black' ); } } }).draw(); </script>
A spline (smoothed) version
It's possible to get a spline
version of the above by, quite simply, changing the obj.coords2
variable to obj.coordsSpline
and adding spline: true
to the charts configuration. Also change the for
loop that redraws the tickmarks to only draw every tenth iteration - otherwise you'll see a lot of tickmarks! As simple as that!
Working demos
From version 6.14
a working demo is available in the demos/
folder of the download archive called line-alternate-fills.html