Chart.js How to invert (swap) axes? - javascript

Taking from inspiration from this question, I am trying to figure out how to swap the axes of a Line chart in Chart.js.
For instance, in Highcharts we have this example, although it's an area chart.
Is it possible to "swap" the X and Y axis on a line chart?
datasets: [
{
label: "data1a",
data: [1,2,3,4,5,1,2,3]
}
]
yAxes: [
{
type: "linear",
display: true,
position: "left",
}
]
Here's my fiddle modified from the above link. I'm basically trying to move it so the graph looks rotated 90 degrees. I tried changing the y position to 'top' but it still doesn't look correct.

The proposal by #dralth works fine with version 2.8.0, but for some reason showLines: true does not work anymore since version 2.9.0.
It is still possible showing the lines by using the showLine property for each dataset.
In case of #dralth's example it works as follows (tested with version 2.9.3):
new Chart(document.getElementById('myChart'), {
type: 'scatter',
data: {
datasets: [
{
label: 'My Dataset',
data: [{x: 3, y: 2}, {x: 5, y: 7}, {x: 9, y: 10}],
showLine: true
},
],
},
options: {
scales: {
xAxes: [
{
type: 'linear',
position: 'bottom',
},
],
yAxes: [
{
type: 'linear',
},
],
}
}
})

I was able to accomplish this in Chart.js 2.8.0:
Change data to a list of objects with x and y. Since the intention is to swap x and y axis, put the "x data" in the y variable and vise verse.
eg. [{x: 3, y: 2}, {x: 5, y: 7}, {x: 9, y: 10}]
Set the chart type to 'scatter'
Add showLines: true to the options
The outcome is a line chart where the line can be horizontal, vertical, or even double back on itself. The orientation of the line is defined by which values you put in x and which you put in y.
Here's an example configuration:
new Chart(document.getElementById('myChart'), {
type: 'scatter',
data: {
datasets: [
{
label: 'My Dataset',
data: [{x: 3, y: 2}, {x: 5, y: 7}, {x: 9, y: 10}],
},
],
},
options: {
showLines: true,
scales: {
xAxes: [
{
type: 'linear',
position: 'bottom',
},
],
yAxes: [
{
type: 'linear',
},
],
}
}
})
If you're using an older version of Chart.js that doesn't have scatter plots, you can use this plugin: http://dima117.github.io/Chart.Scatter/

Related

plotly two y-axis same position of zero-line

I want to plot two axis (bar + scatter) on a plotly chart with javascript, but I can't get the zero baseline of the second y-axis to align with the first axis.
Here is the result of the current version:
The Zero-line of the right y-axis (the scatter line) is higher than the zero-line of the left y-axis. I would want to have them on the same height in the plot, basically overlapping.
I create the Plotly object like this:
const trace1 = { x: dates, y: y1, name: 'item', type: 'bar' };
const trace2 = { x: dates, y: y1_cumsum, name: 'Total', yaxis: 'y2', type: 'scatter' };
Plotly.newPlot(MYDIV, [trace1,trace2], {
margin: {t: 0},
barmode: 'group',
hovermode: 'x unified',
yaxis: {title: 'item', dtick: 1},
yaxis2: {
title: 'total',
overlaying: 'y',
side: 'right'
},
showlegend: true,
legend: {
x: 0.25,
xanchor: 'right',
y: 1
}
});
I tried to change position in the config, but this does only affect the x-position, not where the y-axis starts. I can't find any suitable attribute in the docs (https://plotly.com/javascript/reference/layout/yaxis/) that would achieve that.
How can I set the position of the second y-axis to be the same as the first one?
Thanks.
Assuming you don't have negative values in your data, you can set layout.yaxis.rangemode = 'tozero'for one or both of your axes.
const trace1 = {
x: [3, 4, 5],
y: [0, 15, 13],
mode: 'markers+lines',
type: 'scatter',
yaxis: 'y2'
};
const trace2 = {
x: [3, 4, 5],
y: [1, 0, 3],
type: 'bar'
};
Plotly.newPlot('myDiv', [trace1,trace2], {
margin: {t: 0},
barmode: 'group',
hovermode: 'x unified',
yaxis: {title: 'item', dtick: 1},
yaxis2: {
title: 'total',
overlaying: 'y',
side: 'right',
rangemode: 'tozero'
},
showlegend: true,
legend: {
x: 0.25,
xanchor: 'right',
y: 1
}
});
<head>
<!-- Load plotly.js into the DOM -->
<script src='https://cdn.plot.ly/plotly-2.11.1.min.js'></script>
</head>
<body>
<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>
</body>

