Related
I am experimenting with Chart.js to build radar charts. I mastered the basics (see basic chart below), but I would like to use the x y coordinates of the graph to place texts directly on the canvas.
After some digging, I found out that it is not possible to use getValueForPixel or getPixelForTick in a radar chart. See this github issue. In the connecting thread, a new method getValueForDistanceFromCenter is introduced.
As I understand it, it would be possible to calculate the distance from the center with this method, and use it to get coordinates. I searched the Chart.js documentation and other sites, but cannot find any code examples or information on how to implement this.
Can somebody point me in the right direction how to implement the method in the code?
var data = {
labels: ["Ball Skills", "Shooting", "Physical"],
datasets: [{
label: [`ikke`, `jij`],
backgroundColor: "rgba(38,120,255,0.2)",
borderColor: "rgba(38,120,255, 1)",
data: [90, 90, 90]
}]
};
var options = {
responsive: true,
tooltips: false,
title: {
text: 'Basic example',
display: true,
position: `bottom`,
},
scale: {
angleLines: {
display: true
},
ticks: {
suggestedMin: 0,
suggestedMax: 100,
stepSize: 25,
maxTicksLimit: 11,
display: false,
}
},
legend: {
labels: {
padding: 10,
fontSize: 14,
lineHeight: 30,
},
},
};
var myChart = new Chart(document.getElementById("chart"), {
type: 'radar',
data: data,
options: options
});
The radialLinear scale (in version 2.9.4 that I have seen your are using version 2) there is the method getValueForDistanceFromCenter(value) to get the distance from center but there is another method getPointPositionForValue(index, value) which can provide you the point at a specif index of your data.
To use them and to draw what you want on chart using those points, you need to implement a plugin.
In the below snippet, I'm drawing a rect between the points at a specific value.
const ctx = document.getElementById("myChart");
const data = {
labels: ["Ball Skills", "Shooting", "Physical"],
datasets: [{
label: [`ikke`, `jij`],
backgroundColor: "rgba(38,120,255,0.2)",
borderColor: "rgba(38,120,255, 1)",
data: [50, 50, 50]
}]
};
const options = {
responsive: true,
tooltips: false,
title: {
text: 'Basic example',
display: true,
position: `bottom`,
},
scale: {
angleLines: {
display: true
},
ticks: {
suggestedMin: 0,
suggestedMax: 100,
stepSize: 25,
maxTicksLimit: 11,
display: false,
}
},
legend: {
labels: {
padding: 10,
fontSize: 14,
lineHeight: 30,
},
},
};
const plugin = {
id: 'getDistance',
afterDraw(chart) {
const c = chart.ctx;
const rScale = chart.scale;
c.save();
chart.data.datasets[0].data.forEach(function(item, index) {
const point = rScale.getPointPositionForValue(0.5 + index, 50);
c.beginPath();
c.fillStyle = 'red';
c.fillRect(point.x - 5, point.y - 5, 10, 10);
c.fill();
});
c.restore();
}
};
const myChart = new Chart(ctx, {
type: 'radar',
plugins: [plugin],
data: data,
options: options
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4/dist/Chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"/>
</div>
</body>
</html>
I need to plot a single value in line chart. Currently i am using charts.JS library for line graph purpose.
The data will be varied some times i'll get the single data inside the data set at that time i need to plot the single value with line in the line chart.
I tried with the charts.js annotation plugin but it wasn't met my requirements. which is like it wis overlapping the plotted point in the graph area.
CODE WHICH I HAD TRIED
createLineChart() {
this.lineChart = new Chart(this.lineCanvas.nativeElement, {
type: "line",
data: {
labels:[],
datasets: [
{
fill: false,
backgroundColor: "#0168FF",
borderColor: "#0168FF",
pointBackgroundColor: "white", // wite point fill
pointBorderWidth: 1, // point border width
lineTension: 0,
pointBorderColor: "blue",
pointRadius: 4,
},
],
},
options: {
scales: {
yAxes: [
{
ticks: {
padding: 20,
beginAtZero: true,
min: 0,
stepSize: 100,
},
gridLines: {
drawBorder: false,
},
},
],
xAxes: [
{
// offset: true,
ticks: {
display: false,
//beginAtZero: true,
min: 0,
},
gridLines: {
zeroLineColor: "transparent",
drawBorder: false,
display: false,
},
//offset:true,
},
],
legend: {
display: false,
},
tooltips: {
enabled: false,
},
},
drawTime: "afterDraw", // (default)
} as ChartOptions,
// plugins: [ChartAnnotation]
},
});
}
To generate dynamic data and plot in the graph area.
generateRandomDataSet(size) {
let yaxisArr = [];
let xaxisArr = [];
let random_data:any = this.getRandomData(size)
let maxYTickVal = Math.max.apply(Math, random_data.map((val) => {return val.yaxis}));
let maxVal = Math.ceil((maxYTickVal+1) / 10) * 10
for(let data of random_data) {
yaxisArr.push(data.yaxis)
xaxisArr.push(data.xaxis)
}
console.log("X-Axis array values : "+xaxisArr)
console.log("Y-Axis array values : "+yaxisArr)
this.lineChart.data.datasets[0].data = yaxisArr
this.lineChart.config.data.labels = []
this.lineChart.config.data.labels = xaxisArr
this.lineChart.config.options.scales.yAxes[0].ticks.max =maxVal
this.lineChart.config.options.scales.yAxes[0].ticks.stepSize = maxVal/2
this.lineChart.update()
}
getRandomData(arraySize) {
let data = []
for(var i=1; i<=arraySize; i++) {
let number = Math.floor(Math.random() * 200) + 1
data.push({'xaxis':i,'yaxis':number})
}
return data
}
with the above code i am getting like
what i need to have
You can define an animation.onComplete function as follows to draw the line in case a single data value is present.
animation: {
onComplete: e => {
var ctx = chart.chart.ctx;
var data = chart.config.data.datasets[0].data;
if (data[0] == null) {
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var y = yAxis.getPixelForValue(data[1]);
ctx.save();
ctx.globalCompositeOperation='destination-over';
ctx.strokeStyle = 'blue'
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
ctx.restore();
}
}
},
This function expects the data array to be of format [null, <value>, null] in case a single value is present, otherwise it will be hard to horizontally center the data point (see this answer). It's up to you to change the generateRandomDataSet() function in a way that it provides such data.
Please have a look at your changed code below.
const chart = new Chart('line-chart', {
type: "line",
data: {
labels: ['', 'A', ''],
datasets: [{
data: [null, 120, null],
fill: false,
backgroundColor: "#0168FF",
borderColor: "#0168FF",
pointBackgroundColor: "white",
pointBorderWidth: 1,
lineTension: 0,
pointBorderColor: "blue",
pointRadius: 4,
}],
},
options: {
legend: {
display: false
},
tooltips: {
enabled: false
},
animation: {
onComplete: e => {
var ctx = chart.chart.ctx;
var data = chart.config.data.datasets[0].data;
if (data[0] == null) {
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var y = yAxis.getPixelForValue(data[1]);
ctx.save();
ctx.globalCompositeOperation='destination-over';
ctx.strokeStyle = 'blue'
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
ctx.restore();
}
}
},
scales: {
yAxes: [{
ticks: {
padding: 20,
min: 0,
stepSize: 100
},
gridLines: {
drawBorder: false
}
}],
xAxes: [{
ticks: {
display: false
},
gridLines: {
zeroLineColor: "transparent",
drawBorder: false,
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="line-chart" height="80"></canvas>
I had applied some gradient rule to my chartjs chart. And it looks great as you can see on the below
However, when the browser window is resized (i.e. width of window is smaller), the gradient is ruined (bottom blue colors disappeared). Screenshot:
I want to maintain the graph's gradient with all values and fit the different widths (responsive). Is there any way to do that? Here is what I had tried but didn't work:
.TS File
ngAfterViewInit() {
const ctx = (<HTMLCanvasElement>this.myChart.nativeElement).getContext('2d');
const purple_orange_gradient = ctx.createLinearGradient(0, 200, 0, 20);
purple_orange_gradient.addColorStop(0.1, "#000279");
purple_orange_gradient.addColorStop(0.2, "#0000F2");
purple_orange_gradient.addColorStop(0.3, "#0362FD");
purple_orange_gradient.addColorStop(0.4, "#04D3FD");
purple_orange_gradient.addColorStop(0.5, "#45FFB7");
purple_orange_gradient.addColorStop(0.6, "#B7FF46");
purple_orange_gradient.addColorStop(0.7, "#FFD401");
purple_orange_gradient.addColorStop(0.8, "#FE6500");
purple_orange_gradient.addColorStop(0.9, "#F30004");
purple_orange_gradient.addColorStop(1, "#7E0100");
const bar_chart = new Chart(ctx, {
type: "horizontalBar",
data: {
labels: []=this.histogramLabels.reverse(),
datasets: [{
borderColor: purple_orange_gradient,
pointBorderColor: purple_orange_gradient,
pointBackgroundColor: purple_orange_gradient,
pointHoverBackgroundColor: purple_orange_gradient,
pointHoverBorderColor: purple_orange_gradient,
pointBorderWidth: 10,
pointHoverRadius: 10,
pointHoverBorderWidth: 1,
pointRadius: 3,
fill: true,
backgroundColor: purple_orange_gradient,
borderWidth: 4,
data: []=this.histogramGraphData
}]
},
options: {
legend: {
display:false,
position: "bottom"
},
scales: {
yAxes: [{
ticks: {
display: false,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold",
beginAtZero: true,
maxTicksLimit: 1,
padding: 20,
},
gridLines: {
drawTicks: false,
display: false
}
}],
xAxes: [{
gridLines: {
zeroLineColor: "transparent",
},
ticks: {
padding: 20,
beginAtZero: true,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold"
}
}]
}
}
}
)
}
.HTML
<div class="row my-2">
<div class="col-md-6">
<canvas id=”myChart” #myChart height="130"></canvas>
</div>
</div>
HTML Canvas' createLinearGradient() depends on the y axis coordinates that you pass in as argument. You had passed in a static 200 every time (i.e. ctx.createLinearGradient(0, 200, 0, 20);).
That's why the gradient's steps remains the same everytime. For the gradient to update, you have to recalculate the height of the <canvas> element on window resize and pass it in to createLinearGradient() again.
You can accomplish this by:
Separating the block where you create the gradient into a separate function. eleHeight retrieves the height of the canvas element.
generateGradient(){
let eleHeight = this.myChart.nativeElement.offsetHeight;
// console.log(eleHeight)
let purple_orange_gradient: CanvasGradient = this.myChart.nativeElement.getContext('2d').createLinearGradient(0, eleHeight, 0, 20);
purple_orange_gradient.addColorStop(0.1, "#000279");
purple_orange_gradient.addColorStop(0.2, "#0000F2");
purple_orange_gradient.addColorStop(0.3, "#0362FD");
purple_orange_gradient.addColorStop(0.4, "#04D3FD");
purple_orange_gradient.addColorStop(0.5, "#45FFB7");
purple_orange_gradient.addColorStop(0.6, "#B7FF46");
purple_orange_gradient.addColorStop(0.7, "#FFD401");
purple_orange_gradient.addColorStop(0.8, "#FE6500");
purple_orange_gradient.addColorStop(0.9, "#F30004");
purple_orange_gradient.addColorStop(1, "#7E0100");
return purple_orange_gradient;
}
Add a onresize event handler to your containing <div> and generate the gradient again. You also need to programatically update the chart every time you make a change to re-render it.
<div style="display: block; max-height: 100%" (window:resize)="onResize($event)" >
...
</div>
onResize(event?){
// console.log("onResize");
this.barChartData.forEach((d, i) => {
d.backgroundColor = this.generateGradient();
})
this.chart.chart.update(); //update the chart to re-render it
}
Update the barchartData's properties (that uses gradient) in ngAfterViewInit. We need to do this here because we only want the height of the <canvas> element with data populated. Without data populated, the element is much smaller.
ngAfterViewInit(){
this.barChartData.forEach((d, i) => {
d.backgroundColor = this.generateGradient();
});
this.chart.chart.update(); //update the chart to re-render it
}
Have a look at this Stackblitz example⚡⚡ I have created.
You have to change the gradient whenever your canvas is resizing. Took me a while to figure out a good structure to minimize lines of code and optimize performance. This is the best I could achieve.
There are exeptions when the chart.js onResize() fires though but I couldn't solve this issue completly bulletproof. But for simple resizes it should work.
Complete code (same code in JSBin with live preview):
let sData = {}
sData.labels = []
sData.data = []
const count = 50
for (let x = 0; x < count; x++) {
sData.data.push(Math.floor(Math.random()*100))
sData.labels.push(x)
}
const canvas = document.getElementById('chart')
const ctx = canvas.getContext("2d")
let purple_orange_gradient
function updateGradient() {
let bottom = bar_chart.chartArea.bottom
let top = bar_chart.chartArea.top
purple_orange_gradient = ctx.createLinearGradient(0, bottom+top, 0, top)
purple_orange_gradient.addColorStop(0.1, "#000279")
purple_orange_gradient.addColorStop(0.2, "#0000F2")
purple_orange_gradient.addColorStop(0.3, "#0362FD")
purple_orange_gradient.addColorStop(0.4, "#04D3FD")
purple_orange_gradient.addColorStop(0.5, "#45FFB7")
purple_orange_gradient.addColorStop(0.6, "#B7FF46")
purple_orange_gradient.addColorStop(0.7, "#FFD401")
purple_orange_gradient.addColorStop(0.8, "#FE6500")
purple_orange_gradient.addColorStop(0.9, "#F30004")
purple_orange_gradient.addColorStop(1.0, "#7E0100")
return purple_orange_gradient
}
const bar_chart = new Chart(ctx, {
type: "horizontalBar",
data: {
labels: sData.labels,
datasets: [{
borderColor: purple_orange_gradient,
pointBorderColor: purple_orange_gradient,
pointBackgroundColor: purple_orange_gradient,
pointHoverBackgroundColor: purple_orange_gradient,
pointHoverBorderColor: purple_orange_gradient,
pointBorderWidth: 10,
pointHoverRadius: 10,
pointHoverBorderWidth: 1,
pointRadius: 3,
fill: true,
backgroundColor: purple_orange_gradient,
borderWidth: 4,
data: sData.data
}]
},
options: {
legend: {
display: false,
position: "bottom"
},
scales: {
yAxes: [{
ticks: {
display: false,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold",
beginAtZero: true,
maxTicksLimit: 1,
padding: 20,
},
gridLines: {
drawTicks: false,
display: false
}
}],
xAxes: [{
gridLines: {
zeroLineColor: "transparent",
},
ticks: {
padding: 20,
beginAtZero: true,
fontColor: "rgba(0,0,0,0.5)",
fontStyle: "bold"
}
}]
},
onResize: function(chart, size) {
// onResize gradient change
changeGradient()
}
}
});
// Initial gradient change
changeGradient()
function changeGradient() {
let newGradient = updateGradient()
bar_chart.data.datasets[0].borderColor = newGradient
bar_chart.data.datasets[0].pointBorderColor = newGradient
bar_chart.data.datasets[0].pointBackgroundColor = newGradient
bar_chart.data.datasets[0].pointHoverBackgroundColor = newGradient
bar_chart.data.datasets[0].pointHoverBorderColor = newGradient
bar_chart.data.datasets[0].backgroundColor = newGradient
bar_chart.update()
}
I've spent hours already trying to figure out how to offset the horizontal bars from the zero line on X-Axis so it doesn't overlap when the width of the line is bigger than 1.
Appreciate all the help.
Example is here on CodePen (hope it will show up): https://codepen.io/RomanKl/pen/mzmegG
var barOptions = {
tooltips: {
enabled: false
},
hover :{
animationDuration:0
},
scales: {
xAxes: [{
ticks: {
beginAtZero:true,
min: 0,
max: 10000,
fontFamily: "'Open Sans Bold', sans-serif",
fontSize:12,
callback: function(value, index, values) {
return Math.round(value/1000) + 'k';
}
},
scaleLabel:{
display:false
},
gridLines: {
color: ['#000', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef', '#efefef'],
lineWidth: [4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
zeroLineWidth: 4,
zeroLineColor: '#000',
},
}],
yAxes: [{
gridLines: {
display: false,
},
ticks: {
fontFamily: "'Open Sans Bold', sans-serif",
fontSize:14,
},
}]
},
legend:{
display:false
},
animation: {
onComplete: function () {
var chartInstance = this.chart;
var ctx = chartInstance.ctx;
ctx.textAlign = "left";
ctx.font = "1.6rem Open Sans";
ctx.fillStyle = "#fff";
Chart.helpers.each(this.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
Chart.helpers.each(meta.data.forEach(function (bar, index) {
data = dataset.data[index];
data = data.toFixed(0).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
if(i==0){
ctx.fillText(data, 80, bar._model.y+4);
} else {
ctx.fillText(data, bar._model.x-25, bar._model.y+4);
}
}),this)
}),this);
}
},
};
var ctx = document.getElementById("Chart1");
var myChart = new Chart(ctx, {
type: 'horizontalBar',
borderSkipped: 'bottom',
data: {
labels: ["Aug.'17", "Aug.'18"],
datasets: [{
data: [6336, 6892],
backgroundColor: "rgba(63,103,126,1)",
hoverBackgroundColor: "rgba(50,90,100,1)"
}]
},
options: barOptions,
});
So I've brutally hacked it in the end. I've tried adding a border and then skip it everywhere except the start where I would set the colour to transparent but guess what? Border doesn't show up at the start. It's a requested feature not yet implemented in chart.js as of this posting.
In the end I've used a diabolical solution of using two stacked datasets while setting the first one via data to the desired offset and then setting backgroundColor to transparent and shifting data labels to the left via plugin.
you can see the result in the codepen link posted in the question.
I want to change the font to something snazzier in my Chart.JS horizontal bar chart. I've tried the following, but none of it works:
var optionsBar = {
. . .
//fontFamily: "'Candara', 'Calibri', 'Courier', 'serif'"
//bodyFontFamily: "'Candara', 'Calibri', 'Courier', 'serif'"
//bodyFontFamily: "'Candara'"
label: {
font: {
family: "Georgia"
}
}
};
I also read that this would work:
Chart.defaults.global.defaultFont = "Georgia"
...but where would this code go, and how exactly should it look? I tried this:
priceBarChart.defaults.global.defaultFont = "Georgia";
...but also to no good effet.
For the full picture/context, here is all the code that makes up this chart:
HTML
<div class="chart">
<canvas id="top10ItemsChart" class="pie"></canvas>
<div id="pie_legend"></div>
</div>
JQUERY
var ctxBarChart =
$("#priceComplianceBarChart").get(0).getContext("2d");
var barChartData = {
labels: ["Bix Produce", "Capitol City", "Charlies Portland",
"Costa Fruit and Produce", "Get Fresh Sales",
"Loffredo East", "Loffredo West", "Paragon", "Piazza Produce"],
datasets: [
{
label: "Price Compliant",
backgroundColor: "rgba(34,139,34,0.5)",
hoverBackgroundColor: "rgba(34,139,34,1)",
data: [17724, 5565, 3806, 5925, 5721, 6635, 14080, 9027,
25553]
},
{
label: "Non-Compliant",
backgroundColor: "rgba(255, 0, 0, 0.5)",
hoverBackgroundColor: "rgba(255, 0, 0, 1)",
data: [170, 10, 180, 140, 30, 10, 50, 100, 10]
}
]
}
var optionsBar = {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
},
//fontFamily: "'Candara', 'Calibri', 'Courier', 'serif'"
//bodyFontFamily: "'Candara', 'Calibri', 'Courier', 'serif'"
//bodyFontFamily: "'Candara'"
//Chart.defaults.global.defaultFont = where does this go?
label: {
font: {
family: "Georgia"
}
}
};
var priceBarChart = new Chart(ctxBarChart, {
type: 'horizontalBar',
data: barChartData,
options: optionsBar
});
//priceBarChart.defaults.global.defaultFont = "Georgia";
I even tried this:
CSS
.candaraFont13 {
font-family:"Candara, Georgia, serif";
font-size: 13px;
}
HTML
<div class="graph_container candaraFont13">
<canvas id="priceComplianceBarChart"></canvas>
</div>
...but I reckon the canvas drawing takes care of the font appearance, as adding this made no difference.
UPDATE
I tried this and it completely broke it:
Chart.defaults.global = {
defaultFontFamily: "Georgia"
}
UPDATE 2
As Matthew intimated, this worked (before any of the chart-specific script):
Chart.defaults.global.defaultFontFamily = "Georgia";
This should be useful: http://www.chartjs.org/docs/. It says "There are 4 special global settings that can change all of the fonts on the chart. These options are in Chart.defaults.global".
You'll need to change defaultFontFamily for the font. And defaultFontColor, defaultFontSize, and defaultFontStyle for color, size, etc.
If you wanted to add the font-family to the chart object then you can add it in the options object.
options: {
legend: {
labels: {
fontFamily: 'YourFont'
}
}...}
Here is a link to the docs: https://www.chartjs.org/docs/latest/general/fonts.html
Change font size, color, family and weight using chart.js
scales: {
yAxes: [{ticks: {fontSize: 12, fontFamily: "'Roboto', sans-serif", fontColor: '#000', fontStyle: '500'}}],
xAxes: [{ticks: {fontSize: 12, fontFamily: "'Roboto', sans-serif", fontColor: '#000', fontStyle: '500'}}]
}
See the full code
<!doctype html>
<html>
<head>
<title>Chart.js</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
<script src="js/Chart.bundle.js"></script>
<script src="js/utils.js"></script>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
font-weight:700;
}
</style>
</head>
<body>
<div id="container" style="width:70%;">
<canvas id="canvas"></canvas>
</div>
<script>
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var color = Chart.helpers.color;
var barChartData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
datasets: [{
label: 'Completed',
// Green
backgroundColor: '#4caf50',
borderColor: '#4caf50',
borderWidth: 1,
data: [
5, 15, 25, 35, 45, 55
]
}, {
label: 'Created',
// Blue
backgroundColor: '#1976d2',
borderColor: '#1976d2',
borderWidth: 1,
data: [
10, 20, 30, 40, 50, 60
]
}]
};
window.onload = function () {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
responsive: true,
legend: {
position: 'top',
onClick: null
},
title: {
display: true,
text: '',
fontSize: 20
},
scales: {
yAxes: [{ticks: {fontSize: 12, fontFamily: "'Roboto', sans-serif", fontColor: '#000', fontStyle: '500'}}],
xAxes: [{ticks: {fontSize: 12, fontFamily: "'Roboto', sans-serif", fontColor: '#000', fontStyle: '500'}}]
}
}
});
};
</script>
</body>
</html>
You named the chart priceBarChart in the following part of your code:
var priceBarChart = new Chart(ctxBarChart, {
type: 'horizontalBar',
data: barChartData,
options: optionsBar
})
Which means that priceBarChart.defaults.global.defaultFont = 'Georgia' will 'dive' into the variable priceBarChart, go into its default properties, change one of its global properties and that one is defaultFont, exactly what you want.
But when you apply this code, you basically create the chart with the wrong font and then change it again, which is a bit ugly. What you need to do is tell the chart what the font is beforehand.
You do this by merging your font declaration with the rest of the options, just like how you did it with your variables barChartData and optionsBar.
After you've created barChartData and optionsBar, create another variable with the name, let's say, defaultOptions, like so:
var defaultOptions = {
global: {
defaultFont: 'Georgia'
}
}
You can see that it has the same structure. You go into the global options, and change its defaultFont property. Now you need to apply it to the created chart at the moment it is created, like so:
var priceBarChart = new Chart(ctxBarChart, {
type: 'horizontalBar',
data: barChartData,
options: optionsBar,
defaults: defaultOptions //This part has been added
})
This method of overwriting options is what is being used in almost every JavaScript plugin. When you create a new instance, the plugin copies an object that contains objects that contain objects and so forth. But these objects can be modified with additional options, like barChartData, optionsBar and defaultOptions.
I hope this helps!