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.common.tooltips.js"></script> <script src="RGraph.line.js"></script> <!-- The canvas tag --> <canvas id="cvs" width="650" height="250" 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" />
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: {
spline: false,
shadow: false,
yaxisScaleMax: 400,
colors: ['pink', 'cyan'],
textColor: '#ccc',
xaxis: false,
yaxis: false,
linewidth: 3,
tickmarksSize: 7,
backgroundGridColor: '#666',
backgroundGridDashed: true,
marginLeft: 75,
marginBottom: 50,
yaxisScaleUnitsPost: 'k',
xaxisLabels: ['Rich','Holly','Kevin','Bea','Gary','Pob','Luis','Jim'],
xaxisLabelsOffsety: 5,
textSize: 20,
tooltips: '%{table}',
tooltipsCss: {
border: '3px solid #999'
},
tooltipsPointerCss: {
borderBottom: '3px solid #999',
borderRight: '3px solid #999'
},
tooltipsPointerOffsety: -2,
tooltipsFormattedTableData: [
[
['Time: ', 'Rich'],
['Date: ', '23rd June 1978'],
['Price: ', '$200 .43512']
],
[
['Person: ', 'Holly'],
['Date: ', '23rd June 1978'],
['Price: ', '$300.1945']
],
[
['Person: ','Kevin'],
['Date: ', '23rd June 1978'],
['Price: ', '$200.4956']
],
[
['Time: ', 'Bea'],
['Date: ', '23rd June 1978'],
['Price: ', '$300.4355']
],
[
['Person: ', 'Gary'],
['Date: ', '23rd June 1978'],
['Price: ', '$225.1358']
],
[
['Person: ', 'Pob'],
['Date: ', '23rd June 1978'],
['Price: ', '$350.4677']
],
[
['Person: ', 'Luis'],
['Date: ', '23rd June 1978'],
['Price: ', '$250.8465']
],
[
['Person: ', 'Jim'],
['Date: ', '23rd June 1978'],
['Price: ', '$200.1594']
],
[
['Time: ', 'Rich'],
['Date: ', '30th June 1978'],
['Price: ', '$200.43512']
],
[
['Person: ', 'Holly'],
['Date: ', '30th June 1978'],
['Price: ', '$110.1945']
],
[
['Person: ','Kevin'],
['Date: ', '30th June 1978'],
['Price: ', '$280.4956']
],
[
['Time: ', 'Bea'],
['Date: ', '30th June 1978'],
['Price: ', '$290.4355']
],
[
['Person: ', 'Gary'],
['Date: ', '30th June 1978'],
['Price: ', '$250.1358']
],
[
['Person: ', 'Pob'],
['Date: ', '30th June 1978'],
['Price: ', '$350.4677']
],
[
['Person: ', 'Luis'],
['Date: ', '30th June 1978'],
['Price: ', '$310.8465']
],
[
['Person: ', 'Jim'],
['Date: ', '30th June 1978'],
['Price: ', '$110.1594']
]
],
events: {
draw: function (obj)
{
// Use different sets of coordinates depending on
// whether a spline has been requested or not
var coordinates = obj.properties.spline ? obj.coordsSpline : obj.coords2;
// First, fill the bits which appear ABOVE the cyan
// (the first) line
// Clip the canvas to the the top part of the
// canvas
//
var p1 = [obj.canvas.width - obj.properties.marginRight, obj.properties.marginTop];
var p2 = [obj.properties.marginLeft, obj.properties.marginTop];
RGraph.clipTo.start(obj, [p1,p2].concat(coordinates[0]));
// Begin drawing the lines
obj.path('b');
// Create a path from the first line
RGraph.pathLine(obj.context, coordinates[0]);
// Add the second line to the path in reverse
// order
RGraph.pathLine(obj.context, coordinates[1], false, true);
// Set the globalAlpha and then fill the shape
// that has just been drawn
obj.path('ga 0.5 f purple');
// Reset the canvas
RGraph.clipTo.end();
// Second, fill the bits which appear BELOW the cyan
// (the first) line.
// Clip to the bottom bit of the canvas - below the
// first line.
var p3 = [obj.canvas.width - obj.properties.marginRight, obj.canvas.height - obj.properties.marginBottom];
var p4 = [obj.properties.marginLeft, obj.canvas.height - obj.properties.marginBottom];
RGraph.clipTo.start(obj, [p3,p4].concat(coordinates[0]));
// Draw both of the lines
obj.path('b');
RGraph.pathLine(obj.context, coordinates[0]);
RGraph.pathLine(obj.context, coordinates[1], false, true);
obj.path('ga 0.5 f green');
// Reset the canvas
RGraph.clipTo.end();
//
// 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 middle colored black.
for (var i=0; i<2; ++i) {
var coords = coordinates[i];
// Redraw the lines
RGraph.drawLine(
obj.context,
coords,
null,
obj.properties.colors[i],
(typeof obj.properties.linewidth === 'object'
? obj.properties.linewidth[i]
: obj.properties.linewidth),
null
);
// Draw the tickmarks for the line if necessary
if (obj.properties.tickmarksSize > 0) {
for (var j=0; j<coords.length; j+=(obj.properties.spline ? 10 : 1)) {
var x = coords[j][0];
var y = coords[j][1];
// Draw a donut in the line color. The center of
// the donut is colored black.
obj.path(
"b a % % % % % false f % b a % % % % % false f black",
x, y, obj.properties.tickmarksSize, 0, 6.29,
obj.properties.colors[i],
x, y, obj.properties.tickmarksSize - 3, 0, 6.29
);
}
}
}
}
}
}
}).wave({frames: 120});
</script>
A spline (smoothed) version
It's possible to get a spline version of the above by changing the obj.coords2 variable to obj.coordsSpline and adding spline: true to the chart 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