score:2
well you can try something (ugly) like this, there is a comment in the snippet where the gradient is defined.
surely the colors and composition of the gradient can be determined by input properties like you want. also, one could play with the gradient position or make a radial gradient instead of a linear one.
one last thing, this snippet can really be improved, basically what i did is to identify how the chart is drawn by the library and in which part of it's lifecycle is done, then i copy it into a plugin and replace the solid background color for a canvas linear gradient ;)
to improve the snippet i would start by trying to use the methods defined inside the chart
object (like lineto()
or drawarea()
) instead of copying them inside the plugin, then implement the options defined inside the options
object to create the linear gradient.
var ctx = document.getelementbyid("chart").getcontext("2d");
var scatterchart = new chart(ctx, {
type: "line",
data: {
datasets: [{
label: " dataset",
data: [{
x: 1,
y: 10
},
{
x: 2,
y: 50
},
{
x: 3,
y: 88
},
{
x: 4,
y: 5
}
]
}]
},
options: {
scales: {
xaxes: [{
type: "linear",
position: "bottom"
}]
}
},
plugins: [{
beforedatasetdraw: function(chart, options) {
var metasets = chart._getsortedvisibledatasetmetas();
var ctx = chart.ctx;
var meta, i, el, view, points, mapper, color;
var cliparea = (ctx, area) => {
ctx.save();
ctx.beginpath();
ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
ctx.clip();
};
var uncliparea = (ctx) => {
ctx.restore();
};
var isdrawable = (point) => {
return point && !point.skip;
}
var lineto = (ctx, previous, target, flip) => {
var stepped = target.steppedline;
if (stepped) {
if (stepped === 'middle') {
var midpoint = (previous.x + target.x) / 2.0;
ctx.lineto(midpoint, flip ? target.y : previous.y);
ctx.lineto(midpoint, flip ? previous.y : target.y);
} else if ((stepped === 'after' && !flip) || (stepped !== 'after' && flip)) {
ctx.lineto(previous.x, target.y);
} else {
ctx.lineto(target.x, previous.y);
}
ctx.lineto(target.x, target.y);
return;
}
if (!target.tension) {
ctx.lineto(target.x, target.y);
return;
}
ctx.beziercurveto(
flip ? previous.controlpointpreviousx : previous.controlpointnextx,
flip ? previous.controlpointpreviousy : previous.controlpointnexty,
flip ? target.controlpointnextx : target.controlpointpreviousx,
flip ? target.controlpointnexty : target.controlpointpreviousy,
target.x,
target.y);
}
var drawarea = (ctx, curve0, curve1, len0, len1) => {
var i, cx, cy, r;
if (!len0 || !len1) {
return;
}
// building first area curve (normal)
ctx.moveto(curve0[0].x, curve0[0].y);
for (i = 1; i < len0; ++i) {
lineto(ctx, curve0[i - 1], curve0[i]);
}
if (curve1[0].angle !== undefined) {
cx = curve1[0].cx;
cy = curve1[0].cy;
r = math.sqrt(math.pow(curve1[0].x - cx, 2) + math.pow(curve1[0].y - cy, 2));
for (i = len1 - 1; i > 0; --i) {
ctx.arc(cx, cy, r, curve1[i].angle, curve1[i - 1].angle, true);
}
return;
}
// joining the two area curves
ctx.lineto(curve1[len1 - 1].x, curve1[len1 - 1].y);
// building opposite area curve (reverse)
for (i = len1 - 1; i > 0; --i) {
lineto(ctx, curve1[i], curve1[i - 1], true);
}
}
var dofill = (ctx, points, mapper, view, color, loop) => {
var count = points.length;
var span = view.spangaps;
var curve0 = [];
var curve1 = [];
var len0 = 0;
var len1 = 0;
var i, ilen, index, p0, p1, d0, d1, loopoffset;
ctx.beginpath();
for (i = 0, ilen = count; i < ilen; ++i) {
index = i % count;
p0 = points[index]._view;
p1 = mapper(p0, index, view);
d0 = isdrawable(p0);
d1 = isdrawable(p1);
if (loop && loopoffset === undefined && d0) {
loopoffset = i + 1;
ilen = count + loopoffset;
}
if (d0 && d1) {
len0 = curve0.push(p0);
len1 = curve1.push(p1);
} else if (len0 && len1) {
if (!span) {
drawarea(ctx, curve0, curve1, len0, len1);
len0 = len1 = 0;
curve0 = [];
curve1 = [];
} else {
if (d0) {
curve0.push(p0);
}
if (d1) {
curve1.push(p1);
}
}
}
}
drawarea(ctx, curve0, curve1, len0, len1);
ctx.closepath();
ctx.fillstyle = color;
ctx.fill();
}
for (i = metasets.length - 1; i >= 0; --i) {
meta = metasets[i].$filler;
if (!meta || !meta.visible) {
continue;
}
el = meta.el;
view = el._view;
points = el._children || [];
mapper = meta.mapper;
// note: here is where the gradient is defined. one could probably create the gradient based on input data inside the options object.
color = ctx.createlineargradient(chart.width / 2, chart.height, chart.width / 2, 0);
color.addcolorstop(0, 'red');
color.addcolorstop(0.2, 'red');
color.addcolorstop(0.4, 'yellow');
color.addcolorstop(0.6, 'yellow');
color.addcolorstop(0.8, 'green');
color.addcolorstop(1, 'green');
if (mapper && color && points.length) {
cliparea(ctx, chart.chartarea);
dofill(ctx, points, mapper, view, color, el._loop);
uncliparea(ctx);
}
}
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/chart.js/2.9.3/chart.bundle.js"></script>
<div class="container">
<canvas id="chart"></canvas>
</div>
score:3
there is not a built in option, but we can achieve the result with some code.
var ctx = document.getelementbyid("chart").getcontext("2d");
var scatterchart = new chart(ctx, {
type: "line",
data: {
datasets: [{
label: " dataset",
data: [{
x: 1,
y: 10
},
{
x: 2,
y: 50
},
{
x: 3,
y: 88
},
{
x: 4,
y: 5
}
]
}]
},
options: {
backgroundrules: [{
backgroundcolor: "red",
yaxissegement: 40
},
{
backgroundcolor: "yellow",
yaxissegement: 70
},
{
backgroundcolor: "green",
yaxissegement: infinity
}
],
scales: {
xaxes: [{
type: "linear",
position: "bottom"
}],
yaxes: [{
color: ["#123456", "#234567"]
}]
}
},
plugins: [{
beforedraw: function(chart) {
var ctx = chart.chart.ctx;
var ruleindex = 0;
var rules = chart.chart.options.backgroundrules;
var yaxis = chart.chart.scales["y-axis-0"];
var xaxis = chart.chart.scales["x-axis-0"];
var partpercentage = 1 / (yaxis.ticksasnumbers.length - 1);
for (var i = yaxis.ticksasnumbers.length - 1; i > 0; i--) {
if (yaxis.ticksasnumbers[i] < rules[ruleindex].yaxissegement) {
ctx.fillstyle = rules[ruleindex].backgroundcolor;
ctx.fillrect(xaxis.left, yaxis.top + (i - 1) * (yaxis.height * partpercentage), xaxis.width, yaxis.height * partpercentage);
} else {
ruleindex++;
i++;
}
}
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/chart.js/2.9.3/chart.bundle.js"></script>
<div class="container">
<canvas id="chart"></canvas>
</div>
score:3
let me present a generic approach that works with any such chart aslong as its dataset contains zero or positive values only.
the background colors together with the upper values can simply be defined inside the dataset as follows:
bgcolors: [
{ color: 'red', upto: 40 },
{ color: 'yellow', upto: 70 },
{ color: 'green', upto: 100 }
]
then you could extend an existing line chart (i.e. 'linediffbgcolors') and overwrite its update
function. in there, you would create a linear canvasgradient
and add color stops that correspond to the definitions of bgcolors
mentioned above. at the end, the linear gradient needs to be assigned to the backgroundcolor
option of your dataset
.
this.chart.data.datasets[0].backgroundcolor = gradient;
please have a look at your enhanced code below.
chart.defaults.linediffbgcolors = chart.defaults.line;
chart.controllers.linediffbgcolors = chart.controllers.line.extend({
update: function(reset) {
var yaxis = this.chart.scales['y-axis-0'];
var bgcolors = this.chart.data.datasets[0].bgcolors.slice().reverse();
var max = math.max.apply(null, bgcolors.map(o => o.upto));
var min = yaxis.getvalueforpixel(yaxis.bottom);
var ytop = yaxis.getpixelforvalue(max);
var gradient = this.chart.chart.ctx.createlineargradient(0, ytop, 0, yaxis.bottom);
let offset = 0;
bgcolors.foreach((bgc, i) => {
gradient.addcolorstop(offset, bgc.color);
if (i + 1 == bgcolors.length) {
offset = 1;
} else {
offset = (max - bgcolors[i + 1].upto) / (max - min);
}
gradient.addcolorstop(offset, bgc.color);
});
this.chart.data.datasets[0].backgroundcolor = gradient;
return chart.controllers.line.prototype.update.apply(this, arguments);
}
});
new chart('mychart', {
type: 'linediffbgcolors',
data: {
datasets: [{
label: 'dataset',
data: [
{ x: 1, y: 10 },
{ x: 2, y: 50 },
{ x: 3, y: 88 },
{ x: 4, y: 5 }
],
bgcolors: [
{ color: 'red', upto: 40 },
{ color: 'yellow', upto: 70 },
{ color: 'green', upto: 100 }
]
}]
},
options: {
scales: {
xaxes: [{
type: 'linear'
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/chart.js/2.9.3/chart.js"></script>
<canvas id="mychart" height="100"></canvas>
in case you prefer kind of smooth gradient, you could change the
bgcolors.foreach
loop inside theupdate
function as follows.
bgcolors.foreach((bgc, i) => {
gradient.addcolorstop(offset == 0 ? 0 : offset + 0.05, bgc.color);
if (i + 1 == bgcolors.length) {
offset = 1;
} else {
offset = (max - bgcolors[i + 1].upto) / (max - min);
}
gradient.addcolorstop(offset == 1 ? 1 : offset - 0.05, bgc.color);
});
Source: stackoverflow.com
Related Query
- Chart js different background for y axis
- chart.js Line chart with different background colors for each section
- ChartJS/High Charts Radar chart - Different radial axis labels for each category that appear on hover
- show label in tooltip but not in x axis for chartjs line chart
- Chart JS - set start of week for x axis time series
- Different color for each column in angular-chartjs bar chart
- Can I specify a different font size for each row of text in Chart Title?
- How to hide the y axis and x axis line and label in my bar chart for chart.js
- (Vue, ChartJS) Create gradient background for chart from child component canvas context
- chart js - Apply different color for each x-axes label
- Chart JS, Choose different Y-axis for different datasets
- Vue ChartKick - different colours for bar chart
- How to map json array to two different array for chart
- chartjs custom y axis values, different text for each one
- How to show different product name for every bar in chart js
- Minimum value for x Axis doesn't work for horizontal bar chart | ChartJS
- Chartjs different row background colors according to Y axis values
- How can I have different values for the chart and the tooltip in chart.js?
- create different labels for different data chart js
- Chart Js reduce text size for label on X axis
- chart.JS i want to put different color for each Y axis value grid line color
- Charts.js - Bar chart different colors for value intervals not working
- Linear x axis for bar chart chartjs
- Chart.js two y axes line chart tooltip value incorrect for 2nd y axis
- How do I get a different label for each bar in a bar chart in ChartJS?
- How do you set x and y axis and Title for a line chart using charts.js?
- How to assign different background colors to chart.js pie chart data set?
- Chart JS tick options not working for y axis
- How to start Y Axis Line at 0 from right for negative values in chart js 2?
- getting additional value fields from data source for dx.chartjs doughnut chart
More Query from same tag
- Show data values in Chart.js bars (version 3)
- How to detect when Tooltip closes in chart.js?
- Chart.js different time datasets
- ChartJs create Chart from array
- Using Chart.js with Pyramid Web Framework
- Chart.JS: How to add Data to a specific dataset
- ChartJS Custom text on certain xAxis and yAxis linesS
- how can I add a django array element into a js array using an if condition
- So, I'm fetching my data from phpMyAdmin MySQL to the chart.js, but I need it with AJAX, but how AJAX works with Chart.js?
- Reopening a "ChartJS" chart in a new window (VS, C#, ChartJS)
- chartnew.js - remove lines from pie chart on 100%
- How to always show line chart tooltip in ionic-angular.?
- Chart.js not showing on second tab
- How to update css for doughnut chart with ng2-charts
- Chart.js horizontal line chart or modified horizontal bar chart
- chart.js label color change based on value
- How to access labels array using chart plugin (Chart.pluginService.register) in Chartjs 2.x?
- chart.js change size of label of radar chart
- How to add text to chart.js data?
- getting chartsjs to show key of data label instead of value
- Popup windows for histogram with AngularJS
- How get values on legend label withn Chart js on Angular
- Usage for angular-chart : colors and fonts
- How can i hide label data on chart.js tooltip content?
- how to show multiple values in point hover using chart.js
- Displaying JSON in Chart.js
- Chartjs columns does not appear by value
- JavaScript Chart.JS - issue keeping charts in two rows, instead everything in stacked into one column
- Using chart js options with react-chartjs-2 and typescript
- Chart.plugins.register beforeDraw does not work when using ChartsJS 3.x