How to set Google Chart height based on number of rows? - javascript

I have a Google stacked bar chart that pulls data from a database and draws charts based on said data. I was able to search around and find a way to dynamically set the height based on the number of rows - but for one of my search filters, the charts look way off.
The code is below and works for 4 out of 5 of my filters, but in the 5th filter the number of rows becomes much larger (around 40-50).
Code:
var paddingHeight = 40;
var rowHeight = data.getNumberOfRows() * 50;
var chartHeight = rowHeight + paddingHeight;
var options = {
titlePosition: 'none',
width: 1400,
height: chartHeight,
legend: { position: 'top', maxLines: 3 },
bar: { groupWidth: '50%' },
isStacked: true,
hAxis: {
title: 'Business Hours (excluding weekends & holidays)'
},
colors: ['#0066ff', '#33cc33', '#ffcc00', '#ff0000'],
annotations: {
alwaysOutside: true,
textStyle: {
color: '#000000'
}
}
}
Produces the following results. This first image is what 4 of my 5 filters looks like.
The second image is the one in question that shows I'm clearly doing something wrong.
What is the cause of this and how can I resolve it?
Edit: I suspect my issue is one of the following:
Either my data rows are not being counted correctly as I refresh the page with the latest search parameters or I have a problem with how my divs are set up and interacting with each other. I've tried adjusting the math behind the chartHeight and removing the padding and it seems to have the same effect either way. Am I on the right track or is there something else I'm missing?

need to set options for both height and chartArea.height
here, recommend using rowHeight for chartArea.height
var paddingHeight = 40;
var rowHeight = data.getNumberOfRows() * 50;
var chartHeight = rowHeight + paddingHeight;
var options = {
titlePosition: 'none',
width: 1400,
height: chartHeight,
chartArea: {
height: rowHeight,
},
legend: { position: 'top', maxLines: 3 },
bar: { groupWidth: '50%' },
isStacked: true,
hAxis: {
title: 'Business Hours (excluding weekends & holidays)'
},
colors: ['#0066ff', '#33cc33', '#ffcc00', '#ff0000'],
annotations: {
alwaysOutside: true,
textStyle: {
color: '#000000'
}
}
}
you'll want to leave some room for the legend, y-axis, etc...
chartArea has the following properties
top
left
height
width
you'll want to set top to 20 or something if legend is on top

Related

ApexCharts - How do I move the data label on pie chart?

I am trying to move my data labels inward so that they are easier to read. If there is a way to dynamically center them in the slice, that would be ideal.
I've read the docs and tried modifying the X & Y.. i've tried -50 to 50 and nothing seems to be impacting the position of these labels. Am I missing something?
var PTDLastMonthOptions = {
series: [35, 65],
chart: {
width: 300,
type: 'pie',
},
legend: {
position: 'bottom'
},
dataLabels: {
enabled: true,
offsetX: 50,
offsetY: 50
},
colors: ['#00e396', '#ff4560'],
labels: ['PAID', 'UNPAID']
};
var PTDLastMonthChart = new ApexCharts(document.querySelector("#ptdLastMonthChart"), PTDLastMonthOptions);
PTDLastMonthChart.render();
#Edit 1 - Adding codepen:
https://codepen.io/flashsplat/pen/NWzowbx
#Edit 2 - I am convinced this is a bug and have reported it as such:
https://github.com/apexcharts/apexcharts.js/issues/3537
Thanks!
Change offset in plotOptions not dataLabels https://apexcharts.com/docs/options/plotoptions/pie/#dataLabelsOffset
plotOptions: {
pie: {
dataLabels: {
offset: -10,
},
}
}

How to set the legend area in a two-column fashion in Apache Echarts

I want to set the legend area in a two-column fashion in Apache Echarts, how I can achieve this with legend options? I'm not able to find any example related to this.
Sample image (I want a legend area like the image mentioned below).
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
top: '3%',
},
grid: {
top: '28%',
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: {
type: 'value',
},
yAxis: {
type: 'category',
data: ['Actual Avg', 'Min Standard']
},
series: JSON.parse(data),
};
In "legend" you can define the data by writing something like this
legend:{
...,
data: [
{name: 'series 1', ...},
{name: 'series 2', ...}
]
}
If you want the legend to generate automatically, it will depend on what you have on "series".
"If data is not specified, it will be auto collected from series. For most of series, it will be collected from series.name or the dimension name specified by seriesName of series.encode. For some types of series like pie and funnel, it will be collected from the name field of series.data." - Echarts Documentation
Since i don't know how your "series" is defined, i can't give you a code example, but i think the documentation part will help you.
I found a way to have 2 columns, simply use a vertical legend alignment and fix the height, based on the number of elements you want ot display in a column, for example: (number of element in a column) * (legend element height).
option = {
legend: {
top: '3%',
orient: 'vertical',
align: 'left',
height: '180px' //example
},
};

Apexcharts max width on item bars

