Smaller scale for volume dataset in Chart JS - javascript

I'm graphing some stocks data and I wanted to put the volume in a smaller gray bar dataset at the bottom, like in Yahoo Finance.
What I want:
The small grey dataset is at the bottom.
What I get:
Three different Y scales and the size of the volume dataset is the same a the other.
My code:
When I create the chart:
new Chart(context, {
type: 'line',
data: {
labels: timestamps.map(n =>
(new Date(n * 1000)).toLocaleString()
),
datasets: [
dataset,
vdataset
]
},
options: {
maintainAspectRatio: false,
scales: {
xAxis: {
// type: 'time'
ticks: {
//autoSkip: true,
maxTicksLimit: 10
}
},
yAxes: [{
id: 'volume',
display: false
}],
y: {
beginAtZero: false
},
},
animation: {
duration: 0
},
plugins: {
autocolors: false,
annotation: {
annotations
}
},
tooltips: {
mode: 'nearest'
},
hover: {
intersect: false
}
}
});
The volume dataset:
{
type: 'bar',
label: `Volume`,
data: ...,
backgroundColor: 'transparent',
borderColor: 'grey',
fill: 'origin',
pointRadius: 0,
borderWidth: 2,
yAxisID: 'volume'
}

you need to give every dataset a yAxisID and then you should name your axis with that id like this:
Data:
var data = {
labels: labels,
datasets: [{
label: 'My First Dataset',
data: generateTestSeries(),
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
yAxisID: "something",
},
{
label: 'My Second Dataset',
data: generateTestSeries(),
fill: false,
borderColor: 'rgb(182, 50, 192)',
tension: 0.1,
yAxisID: "volume",
},
]
};
Scales:
scales: {
volume: {
axis: "y",
min: -80,
max: 60,
position: 'right',
},
something: {
axis: "y",
min: -20,
max: 70,
position: 'left',
}
}
Also you shouldn't have the list yAxes, that was how axes were defined in chartjs 2.x
Here is a fiddle to see this in use: JSFiddle
edit: If you want an invisible axis just set display to false as seen in the now updated Fiddle.

Related

How to align vertical axis area on two charts in chart.js

in chart.js I'd like to have 2 charts (one under another) with ticks syncronized. Currently it looks so
as you can see dates are not aligned. Setting equal min-max values is impossible here since values are too different.
I think the solution would be to set equal width to both y-axes. The case is complicated by the second y-axes in upper chart, but may be it's possible to place an empty right scale on the bottom chart?
My current options for the top chart are
options: {
tooltips: {
enabled: true,
trigger: 'axis',
intersect: false,
mode : 'index'
},
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
// left: 500,
right: 0,
top: 0,
bottom: 0,
},
},
scales: {
xAxes: [
{
boundaryGap : false,
gridLines: {
display: false,
},
ticks: {
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return value.split('.').slice(0,2).join('.');
}
},
},
],
yAxes: [
{
id: keys[0],
position: "left",
gridLines: {
drawBorder: false,
zeroLineColor: "rgba(147, 147, 147, 0.2)",
color: "rgba(147, 147, 147, 0.2)",
},
ticks: {
padding: 20,
fontColor: "#2C71C3",
beginAtZero: false,
},
}, {
id: keys[1],
position: "right",
gridLines: {
drawBorder: false,
color: "rgba(147, 147, 147, 0)",
},
ticks: {
padding: 20,
fontColor: "#C6C6C6",
beginAtZero: false,
},
},
],
},
and for the bottom one
options: {
tooltips: {
enabled: true,
trigger: 'axis',
intersect: false,
mode : 'index'
},
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
// left: 500,
right: 0,
top: 0,
bottom: 0,
},
},
scales: {
yAxes: [
{
ticks: {
reverse: true,
},
},
],
xAxes: [
{
gridLines: {
display: false,
},
ticks: {
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return value.split('.').slice(0,2).join('.');
}
},
},
],
},
I dont know how to or if it is even possible to define a width for a scale, but what you can do is add a second Y axis on the right with the grid dissabled and the callback returning a few spaces for spacing
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
position: 'left'
},
{
position: 'right',
gridLines: {
display: false
},
ticks: {
callback: () => (' ')
}
}
]
}
}
}
var 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/2.9.4/Chart.js"></script>
</body>
Little late to the party, but it is possible to set a fixed width. I updated #LeeLenalee snippet with an example (both y axis have a 100px width in this case). This way, it is possible to align both graphs without any problem. Make sure to set a width that isn't too small for the labels though!
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
position: 'left',
afterFit: (scaleInstance) => scaleInstance.width = 100,
},
{
position: 'right',
afterFit: (scaleInstance) => scaleInstance.width = 100,
gridLines: {
display: false
},
ticks: {
callback: () => ''
}
}
]
}
}
}
var 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/2.9.4/Chart.js"></script>
</body>