Chart.js different time datasets

I want to plot my temperature readings of my DIY thermostat and the heater-state using Chart.js. The heater-state is 0 or 1, but I saved it in a minimal representation: I have values only, when it comes on/off. The heating times are never equal to the measurement times, but in between.
I want to plot time-data on the same time x-axis. From at least 20 examples, questions here and other resources I collected this Fiddle, which is my best guess. However, I can't reasonably plot both time axes and their data. If I reduce it to numerical data on the x axis in a very much simplified example, I get the smaller dataset plotted on the first few x-values of the latter one.
The js code is:
var options = {
type: 'line',
data: {
labels: ["2018-12-07 08:45:17",
"2018-12-07 09:30:17", "2018-12-07 10:15:16",
"2018-12-07 11:00:17", "2018-12-07 14:45:16"],
datasets: [
{
label: '1st line',
data: [12, 19, 7, 9, 10, 8],
},
{
steppedLine: 'before',
xAxisID: 'x-axis-2',
label: '2nd line',
data: [
{
x: "2018-12-07 09:15:47",
y: 3
}, {
x: "2018-12-07 10:55:25",
y: 5
}, {
x: "2018-12-07 13:05:00",
y: 3
}],
}
]
},
options: {
scales: {
xAxes: [{}, {
id: 'x-axis-2',
type: 'linear',
position: 'bottom',
//display: false,
}],
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
First, you could use a unique xAxis and define it as a time cartesian axis.
xAxes: [{
type: 'time',
time: {
unit: 'second'
}
}]
Also you shouldn't provide data.labels but rather define each data point using an object containing x and y properties.
var options = {
type: 'line',
data: {
datasets: [{
label: '1st line',
data: [{
x: "2018-12-07 08:45:17",
y: 12
},
{
x: "2018-12-07 09:30:17",
y: 19
},
{
x: "2018-12-07 10:15:16",
y: 7
},
{
x: "2018-12-07 11:00:17",
y: 9
},
{
x: "2018-12-07 14:45:16",
y: 10
}
]
},
{
label: '2nd line',
steppedLine: 'before',
data: [{
x: "2018-12-07 09:15:47",
y: 3
},
{
x: "2018-12-07 10:55:25",
y: 5
},
{
x: "2018-12-07 13:05:00",
y: 3
}
],
backgroundColor: 'lightgreen'
}
]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'second'
}
}]
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="chartJSContainer" height="90"></canvas>
I was finally able to figure out the problem which was the datastructure of the javaScript object. It requires this structure [{ "x": 1, "y":1}, {"x":2, "y":3} ] where in particular the x and y are the object properties x and y for each entry, rather than once and for all (which always made a lot more sense to me). But I can send the data without this extra labels and convert them on the fly with javascript like so:
datasets: [
{
label: 'Temperature',
data: response.temperature.x.map((x, i) => ({ x, y: response.temperature.y[i] })),
},
{
label: 'Room 2 Temperature',
data: response.temp2.x.map((x, i) => ({ x, y: response.temp2.y[i] })),
},
] // datasets

Chart.js line chart with correctly spaced x labels

By default, chart.js seems to space out its x labels equally instead of plotting the (x,y) pairs in space.
var options = {
type: 'line',
data: {
labels: [0, 1, 10],
datasets: [{
data: [1, 2, 1]
}]
},
}
This puts the "1" label halfway between the 0 and the 10 on the x-axis (here's a fiddle). How can I make it locate 1/10 of the way to 10?
As per Chart.js xAxis linear scale : strange behavior you need a linear x-axis with data supplied as x,y pairs.
So, it needs to be:
var ctx = document.getElementById('chartJSContainer').getContext('2d');
var scatterChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Linear Dataset',
data: [{ x: 0, y: 1}
,{x: 1, y: 2 }
,{ x: 10, y: 1} ]
}]
},
options: {
scales: {
xAxes: [{
type: 'linear'
,position: 'bottom'
}]
}
}
});