How can I change the maximum width/height an item bar has in Apexcharts? (https://apexcharts.com/)
I have an horizontal bar chart whose data are loaded dynamically and the number of users (items) varies. When there are few or only one user the bar looks very huge, I would like to set the height to max 50px.
The code:
var timeChart = {
formatter: function (value) {
var v = formatFromSeconds(value);
return v;
}
};
var desv_time = function (value) {
var v = formatFromSeconds(value);
if (value>0)return "+"+v;
else return v;
}
//CHART
var chart1 = new ApexCharts( document.querySelector("#chart-desv"),
{
chart: {
id: 'chart1',
type: 'bar'
},
plotOptions: {
bar: {
horizontal: true,
},
},
dataLabels: {
enabled: true,
formatter: desv_time,
style: {
colors: ["#000"]
}
},
series: [],
xaxis: {labels: {
formatter: desv_time,
}},
tooltip: {
followCursor: true,
x: {
formatter: function(value) {
return value;
},
},
y: {
formatter: desv_time,
title: {formatter: (seriesName) => 'Time difference',}
},
marker: {show:false}
},
title: { text: "Usual workday duration: 08:00", align: "center" }
});
chart1.render();
Screenshot (very huge bar with one user):
I'm using an approach similar to #Oscar Schafer's
I've found that, for my case, the width could be based on the length of my series.
The premises are:
When we have few items, e.g. 1 or 2, the chart width will be filled with only these columns. Then, if I have few items, the columnWidth should be proportionally smaller (close to 20% in my case)
When we have more items, they all share the chart width and fill it more smoothly. Then, if I have a lot of items, the column should be proportionally larger (close to 80%)
I've used the LOGISTIC-GROWTH MODEL as a function to calculate the bar width
Here is the code for to calculate the column width:
// f(x) = c / (1 + a*exp(-x*b)) -> LOGISTIC GROWTH MODEL
var optimalColumnWidthPercent = 20 + (60 / (1 + 30*Math.exp(-seriesLength /3)));
// 20: minimum width should be close to 20 (when only one item)
// 20+60: maximum width should be close 80
// 30 and 3: the a and b from the function, I've selected after testing some cenarios from seriesLength from 1 to 12 and finding which worked for me
...
plotOptions: {
bar: {
columnWidth: optimalColumnWidthPercent + "%"
},
},
For a horizontal bar chart, you can use the barHeight property to set the height of the bars. Unfortunately it can't be set as a pixel value but instead is "the percentage of the available height in the grid-rect" (from docs).
Effectively it works as a maximum height, so the bars will shrink if there's more data that needs to fit.
plotOptions: {
bar: {
barHeight: '70%'
}
}
Here's how I achieve this behaviour in VueJS.
Template part
<apexchart :options="barChartOptions" :series="series"></apexchart>
Script Part
computed() {
chartOptions() {
return {
chart: {
type: 'bar',
height: 100 + this.myData.length() * barWidth,
}
}
}
}
Where myData is an array of data that contains the information to be plotted and barWidth is the width of each bar that I want.
Note that this essentially fixes the width of each bar and then resizes the height of the chart as a linear function of the number of bars.
For a horizontal bar chart, you can use the columnWidth property to set the widthof the bars. Unfortunately it can't be set as a pixel value but instead is "the percentage of the available widthin the grid-rect" (from docs).
Effectively it works as a maximum width, so the bars will shrink if there's more data that needs to fit.
here,
plotOptions: {
bar: {
horizontal: false,
borderRadius: 10,
columnWidth: '45%',
},
},

Google chart api, same options, different data array make bug

I am using line chart via google chart api, and stuck with a problem.
When i am using arrayToDataTable everything works fine and looks okay.
https://jsfiddle.net/Ljz49gqb/
But when i am filling data object, and populate it with data needed, it's being like cut from the right side.
https://jsfiddle.net/Ljz49gqb/1/
Options in this examples, are the same
var options = {
height: 245,
width: '100%',
chartArea: {top: 15, left: 30, width: '100%', height: 190},
areaOpacity: 0.1,
tooltip: {trigger: 'both'},
legend: 'none',
pointSize: 5,
hAxis: {
format: 'MM-dd',
gridlines: {
color: '#fff',
count: 365 /* \_(ツ)_/ */
},
textStyle: {
fontSize: 11
}
},
vAxis: {
gridlines: {
color: '#dedede',
count: 5
},
viewWindow: {
min: 0
},
textStyle: {
fontSize: 11
},
baselineColor: 'dedede'
}
};
p.s. 100% width must left, because page is dynamic and used in mobile.
UPDATE
Displays bad even so
https://jsfiddle.net/Ljz49gqb/2/
UPDATE
It was not about dataTable, it was about Date type in google chart api, and 100% width. (Just to help find this topic in google)
Solved with
chartWrapWidth = document.getElementById('chart_div').offsetWidth;
options.chartArea.width = chartWrapWidth - 45;
https://jsfiddle.net/Ljz49gqb/4/

Making two series point in opposite directions in highcharts

I have a column chart with two series, one of which I want to go down and the other up, like this:
However both of the series have positive y-values, which I can't change, e.g.
blue = [1746181, 1884428, 2089758, 2222362, 2537431, 2507081, 2443179,
2664537, 3556505, 3680231, 3143062, 2721122, 2229181, 2227768,
2176300, 1329968, 836804, 354784, 90569, 28367, 3878];
grey = [1656154, 1787564, 1981671, 2108575, 2403438, 2366003, 2301402, 2519874,
3360596, 3493473, 3050775, 2759560, 2304444, 2426504, 2568938, 1785638,
1447162, 1005011, 330870, 130632, 21208];
Using highcharts options, is it possible to have a chart like this? The example I used for the screenshot is this jsFiddle if it's useful to anyone, however it has a series with negative values which is not an option for me. Instead my data is more like this fiddle
I would try to use two separate yAxes: http://jsfiddle.net/zares7x9/2/, where one of them is reversed:
yAxis: [{
title: {
text: null
},
top: '5%',
height: '45%',
labels: {
formatter: function () {
return (Math.abs(this.value) / 1000000) + 'M';
}
},
min: 0,
max: 4000000
}, {
title: {
text: null
},
labels: {
formatter: function () {
return (Math.abs(this.value) / 1000000) + 'M';
}
},
offset: 0,
showFirstLabel: false, // hide 0-value
reversed: true, //reverse
top: '50%',
height: '45%',
min: 0,
max: 4000000
}],
Setting top and height allows you to render axes like one. Note, that you need to set for one of the series yAxis: 1, to inform Highcharts which series belongs to which axis.

Categories