Chart.js x-axes not working?

I'm trying to make a chart that displays data. I can't seem to get the x axis to work. If I add type:'linear', then it doesn't display the data, but the x-axes displays. If I don't add that, then the data gets displayed, but the x axes doesn't work.
var chart = new Chart(document.getElementById("graph"),
{
type: 'line',
data: {
//labels: [1500,1600,1700,1750,1800,1850,1900,1950,1999,2050],
datasets: [{
display: true,
data: [86,114,106,106,107,111,133,221,783,2478],
label: "Africa",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
scaleShowValues: true,
responsive: false,
title: {
display: true,
text: 'World population (in millions)'
},
scales: {
yAxes: [
{
type: 'linear',
ticks: {
beginAtZero:true,
min: -10,
max: 110,
}
}
],
xAxes: [{
display: true,
position: 'bottom',
//type: 'linear',
ticks: {
display:true,
min: 0,
max: 3000,
stepSize: 10,
autoSkip: true
}
}
]
}
}
});
The data does not fit the type of the chart, there should be two coordinates 'x' and 'y'. Line chart must have data like:
data: [{
x: 10,
y: 20
}, {
x: 15,
y: 10
}]
And delete this rows: min: -10,
max: 110,
That way the graph looks more beautiful and knows how to adjust the Y values itself.

Chart JS: Ignoring x values and putting point data on first available labels

I am making a line chart in chart.js, and am having an issue where I am trying to plot point data on the line but it is ignoring the x values I am giving, and instead putting them on the first available label.
this.myLineChart = new Chart(this.ctx, {
type: 'line',
data: {
labels: [0,2,4,6,8,10],
datasets: [{
label: 'mylabel1',
fill: false,
backgroundColor: 'blue',
borderColor: 'blue',
data: [{
x: 2.5,
y: 85
}, {
x: 3.5,
y: 85
}]
}]
},
options: {
title: {
display: true,
text: 'mytitle1'
},
scales: {
yAxes: [{
display: true,
ticks: {
suggestedMin: 70,
suggestedMax: 100
}
}]
}
}
});
The result I get is this:
But instead I would like this line to be at the x values 2.5 and 3.5, so that it lies in between the 2 and 4 labels.
What should I change in the code to make it behave as I want?
In that case, you don't need to use labels array. Instead set x-axis' type to linear and minimum and maximum value for x-axis' ticks (perhaps stepSize as well) in your chart options, like so :
xAxes: [{
type: 'linear',
ticks: {
suggestedMin: 0,
suggestedMax: 10,
stepSize: 2
}
}]
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
myLineChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'mylabel1',
fill: false,
backgroundColor: 'blue',
borderColor: 'blue',
data: [{
x: 2.5,
y: 85
}, {
x: 3.5,
y: 85
}]
}]
},
options: {
title: {
display: true,
text: 'mytitle1'
},
scales: {
xAxes: [{
type: 'linear',
ticks: {
suggestedMin: 0,
suggestedMax: 10,
stepSize: 2 //interval between ticks
}
}],
yAxes: [{
display: true,
ticks: {
suggestedMin: 70,
suggestedMax: 100
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>

Char.js Interpolation linear

i'm trying to draw functions with Chart.js
I have a problem with my draw let's see :
here
This is the 'x' function and the line isn't straight
I don't know if it's a problem of resolution or of interpolation
So here is my chart :
var scatterChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
borderWidth:2,
pointRadius :0,
borderColor: 'rgba(0, 0, 255, 1)',
label: 'Scatter Dataset',
data: JSON.parse(data),
fill: false,
lineTension: 0,
cubicInterpolationMode: 'linear'
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'bottom'
}]
},
pan: {
enabled: true,
mode: 'xy'
},
zoom: {
enabled: true,
mode: 'xy',
},
responsive: true,
maintainAspectRatio: true,
}
});
Thx guys
The problem is how chart.js is drawing the small line segments between data points. Here is a fiddle that animates a full opacity line over top of a lighter line. The second line is growing at a step=1 while the lighter line is nice and straight [{x:-100,y:-100},{x:100,y:100}]. If you change to step=10 you will see the line fill in straight.
In the code below (or in the fiddle) you can play around with changing the borderWidth, borderColor, and opacity. I tried adding borderCapStyle: 'round' and borderJoinStyle: 'round', but neither seemed to have much effect.
var ctx = document.getElementById("test").getContext("2d");
var i = -100;
var data = [{x: i, y: i}];
var scatterChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
borderWidth: 2,
pointRadius: 0,
borderColor: 'rgba(0, 0, 255, 1)',
label: 'Scatter Dataset 1',
data: data,
fill: false,
lineTension: 0,
cubicInterpolationMode: 'linear'
}, {
borderWidth: 2,
pointRadius: 0,
borderColor: 'rgba(0, 0, 255, 0.4)',
label: 'Scatter Dataset 2',
data: [{x:-100,y:-100},{x:100,y:100}],
fill: false,
lineTension: 0,
cubicInterpolationMode: 'linear'
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'bottom'
}]
},
pan: {
enabled: true,
mode: 'xy'
},
zoom: {
enabled: true,
mode: 'xy',
},
responsive: true,
maintainAspectRatio: true,
}
});
var step = 1;
var intervalId = setInterval(function() {
i += step;
if (i <= 100) {
scatterChart.data.datasets[0].data.push({x:i,y:i});
scatterChart.update();
} else {
clearInterval(intervalId);
}
}, 200);
and
<canvas id="test" width="400" height="300"></canvas>

