kendo version 2015.1.429
I can't figure out why this doesn't work. I've been fighting with it for hours to no avail. I've tried all sorts of variations on the axis name, etc.
Any ideas?
#(Html.Kendo().Chart<OTIS.AppServ.Reporting.ViewModels.ItemDailyForecast>()
.Name("chart_ItemForecastByDay")
.Theme("Silver")
.HtmlAttributes(new { #class = "widgetFullWidth" })
.Title("Item Daily Forecast")
.Legend(legend => legend
.Position(ChartLegendPosition.Bottom)
.Visible(true)
)
.Events(events => events
.Render("hideChartLoadingImage")
)
.AutoBind(true)
.DataSource(ds => ds
.Read(read => read.Action("GetItemForecastByDay", "InventoryReports", new { area = "Reporting", intItemId = Model, intDaysOut = 90}))
.Sort(sort =>
{
sort.Add(model => model.Date).Ascending();
})
)
.Series(series =>
{
series
.Line(model => model.DailyUnitBalanceQty)
//.Column(model => model.DailyUnitBalanceQty)
.Name("Units Avail")
//.Color("#5cbe2d")
.Aggregate(ChartSeriesAggregate.Sum)
.Axis("Axis1")
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("#= series.name # (#= kendo.toString(category, 'd') #, #= kendo.format('{0:n0}', value) #)")
)
;
})
.Series(series =>
{
series
.Line(model => model.DailyDaysOnHandQty)
//.Column(model => model.DailyDaysOnHandQty)
.Name("Days On Hand")
//.Color("#5cbe2d")
.Aggregate(ChartSeriesAggregate.Sum)
.Axis("Axis1")
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("#= series.name # (#= kendo.toString(category, 'd') #, #= kendo.format('{0:n0}', value) #)")
)
;
})
.Series(series =>
{
series
.Column(model => model.DailyReceiptQty)
.Name("Receipt Qty")
//.Color("#5cbe2d")
.Aggregate(ChartSeriesAggregate.Sum)
.Axis("Axis1")
.Spacing(0.0)
.Gap(0.0)
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("#= series.name # (#= kendo.toString(category, 'd') #, #= kendo.format('{0:n0}', value) #)")
)
;
})
.CategoryAxis(axis => axis
.Date()
.BaseUnit(ChartAxisBaseUnit.Days)
.Categories(model => model.Date)
.Labels(labels => {
labels.Rotation(90);
}
)
.AxisCrossingValue(0, 1000)
)
.ValueAxis(axis => axis
.Numeric("Axis1")
.Labels(labels => labels.Format("{0:n0}"))
.PlotBands(bands =>
{
//bands.Add().From(-10).To(50).Color("#c00").Opacity(0.3);
bands.Add().From(49).To(50).Color("#c00").Opacity(0.8);
})
)
.ChartArea(chartArea => chartArea
.Background("transparent")
.Height(300)
)
.PlotArea(plotArea => plotArea
.Background("transparent")
//.Margin(40)
)
)
<script>
$(function(){
var chart = $("#chart_ItemForecastByDay").data("kendoChart");
options["categoryAxis"] = { plotBands: [{ from: "3/17/2019", to: "3/20/2019", color: "green", opacity: 0.3 }] };
options["yAxis"] = { plotBands: [{ from: 20, to: 30, color: "blue", opacity: 0.3 }] };
options["valueAxis"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
options["Axis1"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
chart.setOptions(options);
}
</script>
For Categorical Charts types we should use the categoryAxis and valueAxis plotBands.
<script>
var stats = [
{ value: 48, date: new Date("2014/01/01") },
{ value: 50, date: new Date("2014/01/02") },
{ value: 55, date: new Date("2014/01/03") },
{ value: 35, date: new Date("2014/01/04") },
{ value: 30, date: new Date("2014/01/05") },
{ value: 30, date: new Date("2014/01/20") },
{ value: 50, date: new Date("2014/01/21") },
{ value: 45, date: new Date("2014/01/22") },
{ value: 40, date: new Date("2014/01/23") },
{ value: 35, date: new Date("2014/01/24") },
{ value: 40, date: new Date("2014/01/25") },
{ value: 42, date: new Date("2014/01/26") },
{ value: 40, date: new Date("2014/01/27") },
{ value: 35, date: new Date("2014/01/28") },
{ value: 43, date: new Date("2014/01/29") },
{ value: 38, date: new Date("2014/01/30") },
{ value: 30, date: new Date("2014/01/31") }
];
$("#chart").kendoChart({
dataSource: {
data: stats
},
series: [{
type: "column",
aggregate: "avg",
field: "value",
categoryField: "date"
}],
categoryAxis: {
type: "date",
majorGridLines: {
visible: false
}
},
valueAxis: {
line: {
visible: false
}
}
});
$(function(){
var chart = $("#chart").data("kendoChart");
var options = {};
var fromDate = new Date("2014/01/15");
var toDate = new Date("2014/01/20");;
options["categoryAxis"] = { plotBands: [{ from: fromDate, to: toDate, color: "green", opacity: 0.3 }] };
options["valueAxis"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
chart.setOptions(options);
});
</script>
While for the Scatter Chart types we should use xAxis and yAxis plotBands
<script>
function createChart() {
$("#chart").kendoChart({
title: {
text: "Rainfall - Wind Speed"
},
legend: {
position: "bottom"
},
seriesDefaults: {
type: "scatter"
},
series: [{
name: "January 2008",
data: [
[16.4, 5.4], [21.7, 2], [25.4, 3], [19, 2], [10.9, 1], [13.6, 3.2], [10.9, 7.4], [10.9, 0], [10.9, 8.2], [16.4, 0], [16.4, 1.8], [13.6, 0.3], [13.6, 0], [29.9, 0], [27.1, 2.3], [16.4, 0], [13.6, 3.7], [10.9, 5.2], [16.4, 6.5], [10.9, 0], [24.5, 7.1], [10.9, 0], [8.1, 4.7], [19, 0], [21.7, 1.8], [27.1, 0], [24.5, 0], [27.1, 0], [29.9, 1.5], [27.1, 0.8], [22.1, 2]]
},{
name: "January 2009",
data: [
[6.4, 13.4], [1.7, 11], [5.4, 8], [9, 17], [1.9, 4], [3.6, 12.2], [1.9, 14.4], [1.9, 9], [1.9, 13.2], [1.4, 7], [6.4, 8.8], [3.6, 4.3], [1.6, 10], [9.9, 2], [7.1, 15], [1.4, 0], [3.6, 13.7], [1.9, 15.2], [6.4, 16.5], [0.9, 10], [4.5, 17.1], [10.9, 10], [0.1, 14.7], [9, 10], [2.7, 11.8], [2.1, 10], [2.5, 10], [27.1, 10], [2.9, 11.5], [7.1, 10.8], [2.1, 12]]
},{
name: "January 2010",
data: [
[21.7, 3], [13.6, 3.5], [13.6, 3], [29.9, 3], [21.7, 20], [19, 2], [10.9, 3], [28, 4], [27.1, 0.3], [16.4, 4], [13.6, 0], [19, 5], [16.4, 3], [24.5, 3], [32.6, 3], [27.1, 4], [13.6, 6], [13.6, 8], [13.6, 5], [10.9, 4], [16.4, 0], [32.6, 10.3], [21.7, 20.8], [24.5, 0.8], [16.4, 0], [21.7, 6.9], [13.6, 7.7], [16.4, 0], [8.1, 0], [16.4, 0], [16.4, 0]]
}],
xAxis: {
max: 35,
title: {
text: "Wind Speed [km/h]"
},
crosshair: {
visible: true,
tooltip: {
visible: true,
format: "n1"
}
}
},
yAxis: {
min: -5,
max: 25,
title: {
text: "Rainfall [mm]"
},
axisCrossingValue: -5,
crosshair: {
visible: true,
tooltip: {
visible: true,
format: "n1"
}
}
}
});
var chart = $("#chart").data("kendoChart");
var options = {};
var fromDate = new Date("2014/01/15");
var toDate = new Date("2014/01/20");;
options["xAxis"] = { plotBands: [{ from: 10, to: 20, color: "yellow", opacity: 0.3 }] };
options["yAxis"] = { plotBands: [{ from: -5, to: 0, color: "red", opacity: 0.3 }] };
chart.setOptions(options);
}
$(document).ready(createChart);
$(document).bind("kendo:skinChange", createChart);
</script>
Related
Link to jsfiddle
Why does borderRadius only work on top?
HTML
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div>
<canvas id="canvas" height="100"></canvas>
</div>
JS
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Q0", "Q1", "Q2", "Q3", "Q4"],
datasets: [{
label: 'estimate',
data: [[2, 7], [2, 10], [1, 3], [1, 4], [4, 8]],
backgroundColor: 'lightblue',
borderRadius: 10,
},
{
label: 'actual',
data: [[5, 6], [7, 8], [2, 3], [2, 3], [7, 8]],
backgroundColor: 'red',
borderRadius: 10,
}]
},
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Estimate Histoy'
}
}
});
}
;
I've been searching for a couple of days now. Found a lot of pre-V3 that are rather complex but nothing with V3. Seem rather straightforward. I did see that if the bottom is on an axis it'll not put borderRadius.
Thanks for the help.
If you want all the borders to have a borderRadius you need to specify borderSkipped: false in your dataset
I have a chart as shown below. I have two expectation, firstly as you can see the tick number (1,2,3,4,5) hidden behind the background color of dump datasets (I need that background colors, that's why I am using fake datasets). I need to show them like using z-index or something. I wrote tick numbers in red color for sample.
Secondly I need the show angle line on top also.
var test2 = [2, 2, 2, 2, 2];
var test3 = [3, 3, 3, 3, 3];
var test4 = [4, 4, 4, 4, 4];
var test5 = [5, 5, 5, 5, 5];
new Chart(document.getElementById("myChart"), {
type: 'radar',
data: {
labels: sectionDescriptions,
datasets: [
{
label: "2050",
fill: true,
borderColor: "rgba(0,0,0,1)",
borderWidth: "4",
pointRadius: 3,
pointBorderWidth: 3,
pointBackgroundColor: "cornflowerblue",
pointBorderColor: "rgba(0,0,200,0.6)",
pointHoverRadius: 10,
data: sectionPoints
},
{
radius: 0,
fill: true,
backgroundColor: "rgba(240,0,0,1)",
data: test2
},
{
radius: 0,
fill: true,
backgroundColor: "rgba(255,190,4,1)",
data: test3
},
{
radius: 0,
fill: true,
backgroundColor: "rgba(255,250,5,1)",
data: test4
},
{
radius: 0,
fill: true,
backgroundColor: "rgba(0,180,233,1)",
data: test5
}
]
},
options: {
title: {
display: true,
text: 'Chart'
},
scale: {
gridLine: {
color : "white"
},
ticks: {
beginAtZero: true,
min: 0,
max: 5,
stepSize: 1,
fontColor: 'black',
backDropColor: 'black'
},
pointLabels: {
fontSize: 13,
//fontStyle: 'bold'
}
},
legend: {
display: false
}
}
});
I try to have in the same time datalabels and the sum display in my stacked bar chart.
I use chartjs-plugin-datalabels.js to display datalabels or sum.
Above just with datalabels:
Above just with sum :
I would like to have both in the same chart.
I use the follow tricks to sum display :
<script>
const totalizer = {
id: 'totalizer',
beforeUpdate: chart => {
let totals = {}
let utmost = 0
chart.data.datasets.forEach((dataset, datasetIndex) => {
if (chart.isDatasetVisible(datasetIndex)) {
utmost = datasetIndex
dataset.data.forEach((value, index) => {
totals[index] = (totals[index] || 0) + value
})
}
})
chart.$totalizer = {
totals: totals,
utmost: utmost
}
}
}
new Chart('chart', {
type: 'bar',
data: {
labels: ["Note par thème du répondant", "Note par thème sectorielle", "Note par thème générale"],
datasets: [{
label: 'Thème 1',
data: [12, 19, 3],
backgroundColor: 'rgba(255, 206, 86)'
},
{
label: 'Thème 2',
data: [3,8,1],
backgroundColor: 'rgba(54, 162, 235)'
},
{
label: 'Thème 3',
data: [ 5, 2, 3],
backgroundColor: 'rgba(255, 255, 132)'
},{
label: 'Thème 4',
data: [ 5, 2, 3],
backgroundColor: 'rgba(255, 99, 255)'
},{
label: 'Thème 5',
data: [ 5, 2, 3],
backgroundColor: 'rgba(100, 250, 132)'
},{
label: 'Thème 6',
data: [ 5, 2, 3],
backgroundColor: 'rgba(89, 99, 132)'
},{
label: 'Thème 7',
data: [ 5, 2, 3],
backgroundColor: 'rgba(255, 0, 132)'
},{
label: 'Thème 8',
data: [ 5, 2, 3],
backgroundColor: 'rgba(0, 150, 255)'
},{
label: 'Thème 9',
data: [ 5, 2, 3],
backgroundColor: 'rgba(100, 100, 100)'
},{
label: 'Thème 10',
data: [ 10, 4, 7],
backgroundColor: 'rgba(255, 255, 0)'
}]
},
options: {
title :{
display :true,
text : "Mon titre"
},
scales: {
yAxes: [{
stacked: true,
ticks: {
beginAtZero: true,
suggestedMax: 100
}
}],
xAxes: [{
stacked: true
}]
},
plugins: {
datalabels: {
formatter: (value, ctx) => {
const total = ctx.chart.$totalizer.totals[ctx.dataIndex]
return total.toLocaleString('fr-FR', {})
},
align: 'end',
anchor: 'end',
display: function(ctx) {
return ctx.datasetIndex === ctx.chart.$totalizer.utmost
}
}
}
},
plugins: [totalizer]
});
</script>
I would appreciate any help. Thanks!
OK, I found a way to show Sum and datalabels in the same time.
I add new dataset to represent "Total data" with a backgroundColor transparent and I add this following code in my dataset Total:
datalabels: {
backgroundColor: function (context) {
return 'rgba(244,50,49)';
},
formatter: (value, ctx) => {
const total = ctx.chart.$totalizer.totals[ctx.dataIndex];
return total.toLocaleString('fr-FR', {})
},
align: 'end',
anchor: 'end',
display: function (ctx) {
return ctx.datasetIndex === ctx.chart.$totalizer.utmost
}
Full code bellow :
<script>
const totalizer = {
id: 'totalizer',
beforeUpdate: chart => {
let totals = {}
let utmost = 0
chart.data.datasets.forEach((dataset, datasetIndex) => {
if (chart.isDatasetVisible(datasetIndex)) {
utmost = datasetIndex
dataset.data.forEach((value, index) => {
totals[index] = (totals[index] || 0) + value
})
}
})
chart.$totalizer = {
totals: totals,
utmost: utmost
}
}
}
new Chart('chart', {
type: 'bar',
data: {
labels: ["Note par thème du répondant", "Note par thème sectorielle", "Note par thème générale"],
datasets: [{
label: 'Thème 1',
data: [10, 10, 10],
backgroundColor: 'rgba(68,114,196,0.6)'
}, {
label: 'Thème 2',
data: [13, 8, 11],
backgroundColor: 'rgba(237,125,49,0.6)'
}, {
label: 'Thème 3',
data: [5, 12, 13],
backgroundColor: 'rgba(165,165,165,0.6)'
}, {
label: 'Thème 4',
data: [9, 12, 13],
backgroundColor: 'rgba(255,192,0,0.6)'
}, {
label: 'Thème 5',
data: [5, 12, 9],
backgroundColor: 'rgba(91,155,213,0.6)'
}, {
label: 'Thème 6',
data: [9, 12, 5],
backgroundColor: 'rgba(112,173,71,0.6)'
}, {
label: 'Thème 7',
data: [5, 12, 10],
backgroundColor: 'rgba(38,68,120,0.6)'
}, {
label: 'Thème 8',
data: [15, 12, 10],
backgroundColor: 'rgba(99,99,99,0.6)'
}, {
label: 'Thème 9',
data: [15, 12, 11],
backgroundColor: 'rgba(37,94,145,0.6)'
}, {
label: 'Thème 10',
data: [10, 4, 7],
backgroundColor: 'rgba(24,91,62,0.6)'
}, {
label: 'Total',
data: [0, 0, 0],
backgroundColor: 'rgba(24,91,62,0)',
datalabels: {
backgroundColor: function (context) {
return 'rgba(244,50,49)';
},
formatter: (value, ctx) => {
const total = ctx.chart.$totalizer.totals[ctx.dataIndex];
return total.toLocaleString('fr-FR', {})
},
align: 'end',
anchor: 'end',
display: function (ctx) {
return ctx.datasetIndex === ctx.chart.$totalizer.utmost
}
}
}
]
},
options: {
title: {
text: "Mon titre",
display: true
},
scales: {
yAxes: [{
stacked: true,
ticks: {
beginAtZero: true,
suggestedMax: 100
}
}
],
xAxes: [{
stacked: true
}
]
},
plugins: {
datalabels: {
color: 'rgba(255,255,255)',
display: function (context) {
return context.chart.isDatasetVisible(context.datasetIndex);
},
backgroundColor: function (context) {
return context.dataset.backgroundColor;
},
borderRadius: 4,
font: {
weight: 'bold'
}
}
}
},
plugins: [totalizer]
});
</script>
Great! I just simplified solution without totilizer:
datasets: {
label: 'Total',
data: [120, 120, 120, 120, 120, 120, 120, 120, 120, 120],
backgroundColor: 'rgba(24,91,62,0)',
datalabels: {
backgroundColor: () => 'white',
formatter: (value, ctx) => {
let total = 0;
let index = ctx.dataIndex;
data.datasets.map((d, i) => {
if (i === 2) return;
total += d.data[index];
});
return total;
},
align: 'end',
anchor: 'end',
padding: 0,
},
},
I'm Working on Chart.js, wanted to implement Select All and Unselect All option for labels. I'm trying to find it out but couldn't get anything such.
Please do help me out if anything such feature can be implemented.
If you need to show/hide charts selecting/unselecting all labels here is an example:
var barChartData = {
labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32],
datasets: [{
label: 'One',
backgroundColor: 'rgba(206, 0, 23, 1)',
data: [0, 1, 3, 0, 2, 0, 0, 2, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 2, 1, 0, 1, 2, 1, 1, 0, 0, 0, 2, 2, 0, 3]
}, {
label: 'Two',
backgroundColor: 'rgba(206, 0, 23, 0.75)',
data: [0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
}, {
label: 'Three',
backgroundColor: 'rgba(206, 0, 23, 0.5)',
data: [0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1]
}]
};
var ctx = document.getElementById('canvas').getContext('2d');
var chartInstance = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: false,
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
$("#toggle").click(function() {
chartInstance.data.datasets.forEach(function(ds) {
ds.hidden = !ds.hidden;
});
chartInstance.update();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<button id="toggle">show/hide all</button>
<canvas id="canvas" height="500" width="800"></canvas>
Jsfiddle: https://jsfiddle.net/beaver71/00q06vjp/
Credits: see https://github.com/chartjs/Chart.js/issues/3009
Update: for pie chart use "meta", see: https://jsfiddle.net/beaver71/u0y0919b/
For ChartJS 2.9.3, this works as requested by David in the comments:
const chart = ...
chart.data.datasets.forEach(dataset => {
Object.keys(dataset._meta).forEach(key => {
const current = !dataset._meta[key].hidden
dataset._meta[key].hidden = current || null
})
})
chart.update()
Toggles all with a button, while playing nicely with the individual toggling in the chart legend.
V3 Answer
You can use a custom generateLabels function together with a custom onClick to get it as an extra legendItem like so:
const defaultLegendClickHandler = Chart.defaults.plugins.legend.onClick;
const pieDoughnutLegendClickHandler = Chart.controllers.doughnut.overrides.plugins.legend.onClick;
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {
plugins: {
legend: {
onClick: (evt, legendItem, legend) => {
const type = legend.chart.config.type;
let allLegendItemsState = [];
if (legendItem.text === 'hide all datasets' || legendItem.text === 'show all datasets') {
if (typeof legend.hideAll === 'undefined') {
legend.hideAll = false;
}
legend.chart.data.datasets.forEach((dataset, i) => {
legend.chart.setDatasetVisibility(i, legend.hideAll)
});
legend.hideAll = !legend.hideAll;
legend.chart.update();
return;
}
if (type === 'pie' || type === 'doughnut') {
pieDoughnutLegendClickHandler(evt, legendItem, legend)
} else {
defaultLegendClickHandler(evt, legendItem, legend);
}
allLegendItemsState = legend.chart.data.datasets.map((e, i) => (legend.chart.getDatasetMeta(i).hidden));
if (allLegendItemsState.every(el => !el)) {
legend.hideAll = false;
legend.chart.update();
} else if (allLegendItemsState.every(el => el)) {
legend.hideAll = true;
legend.chart.update();
}
},
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
const {
labels: {
usePointStyle,
pointStyle,
textAlign,
color
}
} = chart.legend.options;
const legendItems = chart._getSortedDatasetMetas().map((meta) => {
const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
return {
text: datasets[meta.index].label,
fillStyle: style.backgroundColor,
fontColor: color,
hidden: !meta.visible,
lineCap: style.borderCapStyle,
lineDash: style.borderDash,
lineDashOffset: style.borderDashOffset,
lineJoin: style.borderJoinStyle,
strokeStyle: style.borderColor,
pointStyle: pointStyle || style.pointStyle,
rotation: style.rotation,
textAlign: textAlign || style.textAlign,
datasetIndex: meta.index
};
});
legendItems.push({
text: (!chart.legend.hideAll || typeof chart.legend.hideAll === 'undefined') ? 'hide all datasets' : 'show all datasets',
fontColor: color,
fillStyle: 'turquoise', // Box color
strokeStyle: 'turquoise', // LineCollor around box
});
return legendItems;
}
}
}
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
</body>
The correct answer result in :
chart.data.datasets.forEach((obj, index) => {
let meta = this.eval_chart.getDatasetMeta(index);
meta.hidden = !meta.hidden || null;
});
chart.update();
As wrote in the documentation : https://www.chartjs.org/docs/latest/configuration/legend.html#custom-on-click-actions
I am creating a Google line chart as per Google Line Chart Documentation.
I want to style the colour of the line such that it is a gradient between two colours, say between Green and Red. The weighting of each colour should be controlled by the 'y' value of the line.
i.e. at the point where the line's 'y' value is 0, the line will be completely green, At the highest 'y' value on the it should be completely red. In between values should have a weighting depending on the value of y at that point.
Is this possible? If so, how?
Since Google Line Chart is SVG based, you could customize how the line can change from one color to another via linearGradient element.
The below example shows how to inject [linearGradient element] into the chart (google.visualization.LineChart):
google.load('visualization', '1', { packages: ['corechart', 'line'] });
google.setOnLoadCallback(drawBackgroundColor);
function drawBackgroundColor() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'Dogs');
data.addRows([
[0, 0], [1, 10], [2, 23], [3, 17], [4, 18], [5, 9],
[6, 11], [7, 27], [8, 33], [9, 40], [10, 32], [11, 35],
[12, 30], [13, 40], [14, 42], [15, 47], [16, 44], [17, 48],
[18, 52], [19, 54], [20, 42], [21, 55], [22, 56], [23, 57],
[24, 60], [25, 50], [26, 52], [27, 51], [28, 49], [29, 53],
[30, 55], [31, 60], [32, 61], [33, 59], [34, 62], [35, 65],
[36, 62], [37, 58], [38, 55], [39, 61], [40, 64], [41, 65],
[42, 63], [43, 66], [44, 67], [45, 69], [46, 69], [47, 70],
[48, 72], [49, 68], [50, 66], [51, 65], [52, 67], [53, 70],
[54, 71], [55, 72], [56, 73], [57, 75], [58, 70], [59, 68],
[60, 64], [61, 60], [62, 65], [63, 60], [64, 50], [65, 45],
[66, 40], [67, 42], [68, 35], [69, 30]
]);
var options = {
hAxis: {
title: 'Time'
},
vAxis: {
title: 'Popularity'
},
backgroundColor: '#f1f8e9'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
google.visualization.events.addOneTimeListener(chart, 'ready', function () {
addChartGradient(chart);
});
chart.draw(data, options);
}
function addChartGradient(chart) {
var chartDiv = chart.getContainer();
var svg = chartDiv.getElementsByTagName('svg')[0];
var properties = {
id: "chartGradient",
x1: "0%",
y1: "0%",
x2: "0%",
y2: "100%",
stops: [
{ offset: '5%', 'stop-color': '#f60' },
{ offset: '95%', 'stop-color': '#ff6' }
]
};
createGradient(svg, properties);
var chartPath = svg.getElementsByTagName('path')[1]; //0 path corresponds to legend path
chartPath.setAttribute('stroke', 'url(#chartGradient)');
}
function createGradient(svg, properties) {
var svgNS = svg.namespaceURI;
var grad = document.createElementNS(svgNS, 'linearGradient');
grad.setAttribute('id', properties.id);
["x1","y1","x2","y2"].forEach(function(name) {
if (properties.hasOwnProperty(name)) {
grad.setAttribute(name, properties[name]);
}
});
for (var i = 0; i < properties.stops.length; i++) {
var attrs = properties.stops[i];
var stop = document.createElementNS(svgNS, 'stop');
for (var attr in attrs) {
if (attrs.hasOwnProperty(attr)) stop.setAttribute(attr, attrs[attr]);
}
grad.appendChild(stop);
}
var defs = svg.querySelector('defs') ||
svg.insertBefore(document.createElementNS(svgNS, 'defs'), svg.firstChild);
return defs.appendChild(grad);
}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id="chart_div"></div>
JSFiddle