C3 Bar Graph x-axis labels are too congested - javascript
I have created a Bar graph using C3 JS plugin, The graph is working fine but the problem is with the x-axis labels looks too congested like as shown below
Working JSFiddle
My Code is as given below
var chart = c3.generate({
bindto: "#chart",
data: {
x : 'x',
columns: [
['x', "2016-04-01","2016-04-08","2016-04-15","2016-04-22","2016-04-29","2016-05-06","2016-05-13","2016-05-20","2016-05-27","2016-06-03","2016-06-10","2016-06-17","2016-06-24","2016-07-09","2016-07-10","2016-07-11","2016-07-12","2016-07-13","2016-07-15","2016-07-16","2016-07-17","2016-07-18","2016-07-19","2016-07-20","2016-07-21","2016-07-22","2016-07-23","2016-07-24","2016-07-25","2016-07-26","2016-07-27","2016-07-28","2016-07-29","2016-07-30","2016-07-31","2016-08-01","2016-08-02","2016-08-03","2016-08-04","2016-08-05","2016-08-06","2016-08-07","2016-08-08","2016-08-09","2016-08-10","2016-08-11","2016-08-12","2016-08-13","2016-08-14","2016-08-15","2016-08-16","2016-08-17","2016-08-18","2016-08-19","2016-08-20","2016-08-21","2016-08-22","2016-08-23","2016-08-24","2016-08-25","2016-08-26","2016-08-27","2016-08-28","2016-08-29","2016-08-30","2016-08-31","2016-09-01","2016-09-02","2016-09-03","2016-09-04","2016-09-05","2016-09-06","2016-09-07","2016-09-08","2016-09-09","2016-09-10","2016-09-11","2016-09-12","2016-09-13","2016-09-14","2016-09-15","2016-09-16","2016-09-17","2016-09-18","2016-09-19","2016-09-20","2016-09-21","2016-09-22","2016-09-23","2016-09-24","2016-09-25","2016-09-26","2016-09-27","2016-09-28","2016-09-29","2016-09-30","2016-10-01","2016-10-02","2016-10-03","2016-10-04","2016-10-05","2016-10-06","2016-10-07","2016-10-08","2016-10-09","2016-10-10","2016-10-11","2016-10-12","2016-10-13","2016-10-14","2016-10-15","2016-10-16","2016-10-17","2016-10-18","2016-10-19","2016-10-20","2016-10-21","2016-10-22","2016-10-23","2016-10-24","2016-10-25","2016-10-26","2016-10-27","2016-10-28","2016-10-29","2016-10-30","2016-10-31","2016-11-01","2016-11-02","2016-11-03","2016-11-04","2016-11-09"],
['pv1', 2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2500,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2696,2748,2748,2694,2694,2694,2694,2694,2694,2694,2668,2668,2668,2668,2576,2572,2572,3043,3084,3084,3084,3084,3084,3156,3521,3521,3550,3542,3542,3573,3580,3629,3579,3584,3542,2757,2791,2696,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3415,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3414,3369,3376,3371,3373,3371,3379,3363,3373,3347,3348,3382,3402,3410,3434,2579,2579,2369],
['pv2', 1750,1750,1750,1750,1825,1850,1975,2150,2375,2425,2475,2500,2500,2087,2087,2087,2087,2091,2087,1767,1767,1767,1633,1498,1498,1642,1637,1633,1609,1841,1713,1702,1862,1888,1888,1888,1949,1976,1977,2014,2014,2014,1946,1966,1973,2224,2252,2318,2318,2318,2327,2373,2513,2535,2543,2534,2539,2823,2849,2990,3142,3142,3108,2513,2687,2678,2856,2860,2861,2862,2866,2869,2870,2875,2874,2874,2874,2879,2885,2886,2883,2889,2896,2895,2899,2903,2909,2911,2913,2913,2913,2916,2922,2933,2937,2943,2942,2943,2947,1811,1826,1837,1840,1840,1841,1843,1511,1854,1853,1851,1852,1853,1849,1852,1874,1857,1883,1886,1888,1904,1903,1924,1947,2060,2068,2068,2082,1582,1344,836,839,788]
],
type: 'bar'
},
axis: {
x: {
type: 'category',
tick: {
rotate: -60,
multiline: false
},
height: 130
}
}
});
Can anyone please tell me some solution for this
What I did to solve it
I have used timeseries type instead of category type, after that the label issue got resolved but the graph was been plottted with more white spaces for the month of march like as shown below
Working JSFiddle
You can use c3's tick count setting for this, so here we say 20 labels.
However there is an added gotcha in that ticks that now resolve to a fractional category value won't show - i.e. the 2nd equally spaced tick out of 20 may be the 2.6667th element in the x category axis - so you need to have a little format function that adjusts for this, otherwise you just get the end and start labels. (Or you could figure out a tick count that divides into your data count + 1 as a whole number.)
tick: {
format: function (x) {
var cats = this.api.categories();
return cats[Math.round(x)];
},
count: 20,
rotate: -60,
multiline: false
},
http://jsfiddle.net/fz0t10yb/7/
One of the possible solution could be to use x-axis labels at required indexes only & leaving others blank.
['x', "2016-04-01","","","","2016-04-29","","","",...]
['pv1', 2500,2500,2500,2500,2500,2500,2500,2500,...]
['pv2', 1750,1750,1750,1750,1825,1850,1975,2150,...]
You can position labels so that it would capture the date and at same time it looks good also.
Related
apexcharts different options for axis range
Let's take a look at the simple chart data: it has (x,y) pairs: x y 0 -3 1 2 2 7 3 8 4 15 5 0 The idea is to create a basic line chart, using VueJS in my case, but the idea can be generalized to JavaScript. I have a series array of objects, where each object has x and y coordinates: series = [ { x: 0, y: -3 }, { x: 1, y: 2 }, ... ] This series is part of options object: const options = { chart: { type: 'line' }, series: series } const chart = new ApexCharts(document.querySelector("#chart"), options); chart.render(); And the chart is rendered. Now, let's say I want to append the data to that chart - add 2 new (x,y) pairs const newData = [ { x: 6, y: 20 }, { x: 7, y: -10 } ] chart.appendData([{ data: chartData }]) I would also like that newly appendedData has, for example, different color, fill, or something else - so newly added data displays differently than old data. Feel free to point me to documentation if I missed anything, but I searched through apex chart methods, and the only thing that looks remotely close to this would be inside updateOptions() method, the redrawPath flag (updateOptions docs: When the chart is re-rendered, should it draw from the existing paths or completely redraw the chart paths from the beginning. By default, the chart is re-rendered from the existing paths
In order to style the new data differently, you'll want to put these data points into a different series using the appendSeries method: const newData = [ { x: 6, y: 20 }, { x: 7, y: -10 } ] chart.appendSeries({ name: "series-2", // optional data: newData }) Most of the styling in ApexCharts is done based on series (more specifically seriesIndex). So by placing the new data in a separate series you'll be able to style this second series using an array of, for example, colors. You could either specify the color you would like to use as you append the new series of data using the updateOptions method you mention, or you can specify it in advance. chartOptions: { colors: ["#546E7A", "#E91E63"], } When working with "Numeric paired values in XY properties", the xaxis type also has to be explicitly set to numeric: chartOptions: { xaxis: { type: 'numeric', }, } The tricky bit comes when you want to add more data a second time (or third, more time). There are two approaches I can think of here: Shuffle the existing data across to the original series (append series-2 to series-1) - and overwrite series-2 with your new data. You don't need to edit the colors in chartOptions. You could shuffle the colors along. If you want all "old" data to have the same color, simply prepend the colors array with your base color every time you add a new series. Or if you want each series to have a different color, just append a color every time you add a new series.
Highcharts with custom scaling in upper regions
I would like to know how to achieve a custom scale for a chart in Highcharts. I want to display a boxplot which has very high whiskers. The normal values to display are between 500 and 1000 but there are some anomalies which are about 6000 on y-axis. This is causing the whole chart to be squeezed and the scaling is so small that you can't determine the boxplots correctly. I would like to increase the tick-size between 1000 and 6000 to decrease the heigt of the chart.
Highcharts provides breaks functionality that seems to be ideal for your case: https://api.highcharts.com/highcharts/yAxis.breaks Another approach is to change the yAxis type to logarithmic: https://api.highcharts.com/highcharts/yAxis.type EDIT The discussion in the comments section reveals that the OP needs rather custom y axis formatting than breaks functionality. Here's how to approach this issue: The problem here is that axes in Highcharts can only have either constant or logarythmic scales. Your example shows irregular scale - the values are not in constant or logarythmic order ([0, 3, 10, 30, 150]). Here's what I've done to mimic that kind of look and behaviour: I set tickPositions to [0, 1, 2, 3, 4] - these are the actual values that appear on the chart. As you can see the distance between all these numbers is constant: 1. Then I used formatter to display corresponding number from ranges array for each label. yAxis: { tickPositions: [0, 1, 2, 3, 4], labels: { formatter: function() { return ranges[this.pos]; } } }, Before I passed the data to the chart constructor I converted all the values so that they're between 0 and 4: series: [{ data: [2, 120].map(function(val) { var range = findRange(val); var y = range.index + (val - range.low) / (range.high - range.low); return { y: y, originalValue: val }; }) }] Finally I used originalValue property in tooltip.format string to print to the user the number before the conversion. tooltip: { pointFormat: "<span style='color:{point.color}'>\u25CF</span> {series.name}: <b>{point.originalValue}</b><br/>" }, This example is simplified to the line series case but can be easily adjusted to boxplot series. The code serves only for the example purposes and should be improved - it's easy to cause an error within it. Live working demo: https://jsfiddle.net/kkulig/ytjz1jej/ API references: https://api.highcharts.com/highcharts/tooltip.pointFormat https://api.highcharts.com/highcharts/yAxis.tickPositions https://api.highcharts.com/highcharts/xAxis.labels.formatter
How can I create a horizontal stacked bar chart with labels on the bars themselves as well as labels above the bars?
I'm trying to create a horizontal stacked bar chart with labels on the bars themselves (currently using dataLabels) as well as labels just above the bars. Here is a JSFiddle I've created that somewhat resembles what I am trying to accomplish. In this example I've placed the labels using plotLine labels, but I'm having a difficult time figuring out how to place the bars correctly in my real use case as I get the data for the bars through Ajax calls. JSFiddle I've experimented with stackLabels, plotLine labels as well as plotBand labels but to no avail. How can I place labels above the bars correctly every time?
I would use plotBands instead of plotLines - you can better control the alignment within the band, which can be set to cover the same portion of the graph as the bar itself. An example. Using your series data: var series = [{ name: 'John', data: [5] }, { name: 'Jane', data: [2] }, { name: 'Joe', data: [3] }] We can loop through and build a plotBands array from the same data: var bands = [], prevData = 0; $.each(series, function(i,ser) { var point = ser.data[0], name = ser.name; bands.push({ from: prevData, to: (prevData + point), color: 'rgba(255,255,255,0)', label: { text: name, align: 'center' } }); prevData = (prevData+point); }); To make this match the order of the series as plotted, we need to set reversedStacks: false on the yAxis, as by default, Highcharts reverses the order of the series. Then we populate the plotBands with our generated array: yAxis: { reversedStacks: false, plotBands: bands } In this way you can make use of the full feature set of the plotBands label properties. Updated fiddle: http://jsfiddle.net/jlbriggs/xwzfjbhe/4/ And this adjusts to fit however many data points you have, provided you keep the same format (series.name, series.data[0]): http://jsfiddle.net/jlbriggs/xwzfjbhe/5/ There are a number of other ways you can go about this as well, including: The labels property: http://api.highcharts.com/highcharts/labels The renderer function: http://api.highcharts.com/highcharts/Renderer
How to duplicate Y Axis on JQuery Flot
I'm being able to use JQuery Flot, and it's a very nice tool. However, I could not find a GOOD solution for my problem. I want to duplicate Y axis, so I can display 1 on the left and 1 on the right, so the users, when comparing data from the rightmost side of the chart, won't have to scroll through the leftmost side of the chart. I'm assuming they will be accessing it through a smartphone. JQuery Flot allows multiple axis, but for each axis, I would need a different set of data, as in this example: http://people.iola.dk/olau/flot/examples/multiple-axes.html But I don't want to duplicate the data. Can't I just 'tell' Flot to duplicate the yaxis using the same set of data?
You can use the hooks functionality to force flot to show the second yaxis even though it has no data series assigned to it: // hook function to mark axis as "used" // and assign min/max from left axis pOff = function(plot, offset){ plot.getYAxes()[1].used = true; plot.getYAxes()[1].datamin = plot.getYAxes()[0].datamin; plot.getYAxes()[1].datamax = plot.getYAxes()[0].datamax; } $.plot("#placeholder2", [ { data: d2 } ], { hooks: { processOffset: [pOff] }, yaxes: [ {}, {position: 'right'} // add second axis ] }); Depending on how your axis is configured though, this might be messy. You'll have to steal parameters from the left axis to get it to work (as I've done above with datamin/datamax). If it was my code, I'd go with your duplicate data approach. You aren't really duplicating anything, just assigned the same array to two series. I'd then configure the 2nd series to simply not draw. var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]]; // use the same data but toggle off the lines... $.plot("#placeholder", [ { data: d2 }, {data: d2, yaxis: 2, lines: {show: false}} ], { yaxes: [ {}, {position: 'right'} ] }); Here's a fiddle demonstrating the two approaches.
Highcharts blank chart with x and y axis
I want to use highcharts creating a blank chart with no datas but x and y axis. How to do it? var chart = new Highcharts.Chart({ chart: { renderTo: 'container' }, yAxis: { labels: { formatter: function() { return this.value +' km'; } } }, series: [{ data: [] }] }); it returns But I want to display y-axis with label.
You can put in your min/max values for the xAxis and yAxis and use null for all data. Forked from #ZaheerAhmed's response above as I figure it deserves a spot as an alternative solution without needing to hide the data after the fact. i.e. yAxis: { min: 1, max: } , xAxis: { min: 1, max: 50 }, series: { data:[null,null] }
You can put data and hide the series after setting property ignoreHiddenSeries : false Here is Working Demo If you hide the series Y-Axis will still be visible.
FWIW, it seems that highcharts has this functionality built in yAxis.showEmpty Unfortunately, the fiddle listed in the documentation doesn't work, and there is a related open highcharts issue on the matter: no hide y axis
Setting min and max for xAxis and yAxis is not a good solution! Because if the data is loaded later (When it's resolved), then you won't have auto calculated min and max. In Highcharts API, it's said: If null, the max value is automatically calculated So you should set min and max back to null when the data is loaded. But in my case setting it to null or even deleting the option, didn't result in automatic calculating (Seems strange). What I did instead was setting charts.showAxes to true! That's it. Take a look at the demo provided by Highcharts Important: You of course need to set series to something like this: series: [ { data: [null, null, null] }, { data: [null, null, null] } ] Note: Make sure xAxis.showEmpty and yAxis.showEmpty are set true (which is true by default).