Chart.js v2 - combined stacked bar chart and 2 unstacked lines

Can Chart.js v2.x generate a combined stacked bar chart with 2 unstacked lines utilizing one y-axis? If so, how?
Below fiddle has 2 y-axis. The descending line, would render better if the right y-axis had a maximum value of 6000 as does the left axis.
jsfiddle example.
Below is the code for reference.
// set default no fill beneath the line
Chart.defaults.global.elements.line.fill = false;
// stacked bar with 2 unstacked lines - nope
var barChartData = {
labels: ['2016', '2017', '2018', '2019'],
datasets: [{
type: 'bar',
label: 'a',
yAxisID: "y-axis-0",
backgroundColor: "rgba(217,83,79,0.75)",
data: [1000, 2000, 4000, 5000]
}, {
type: 'bar',
label: 'b',
yAxisID: "y-axis-0",
backgroundColor: "rgba(92,184,92,0.75)",
data: [500, 600, 700, 800]
}, {
type: 'line',
label: 'c',
yAxisID: "y-axis-0",
backgroundColor: "rgba(51,51,51,0.5)",
data: [1500, 2600, 4700, 5800]
}, {
type: 'line',
label: 'd',
yAxisID: "y-axis-1",
backgroundColor: "rgba(151,187,205,0.5)",
data: [5000, 3000, 1000, 0]
}]
};
var ctx = document.getElementById("chart").getContext("2d");
// allocate and initialize a chart
var ch = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: true,
text: "Chart.js Bar Chart - Stacked"
},
tooltips: {
mode: 'label'
},
responsive: true,
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true,
position: "left",
id: "y-axis-0",
}, {
stacked: false,
position: "right",
id: "y-axis-1",
}]
}
}
});
Turns out, I just needed a modification or two so that the 2 y-axis use the same scale. See this jsfiddle. Now the chart renders better. The key, in my case, is adding a ticks node and these two properties to both yAxes objects:
ticks: {
beginAtZero: true,
suggestedMax: 5800
}
Naturally, the suggestedMax value would not be hard coded. Further, since the 2 scales are now the same, I hid the right scale with this property setting display: false.
As the fiddle shows, we now have 2 unstacked lines on a stacked bar chart nicely rendered.
Use this as the data for the graph:
var barData = {
labels: ['test1','test2'],
datasets: [
{
label: 'stack1',
backgroundColor: 'yellow',
borderColor: 'white',
borderWidth: 1,
stack: '1',
data: [5,4,3,2,1]
},
{
label: 'stack2',
backgroundColor: 'blue',
borderColor: 'white',
borderWidth: 1,
stack: '2',
data: [1,2,3,4,5]
}
]
};
This is the component to render the data:
<Bar data={barData} options={{scales: { xAxes: [{stacked:true}} }], yAxes:[{stacked:true}}] } }}}} />

Categories

Resources