How to dynamically arrange random number of subplots inside layout in PlotlyJS - javascript

I want Plotly to arrange the pie charts based on the width and height of the layout and the numbers of subplots.
I would like to find out if PlotlyJS is capable of dynamically arranging a random number of subplots.
The only way of resolving this was to manually set the domain, between [0,1] on x and y axis, for each subplot:
var data = [{
values: allValues[0],
labels: allLabels,
type: 'pie',
name: 'Starry Night',
marker: {
colors: ultimateColors[0]
},
domain: {
//x: [0, .48],NOT FIX: DYNAMICALLY
//y: [0, .49]
},
hoverinfo: 'label+percent+name',
xanchor: 'center',
/*xref: 'paper',*/
textinfo: 'none'
},{
values: allValues[1],
labels: allLabels,
type: 'pie',
name: 'Sunflowers',
marker: {
colors: ultimateColors[1]
},
domain: {
//x: [0.52, 1],NOT FIX: DYNAMICALLY
//y: [0, .49]
},
hoverinfo: 'label+percent+name',
xanchor: 'center',
/*xref: 'paper',*/
textinfo: 'none'
},{
values: allValues[2],
labels: allLabels,
type: 'pie',
name: 'Irises',
marker: {
colors: ultimateColors[2]
},
/*xref: 'paper',*/
domain: {
//x: [0, .48],NOT FIX: DYNAMICALLY
//y: [.51, 1]
},
hoverinfo: 'label+percent+name',
xanchor: 'center',
textinfo: 'none'
},{
values: allValues[3],
labels: allLabels,
type: 'pie',
name: 'The Night Cafe',
marker: {
colors: ultimateColors[3]
},
/*xref: 'paper',*/
domain: {
//x: [0.52, 1],NOT FIX: dynamically
//y: [0.52, 1]
},
hoverinfo: 'label+percent+name',
xanchor: 'center',
textinfo: 'none'
}];
https://jsfiddle.net/908z4qht/2/

Related

How to show area chart with timeseries configuration with different datasets in Chart.js v3?

