当点为负时,我需要更改折线图中的填充颜色(内部区域)。
代码简单而基本:
$(document).ready(function(){
var ctx = $("#myChart").get(0).getContext("2d");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
//fillColor : "rgba(60,91,87,1)",
// String - the color to fill the area under the line with if fill is true
backgroundColor: "rgba(75,192,192,0.4)",
strokeColor : "rgba(60,91,87,1)",
pointColor : "rgba(60,91,87,1)",
pointStrokeColor : "#58606d",
// The actual data
data: [65, 59, 80, -81, 56, 55, -40],
// String - If specified, binds the dataset to a certain y-axis. If not specified, the first y-axis is used. First id is y-axis-0
yAxisID: "y-axis-0",
}
]
};
var options = {
scales: {
yAxes: [{
display: true,
ticks: {
suggestedMin: 0, // minimum will be 0, unless there is a lower value.
// OR //
beginAtZero: true // minimum value will be 0.
}
}]
}
};
var myLineChart = new Chart(ctx, {
type: 'line',
data: data,
options: options
});
// myLineChart.data.datasets[0].metaDataset._points[3]._model.backgroundColor = "red";
// if (myLineChart.datasets[0].points[4].value < 0) {
// myLineChart.datasets[0].points[4].fillColor = "red";
// myLineChart.update();
// }
})
我试图得到这个结果:
答案 0 :(得分:8)
您可以扩展折线图来执行此操作。
预览强>
<强>脚本强>
Chart.defaults.NegativeTransparentLine = Chart.helpers.clone(Chart.defaults.line);
Chart.controllers.NegativeTransparentLine = Chart.controllers.line.extend({
update: function () {
// get the min and max values
var min = Math.min.apply(null, this.chart.data.datasets[0].data);
var max = Math.max.apply(null, this.chart.data.datasets[0].data);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
// figure out the pixels for these and the value 0
var top = yScale.getPixelForValue(max);
var zero = yScale.getPixelForValue(0);
var bottom = yScale.getPixelForValue(min);
// build a gradient that switches color at the 0 point
var ctx = this.chart.chart.ctx;
var gradient = ctx.createLinearGradient(0, top, 0, bottom);
var ratio = Math.min((zero - top) / (bottom - top), 1);
gradient.addColorStop(0, 'rgba(75,192,192,0.4)');
gradient.addColorStop(ratio, 'rgba(75,192,192,0.4)');
gradient.addColorStop(ratio, 'rgba(0,0,0,0)');
gradient.addColorStop(1, 'rgba(0,0,0,0)');
this.chart.data.datasets[0].backgroundColor = gradient;
return Chart.controllers.line.prototype.update.apply(this, arguments);
}
});
然后
...
var myLineChart = new Chart(ctx, {
type: 'NegativeTransparentLine',
data: {
...
答案 1 :(得分:6)
要获取上面的 @potatopeelings 代码以使用chart.js 2.5.x,您需要添加 yAxisID:'y-axis-0'进入您的数据集,如下所示。
var myLineChart = new Chart(ctx, {
type: 'NegativeTransparentLine',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
yAxisID : 'y-axis-0',
....
答案 2 :(得分:0)
[1,2,3,...]
,则@potatopeelings代码将起作用
如果数据格式为[{x: 1 , y: 1},...]
,则需要将var min
和var max
更改为:
var min = this.chart.data.datasets[0].data.reduce((min, p) => p.y < min ? p.y : min, this.chart.data.datasets[0].data[0].y);
var max = this.chart.data.datasets[0].data.reduce((max, p) => p.y > max ? p.y : max, this.chart.data.datasets[0].data[0].y);
在ChartJS 2.7.3上测试
答案 3 :(得分:0)
我更新了用于多个数据集的方法。
Chart.defaults.NegativeTransparentLine = Chart.helpers.clone(Chart.defaults.line);
Chart.controllers.NegativeTransparentLine = Chart.controllers.line.extend({
update: function () {
for(let i=0; i< this.chart.data.datasets.length; i++) {
// get the min and max values
var min = Math.min.apply(null, this.chart.data.datasets[i].data);
var max = Math.max.apply(null, this.chart.data.datasets[i].data);
var yScale = this.getScaleForId(this.chart.data.datasets[i].yAxisID);
// figure out the pixels for these and the value 0
var top = yScale.getPixelForValue(max);
var zero = yScale.getPixelForValue(0);
var bottom = yScale.getPixelForValue(min);
// build a gradient that switches color at the 0 point
var ctx = this.chart.chart.ctx;
var gradient = ctx.createLinearGradient(0, top, 0, bottom);
var ratio = Math.min((zero - top) / (bottom - top), 1);
gradient.addColorStop(0, 'rgba(55,210,99,0.4)');
gradient.addColorStop(ratio, 'rgba(55,210,99,0.4)');
gradient.addColorStop(ratio, 'rgba(247,100,120,0.4)');
gradient.addColorStop(1, 'rgba(247,100,120,0.4)');
this.chart.data.datasets[i].backgroundColor = gradient;
}
return Chart.controllers.line.prototype.update.apply(this, arguments);
}
});
在Angular 8上的chart.js 2.8.0上进行了测试
import { Component, OnInit, ViewChild } from '@angular/core';
import { Chart, ChartDataSets, ChartOptions } from 'chart.js';
import { Color, Label } from 'ng2-charts';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public lineChartData: ChartDataSets[] = [
{ data: [89, 0, -80, 81, 56, -55, 40], label: 'Series A', yAxisID: 'y-axis-0' },
{ data: [-890, 0, 800, -810, -560, 550, -400], label: 'Series B', yAxisID: 'y-axis-0' },
];
public lineChartLabels: Label[] = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
public lineChartOptions: (ChartOptions & { annotation: any }) = {
responsive: true,
};
public lineChartColors: Color[] = [
{
backgroundColor: 'rgba(255,0,0,0.3)',
},
{
backgroundColor: 'rgba(0,255,0,0.3)',
},
];
public lineChartLegend = true;
public lineChartType = 'line';
public lineChartPlugins = [];
constructor() {
Chart.defaults.NegativeTransparentLine = Chart.helpers.clone(Chart.defaults.line);
Chart.controllers.NegativeTransparentLine = Chart.controllers.line.extend({
update: function () {
for(let i=0; i< this.chart.data.datasets.length; i++) {
// get the min and max values
var min = Math.min.apply(null, this.chart.data.datasets[i].data);
var max = Math.max.apply(null, this.chart.data.datasets[i].data);
var yScale = this.getScaleForId(this.chart.data.datasets[i].yAxisID);
// figure out the pixels for these and the value 0
var top = yScale.getPixelForValue(max);
var zero = yScale.getPixelForValue(0);
var bottom = yScale.getPixelForValue(min);
// build a gradient that switches color at the 0 point
var ctx = this.chart.chart.ctx;
var gradient = ctx.createLinearGradient(0, top, 0, bottom);
var ratio = Math.min((zero - top) / (bottom - top), 1);
gradient.addColorStop(0, 'rgba(55,210,99,0.4)');
gradient.addColorStop(ratio, 'rgba(55,210,99,0.4)');
gradient.addColorStop(ratio, 'rgba(247,100,120,0.4)');
gradient.addColorStop(1, 'rgba(247,100,120,0.4)');
this.chart.data.datasets[i].backgroundColor = gradient;
}
return Chart.controllers.line.prototype.update.apply(this, arguments);
}
});
this.lineChartType = 'NegativeTransparentLine';
}
ngOnInit() {
}
}
<div style="display: block;">
<canvas baseChart width="400" height="400"
[datasets]="lineChartData"
[labels]="lineChartLabels"
[options]="lineChartOptions"
[colors]="lineChartColors"
[legend]="lineChartLegend"
[chartType]="lineChartType"
[plugins]="lineChartPlugins">
</canvas>
</div>
答案 4 :(得分:0)
@potatopeelings如果所有数据都是负值或正值,则渐变会变得混乱,这就是我固定的方式。 (更改了渐变颜色,但修复程序仍然存在)
Chart.defaults.NegativeTransparentLine = Chart.helpers.clone(Chart.defaults.line);
Chart.controllers.NegativeTransparentLine = Chart.controllers.line.extend({
update: function () {
// get the min and max values
var min = Math.min.apply(null, this.chart.data.datasets[0].data);
var max = Math.max.apply(null, this.chart.data.datasets[0].data);
var yScale = this.getScaleForId(this.getDataset().yAxisID);
// figure out the pixels for these and the value 0
var top = yScale.getPixelForValue(max);
var zero = yScale.getPixelForValue(0);
var bottom = yScale.getPixelForValue(min);
// build a gradient that switches color at the 0 point
var ctx = this.chart.chart.ctx;
var gradient = ctx.createLinearGradient(0, top, 0, bottom);
var ratio = Math.min((zero - top) / (bottom - top), 1);
if(ratio < 0){
ratio = 0;
gradient.addColorStop(1, 'rgba(0,255,0,1)');
}else if(ratio == 1){
gradient.addColorStop(1, 'rgba(255,0,0,1)');
}else{
gradient.addColorStop(0, 'rgba(255,0,0,1)');
gradient.addColorStop(ratio, 'rgba(255,0,0,1)');
gradient.addColorStop(ratio, 'rgba(0,255,0,1)');
gradient.addColorStop(1, 'rgba(0,255,0,1)');
}
console.log(ratio)
this.chart.data.datasets[0].backgroundColor = gradient;
return Chart.controllers.line.prototype.update.apply(this, arguments);
}
});
答案 5 :(得分:0)
这源自this post。它适用于 Chart.js v2.9.4,不需要任何外部代码或创建自定义图表类型。只需将此插件对象添加到您的图表选项即可。 (注意 plugins 对象和 options 对象是分开的。如果你把 plugins 对象放在 options 对象里面,它不会工作。)
new Chart(document.querySelector(`canvas`), {
type: 'line',
data: {
labels: your_labels,
datasets: [{
data: your_data
}]
},
options: {
maintainAspectRatio: false, //allow the graph to resize to its container
scales: {
yAxes: [{
ticks: {
beginAtZero: true //make sure zero line exists on the graph
}
}]
}
}, //<-make sure plugins is outside of the options object
plugins: [{
beforeRender: function(graph) {
let gradient = graph.ctx.createLinearGradient(0, 0, 0, graph.height), //create a gradient for the background
zero_line = graph.scales[`y-axis-0`].getPixelForValue(0) / graph.height; //calculate where the zero line is plotted on the graph
gradient.addColorStop(0, `rgba(0,200,0,.2)`); //good color faded out
gradient.addColorStop(zero_line, `rgba(0,200,0,.8)`); //good color at zero line
gradient.addColorStop(zero_line, `rgba(200,0,0,.8)`); //bad color at zero line
gradient.addColorStop(1, `rgba(200,0,0,.2)`); //bad color faded out
graph.data.datasets[0]._meta[0].$filler.el._model.backgroundColor = gradient; //set the graphs background to the gradient we just made
}
}]
});
显然,对于更复杂的图表,您需要更新数据集索引和轴名称,但对于简单的图表,就是这么简单。