Highcharts: completely custom label positions on x-axis

I'm trying to make a histogram using highcharts, but the data is being bucketed by the server so as far as I can tell, I can't use the histogram chart type.
Here's my chart:
Highcharts.chart('container', {
credits: {
enabled: false
},
title: {
text: null
},
xAxis: {
type: 'category',
labels: {
rotation: -45
}
},
series: [
{
type: 'variwide',
showInLegend: false,
data: [
{ name: '0.00 - 10.10', y: 13, z: 1260000 },
{ name: '10.10 - 34.14', y: 10, z: 3000000 },
{ name: '34.14 - 54.56', y: 9, z: 2550000 },
{ name: '54.56 - 71.43', y: 15, z: 2110000 },
{ name: '71.43 - 102.09', y: 4.6, z: 3830000 },
{ name: '102.09 - 161.56', y: 1.8, z: 7430000 },
{ name: '161.56 - 217.26', y: 5.7, z: 6960000 },
{ name: '217.26 - 301.65', y: 0.7, z: 10550000 },
{ name: '301.65 - 382.82', y: 2.8, z: 10150000 },
{ name: '382.82 - 874.80', y: 0.2, z: 61500000 }
]
}
]
});
#container {
max-width: 800px;
min-width: 380px;
margin: 0 auto;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/variwide.js"></script>
<div id="container"></div>
As you can see, the labels look pretty bad.
Two solutions, neither of which I can work out how to do:
Rename the points (I can do this) and move them to the right so that they're under the ticks
Better solution: make the x axis linear and have the labels appear in natural places like they would usually on a linear graph, similar to https://www.highcharts.com/demo/histogram . Changing the axis to linear seems to mess everything up on a variwide chart, though…
Any ideas?
Variwide series doesn't support non categorized x axis. It's reported as an issue on github: https://github.com/highcharts/highcharts/issues/7359
Workaround:
Variwide can be simulated by using column series.
Create a separate series for each point and link them together by putting linkedTo: ':previous' in each of them (except of the first one). Then set pointRange for every series. pointRange is series' property and cannot be assigned to individual points - that's why separate series has to be crated for each point.
series: [{
data: [
[5, 99]
],
pointRange: 2
}, {
linkedTo: ':previous',
data: [
[7.5, 72]
],
pointRange: 3
}, {
linkedTo: ':previous',
data: [
[14, 111]
],
pointRange: 10
}]
x position of the point indicates the middle of the column. So if the x = 5 and pointRange = 2 then the column will span from 4 to 6.
Unfortunately Highcharts doesn't handle extremes well while using multiple values of pointRange. Setting x axis minimum fixes it:
xAxis: {
min: 9, // 4 (axis' minimum) + 10 (max point range) / 2 = 9
},
These plotOptions are required to achieve proper widths of columns:
grouping: false,
groupPadding: 0,
pointPadding: 0,
Live demo: http://jsfiddle.net/BlackLabel/27gr3wh8/
API reference: https://api.highcharts.com/highcharts/

Disable tooltip in CanvasJS Combination Chart

Is it possible to disable tooltips for only one series in a combination chart of canvasjs below?
data: [
{
type: "area",
color: "red", // change color here
fillOpacity: 1,
dataPoints: [
{ x: 0, y: 100 },
{ x: 100, y: 100 }
]
},
{
type: "area",
color: "yellow",
toolTipContent: " ",
dataPoints: [
{ x: 0, y: 10 },
{ x: 100, y: 100 }
]
}
]
Here is the link to my fiddle :
https://jsfiddle.net/Abhishek1191/s71djz9m/2
I have four separate series plotted inside the fiddle. 3 Area and 1 line. If anyone may let me know if I can disable tooltips for area series.
Thanks in advance
Instead of setting toolTipContent to empty string, set toolTipContent to null which will disable the toolTip for individual dataPoint / dataSeries. In your jsfiddle you are using v1.4.1 which does not support this feature. Please download the latest version. Here is the working code .
var chart = new CanvasJS.Chart("container",
{
data: [
{
toolTipContent: null,
type: "column",
dataPoints:[
{ x: 10, y: 20}
]
}
]
});
chart.render();

Categories

Resources