I've been trying to implement area chart which has different datasets and we are following the configuration of timeseries chart by providing the options a min & max value to generate labels automatically. Here is my code :
var feronisData = [398, 445];
var formattedDates = ["Feb 01", "Mar 20"];
var colors = ['#5ba2df', '#e2ac00', '#59b110'];
var data = {
/* labels: formattedDates, */
datasets: [{
type: 'line',
fill: 1,
spanGaps: true,
pointStyle: 'circle',
label: 'Feronis',
data: [{x: moment('2021-02-10 00:00:00.000').format('MMM DD'), y: 250}, {x: moment('2021-02-28 00:00:00.000').format('MMM DD'), y: 350}],
borderColor: '#5ba2df',
labels: [],
borderWidth: 3,
backgroundColor: 'rgba(0, 0, 0,0)',
}, {
type: 'line',
fill: true,
borderColor: '#2187f3',
backgroundColor: '#219634',
borderWidth: 1,
spanGaps: false,
pointStyle: 'circle',
label: 'Others',
data: [{x: moment('2021-01-24 00:00:00.000').format('MMM DD'), y: 150},{x: moment('2021-02-04 00:00:00.000').format('MMM DD'), y: 300}, {x: moment('2021-03-24 00:00:00.000').format('MMM DD'), y: 450}],
borderColor: '#e2ac00',
labels:[],
borderWidth: 3,
backgroundColor: 'rgba(0, 0, 0,0)',
}]
};
var options = {
showLines: true,
layout: {
padding: {
left: 0,
right: 0,
top: 0,
bottom: 80
}
},
elements: {
point: {
radius: 1,
hoverRadius: 5,
}
},
hover: {
mode: 'index',
intersect: false
},
responsive: true,
tooltips: {
enabled: true,
mode: 'index',
intersect: false,
yAlign: 'right',
},
scales: {
x : {
type: 'time',
min: 'Jan 01',
max: 'Jul 01',
time: {
unit: 'day',
displayFormats: {
day: 'MMM DD'
}
}
/* xAxes: [{
type: 'time',
time: {
unit: 'day',
unitStepSize: 10,
format: 'MMM DD',
displayFormats: {
'day': 'dddd',
'week': 'MMM DD',
'month': 'MMM DD'
},
min: 'JAN 01',
max: 'JUL 01'
},
display: true,
interval: 5,
intervalType: "month",
gridLines: {
drawOnChartArea: false,
}
}], */
},
y: {
stacked: true,
}
}}
this.chart = new Chart('canvas', {
responsive: true,
data: data,
options: options
});
The same is available on fiddle here : https://jsfiddle.net/erdfs37h/
Configuaration is Backend is not going to provide me any set of labels as labels array shown in each dataset. Instead we are depending directly on the data array which provides values in this format [{x: 'xItem', y: 'someValueToPlot'}]
Note : actually I'm going to render this with React.js where my common component generates chart based on these configuration, but it is almost similar to what I've shown on fiddle link.
Since we are also using the timeseries configuration, can you point out any specific thing that I'm missing here?
Currently, I think the solution can be achieved by adding these key-fields for each dataset
type: 'line',
fill: {
target: 'origin',
above: 'rgb(123, 43, 54)', // Area will be reddish above the origin
below: 'rgb(65, 47, 231)' // And blue below the origin
},
Your issue is that you provided duplicate keys for the backgroundColor and in your duplicate you set it to a fully transparent color so thats why its not showing also the labels array in your dataset config is redundent since you are using object notation
Example:
var feronisData = [398, 445];
var formattedDates = ["Feb 01", "Mar 20"];
var colors = ['#5ba2df', '#e2ac00', '#59b110'];
var data = {
/* labels: formattedDates, */
datasets: [{
type: 'line',
fill: 1,
spanGaps: true,
pointStyle: 'circle',
label: 'Feronis',
data: [{
x: moment('2021-02-10 00:00:00.000').format('MMM DD'),
y: 250
}, {
x: moment('2021-02-28 00:00:00.000').format('MMM DD'),
y: 350
}],
borderColor: '#5ba2df',
borderWidth: 3,
}, {
type: 'line',
fill: true,
borderColor: '#2187f3',
backgroundColor: '#219634',
borderWidth: 1,
spanGaps: false,
pointStyle: 'circle',
label: 'Others',
data: [{
x: moment('2021-01-24 00:00:00.000').format('MMM DD'),
y: 150
}, {
x: moment('2021-02-04 00:00:00.000').format('MMM DD'),
y: 300
}, {
x: moment('2021-03-24 00:00:00.000').format('MMM DD'),
y: 450
}],
}]
};
var options = {
showLines: true,
layout: {
padding: {
left: 0,
right: 0,
top: 0,
bottom: 80
}
},
elements: {
point: {
radius: 1,
hoverRadius: 5,
}
},
hover: {
mode: 'index',
intersect: false
},
responsive: true,
plugins: {
tooltip: {
enabled: true,
mode: 'index',
intersect: false,
yAlign: 'right',
},
},
scales: {
x: {
type: 'time',
min: 'Jan 01',
max: 'Jul 01',
time: {
unit: 'day',
displayFormats: {
day: 'MMM DD'
}
}
},
y: {
stacked: true,
}
}
}
this.chart = new Chart('canvas', {
responsive: true,
data: data,
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.1/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#2.27.0"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-adapter-moment/1.0.0/chartjs-adapter-moment.min.js"></script>
<canvas style="height: 400px;" id='canvas' />
You might also want to check the migration guide out since as I can see fast your tooltip is also wrongly configured:https://www.chartjs.org/docs/master/getting-started/v3-migration.html

chartJS Horizontal Bar - Hide Stacked Bars But Still Show In Tooltip

I'm using a chartJS Horizontal Bar to visualize some data & the annotation plugin to add vertical lines in the plot area.
What I want to accomplish: showing annotation values/color-box in the tooltip.
What I've done thus far: I've added in bar charts to get the values in the tooltip. (see images & code below).
Where I'm stuck: I would like to hide/offset aBar 1 & aBar 2; in other words, I don't want these bars to appear at all, but I do want the entries to appear in the tooltip. (please see second image).
Current Output
Desired Output
Code
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: false, // RANGE
datasets: [
{
type: 'horizontalBar',
label: 'Bar 1',
backgroundColor: 'rgba(121,185,29,0.85)',
stack: 'Stack 0',
data: [
16 ],
borderColor: 'white',
borderWidth: 0.5
},
{
type: 'horizontalBar',
label: 'Bar 2',
backgroundColor: 'rgba(246,171,0,0.3125)',
stack: 'Stack 0',
data: [
24 ]
},
{
type: 'horizontalBar',
label: 'Bar 3',
backgroundColor: 'rgba(226,33,27,0.5)',
stack: 'Stack 0',
data: [
80 ]
},
{
type: 'horizontalBar',
label: 'aBar 1',
backgroundColor: '#20C5CB',
stack: 'Stack 1',
data: [
6 ]
},
{
type: 'horizontalBar',
label: 'aBar 2',
backgroundColor: '#7f3391',
stack: 'Stack 2',
data: [
120 ]
},
]
},
options: {
responsive: true,
legend:false,
responsive: true,
maintainAspectRatio: false,
title: false,
tooltips: {
mode: 'index',
intersect: true,
bodyFontSize:10,
titleFontSize:0,
titleMarginBottom:0,
},
plugins: {
labels:false,
},
scales: {
xAxes: [{
ticks: {
max: 124,
min: 0,
stepSize: 10
}
}]
},
annotation: {
annotations: [
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 6,
borderColor: '#20C5CB',
borderWidth: 3,
borderDash: [6,3],
label: {
enabled: false,
content: 'Annotation 2',
fontSize: 8,
fontStyle: 'normal',
rotation: 0,
xPadding: 2,
yPadding: 2,
cornerRadius: 1,
}
},
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 120,
borderColor: '#7f3391',
borderWidth: 3,
label: {
enabled: false,
content: 'Annotation 1',
fontSize: 8,
fontStyle: 'normal',
rotation: 0,
xPadding: 2,
yPadding: 2,
cornerRadius: 1,
}
}
]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.min.js"></script>
<canvas id="myChart"></canvas>
Add the hidden tag to datasets of the series you want to hide like this:
type: 'horizontalBar',
label: 'aBar 1',
backgroundColor: '#20C5CB',
stack: 'Stack 1',
hidden: true,
data: [6],
and use a callback to the label tooltip like this:
tooltips: {
mode: 'index',
intersect: true,
bodyFontSize:10,
titleFontSize:0,
titleMarginBottom:0,
callbacks: {
label: function(tooltipItem, data) {
return data.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index])
}
}
},
Found solution here: Chartjs show hidden data on tooltip

Drilldown operation in Column-Stacked Bar diagram HighCharts

I have a bar diagram something similar to this
https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/demo/column-stacked/
And I need to display a drill-down in such a way that a single column is split into multiple bars in the next page.
For example:
If I click Apples column in the bar, it should drill down into the next page with 3 columns
First Column - x-Axis: Joe, y-Axis: 3
Second Column - x-Axis: Jane, y-Axis: 2
Third Column - x-Axis: John, y-Axis: 5
Similar operations for the rest of the columns in the main bar diagram.
Finally, I should be able to navigate back to the main page as well.
Any help from anyone would be much appreciated. Thanks in advance.
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: ( // theme
Highcharts.defaultOptions.title.style &&
Highcharts.defaultOptions.title.style.color
) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor:
Highcharts.defaultOptions.legend.backgroundColor || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true
}
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<figure class="highcharts-figure">
<div id="container"></div>
<p class="highcharts-description">
Chart showing stacked columns for comparing quantities. Stacked charts
are often used to visualize data that accumulates to a sum. This chart
is showing data labels for each individual section of the stack.
</p>
</figure>
Your requirement is possible to achieve by config data in the proper way and adding drilldown module.
Demo: https://jsfiddle.net/BlackLabel/xz46uspb/
Series data example:
series: [{
name: 'John',
data: [{
y: 5,
name: 'Apples',
drilldown: "Apples"
}, {
y: 3,
name: 'Oranges',
drilldown: "Oranges"
}, {
y: 4,
name: 'Pears',
drilldown: "Pears"
}]
}, ...
],
And drilldown data:
drilldown: {
series: [{
name: 'Apples',
id: 'Apples',
colorByPoint: true,
data: [{
name: 'John',
y: 5
}, {
name: 'Jane',
y: 2
}, {
name: 'Joe',
y: 3
}]
}]
}
API: https://api.highcharts.com/highcharts/xAxis.type
API: https://api.highcharts.com/highcharts/series.column.colorByPoint
API: https://api.highcharts.com/highcharts/drilldown

Distance between x-axis labels and the chart in Highcharts

I'm trying to create a distance between the x-axis labels and the chart in Highcharts. I tried using "distance" and "padding" but none worked.
chart: {
type: 'column'
},
title: {
text: 'Data input as column arrays'
},
data: {
columns: [
[null, 'Apples', 'Pears', 'Oranges'], // categories
['Blue', 1, 4, 3], // first series
['Black', 5, 4, 2] // second series
]
},
xAxis: {
categories: [
'First Category',
'Second Category',
'Third Category',
],
labels: {
style: {
fontFamily: 'openSans',
fontSize: '16px',
color: '#000000',
},
}
}
Here is jsfiddle: http://jsfiddle.net/aaq4zww5/2/
Thanks!
Option1: use the offset in the xAxis:
xAxis: {
...
offset: 10,
},
Option2: use y under xAxis->labels:
labels: {
...
y: 25,
},
Check jsfiddle.

HighCharts - show xaxis titles

I am working with highcharts, but first let me explain.
The graph needs these items / options
- each bar should have its own width (done)
- each bar should have its own color (done)
- a line with the avarage level (done)
However, there is one thing I can't get working: On the xaxis is need the names of the bars (like here: http://www.highcharts.com/demo/column-rotated-labels).
I've tried different methods, and if I use method 1 I can't set custom bar widths, if I use method 2 I can't set the titles on the x-axis. Anybody an idea?
My code so far:
$(function () {
// Create the chart
$('#container').highcharts({
chart: {
type: 'column',
},
credits: {
enabled: false,
},
title: {
text: ''
},
xAxis: {
type: 'category',
title: {
text: 'Kerntaken',
},
labels: {
enabled: true,
},
categories: ['Apples', 'Bananas', 'Oranges']
},
yAxis: [{
title: {
text: 'Gemiddeld niveau',
},
allowDecimals: false,
plotLines: [{
color: 'black',
value: '2', // Insert your average here
width: '1',
zIndex: 5, // To not get stuck below the regular plot lines
label: {
text: 'gemiddeld niveau',
align: 'right',
y: 12,
x: 0
}
}],
},{
title: {
text: ''
},
allowDecimals: false,
},{
title: {
text: ''
},
allowDecimals: false,
},{
title: {
text: '',
},
opposite: true,
}],
legend: {
enabled: false
},
tooltip: {
pointFormat: '<b>{point.y:.2f}</b><br/>',
},
series: [{
name: "Kerntaken",
colorByPoint: true,
colors: ['#c8173c', '#f2d38d', '#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 20,
data: [{
name: "Adviseren",
y: 3.2,
drilldown: "Adviseren",
}],
}, {
name: "Kerntaken",
colorByPoint: true,
colors: ['#f2d38d', '#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 50,
data: [{
name: "Analyseren",
y: 1.5,
drilldown: "Analyseren",
}]
}, {
name: "Kerntaken",
colorByPoint: true,
colors: ['#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 30,
data: [{
name: "Organiseren",
y: 3.9,
drilldown: "Organiseren",
}]
}, {
name: 'CP niveau',
type: 'spline',
data: [2],
tooltip: {
headerFormat: 'gemiddeld niveau<br>',
},
}],
});
My fiddle with my code so far: https://jsfiddle.net/Mik3yZ/L181kpqt/2/
Hi, can you check if it's this that you want?
I changed your series data to this:
{
name: "Apples",
colorByPoint: true,
colors: ['#c8173c', '#f2d38d', '#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 20,
data: [3.2, 0, 0],
}, {
name: "Bananas",
colorByPoint: true,
colors: ['#f2d38d', '#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 50,
data: [0, 1.5, 0]
}, {
name: "Oranges",
colorByPoint: true,
colors: ['#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 30,
data: [0, 0, 3.9]
}
You were giving the data an object, but it's expecting an array. I set 0's in the values to balance the sets in the other columns.
In the first object data attribute, the first value is for the apples in the first column. If you change the second value you will get apples in the second column and so forth. In this fiddle you have apples in all the columns.
Here is the updated fiddle for your answer.
You don't have to fill data with nulls, neither with zeros, but you can simply provide x index in the point. I'm not sure if that is really suitable for your use-case with drilldown (and categorized axis), but may be enough:
Example for data:
series: [{
name: "Kerntaken",
colorByPoint: true,
colors: ['#c8173c', '#f2d38d', '#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 20,
data: [{
x: 0, // added x-position
name: "Adviseren",
y: 3.2,
drilldown: "Adviseren",
}],
}, {
name: "Kerntaken",
colorByPoint: true,
colors: ['#f2d38d', '#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 50,
data: [{
x: 1, // added x-position
name: "Analyseren",
y: 1.5,
drilldown: "Analyseren",
}]
}, {
name: "Kerntaken",
colorByPoint: true,
colors: ['#e2584d', '#6f2236', '#4e787a', '#867e97', '#000000'],
pointWidth: 30,
data: [{
x: 2, // added x-position
name: "Organiseren",
y: 3.9,
drilldown: "Organiseren",
}]
}, {
name: 'CP niveau',
type: 'spline',
data: [2],
tooltip: {
headerFormat: 'gemiddeld niveau<br>',
},
}],
Now, as I said before, disable grouping from columns:
plotOptions: {
column: {
grouping: false
}
}
And working demo: http://jsfiddle.net/xkjqtcq3/3/
Extra note:
You have a lot of extra commas in your code, just be aware it will cause errors in IE < 9.
You need to change the series data format like this. Since you are using multiple series, you should have the mapping category values(here null) for each series to show the correcsponding x-axis Labels.
series: [{
name: "Kerntaken",
pointWidth: 20,
data: [3.2,null,null]
}, {
name: "Kerntaken",
pointWidth: 50,
data: [null,1.5,null]
}, {
name: "Kerntaken",
pointWidth: 30,
data: [null,null,3.9]
}]
Here is the updated Fiddle, Hope this helps.

Categories

Resources