jQuery Flot Charts: Auto bar width with dynamic items - javascript

My charts output dynamic data based on input filters. These can have 1 to 30 bars and they resize on screen resize/device. Just an example, currently where there's < 5 bars and the charts width is 1138px (max), then I have pretty big bars in width.
Q. How is this problem dealth with?
var options = {
xaxis: { ticks: ticks},
grid: { clickable: false, hoverable: true },
series: { stack: true, bars: {show: true,align: 'center',barWidth: 0.5,lineWidth: 2,fillColor: {colors: [{opacity: 0.9}, {opacity: 0.9}]}} },
legend: {container: ".widget-legend"}
};

Assuming you want to give your bars the same pixel width whether there are 1 or 30 bars, you can calculate the value for barWidth from the width of the chart (in x axis units and pixels, correcting for axes and margins) using cross-multiplication. A reasonable pixel width for up to 30 bars on 1100 pixels would be around 20 pixels per bar.
var chartWidthInPixels = 1100 * 0.95; // or $('#chart').width() * 0.95
var barWidthInPixels = 20; // or chartWidthInPixels / 50
var chartWidthInAxisUnits = (max(ticks) - min(ticks)) + 1; // this will be 1 for one bar
var barWidthInAxisUnits = barWidthInPixels * (chartWidthInAxisUnits / chartWidthInPixels);
For one bar with the above example values this gives around 0.019 for the barWidth. By variation of the constants in the formulas you can modify the calculation.

Related

How to create a fixed number of y axes for a chartsjs linear graph?

I would like the graph to adjust itself according to 5 y axes for a chartsjs linear graph. As of now chartsjs adjusts the number of y axes after the data. I would like it to always be 5 and have the data adjust itself accordingly.
If we want to limit the minimum and maximum value for the y-axis then we can add the scales property to the options and set the yAxes property.
In the following example we are setting the minimum value for the y-axis to -10 and maximum value to 80 and we are also defining the stepSize of 10.
var options = {
scales: {
yAxes: [{
ticks: {
max: 80,
min: -10,
stepSize: 10
}
}]
},
};

drawing multi colored custom symbols in highcharts

I need to draw custom markers on a highchart at particular intervals.
I have managed to create a custom bar using the following javascript:
Highcharts.Renderer.prototype.symbols.hline =
function(x, y, width, height) {
return ['M',x-30 ,y + height / 2,'L',x+width+30,y + width / 2];
};
https://jsfiddle.net/jimmain/9gqca584/5/
My problem is that I need to also draw a single pixel border around the pink box.
I am using a stacked bar chart for the chart.
Ideally I would also like to increase the padding underneath the bar (between the bar and the x-axis) but I am not sure it can be independently increased.
It's not clear to me how I can use the renderer to change color. I could just draw one black box, and then another smaller inset pink box on top, but I am not clear on how to change colors in the SVG renderer.
SVG's path can not have border, so solution is to use renderer.rect(): https://jsfiddle.net/BlackLabel/9gqca584/43/
Note: It's bar series, so chart is inverted, that means we need to swap x with y and height with width.
Snippet:
function addRect(chart) {
return chart.renderer.rect(
chart.yAxis[0].toPixels(5) - 4, // 4 = half width
chart.xAxis[0].toPixels(0),
8,
5
).attr({
fill: 'rgba(253,0,154,0.9)',
stroke: 'black',
'stroke-width': 2,
zIndex: 5
}).add();
}
function positionRect(chart, rect) {
rect.animate({
x: chart.yAxis[0].toPixels(5) - 4, // 4 = half width
y: chart.xAxis[0].toPixels(0) - chart.series[0].points[0].pointWidth / 2,
height: chart.series[0].points[0].pointWidth
});
}
$(function() {
$('#container').highcharts({
legend: {
enabled: false
},
chart: {
type: 'bar',
events: {
load: function() {
this.customRect = addRect(this);
positionRect(this, this.customRect);
},
redraw: function() {
positionRect(this, this.customRect)
}
}
},
...
});
});

Making the labels responsive in chart js

I'm having a hard time making the labels in the y-axis responsive.I want the labels to move to multiple lines and have responsive font sizes when the space is not enough.I'm using the chart.js datalabels library for labelling on top of horizontalBar Graph.Also the labels are getting hidden due to the outer chart container.
var chart = new Chart('ctx', {
type: 'horizontalBar',
data: {
labels: ["Something something something", "blah blah..", "blah blah..","Something something something"],
datasets: [{
data: [6, 87, 56,25,100,65],
backgroundColor: "#4082c4"
}]
},
options:{
responsive: true,
maintainAspectRatio: false,
plugins: {
datalabels: {
color: 'black',
anchor: "end",
align: "right",
offset: 20,
display: function (context) {
return context.dataset.data[context.dataIndex];
},
font: {
weight: 'bold',
size: 26
},
formatter: Math.round
}
},
legend: {
"display": false
},
tooltips: {
"enabled": false
},
scales: {
yAxes: [{
barPercentage: 1.0,
gridLines: {
display: false
},
ticks: {
fontSize: 20,
beginAtZero: true,
}
}],
xAxes: [{
gridLines: {
display: false
},
ticks: {
min: 0,
max: 100,
stepSize: 20
}
}]
}
}
})
The numbers in the right side of the bar also gets clipped of.I want the chart to be at the center horizontally.In the browser the chart looks like this-
Link to the fiddle:-https://jsfiddle.net/24wdpfxL/
You can do this, but it's a bit hack-y.
First the data labels. In the datalabels config section, you can try something like:
/* Adjust data label font size according to chart size */
font: function(context) {
var width = context.chart.width;
var size = Math.round(width / 32);
return {
weight: 'bold',
size: size
};
}
Change the size calculation as necessary.
For the y-axis labels, there's an answer here, however apparently since Chart.js 2.7.0, the line:
c.scales['y-axis-0'].options.ticks.fontSize
..should be changed to:
c.scales['y-axis-0'].options.ticks.minor.fontSize
(ref)
So to scale the y-axis labels font size according to chart height, it might look like:
plugins: [{
/* Adjust axis labelling font size according to chart size */
beforeDraw: function(c) {
var chartHeight = c.chart.height;
var size = chartHeight * 5 / 100;
c.scales['y-axis-0'].options.ticks.minor.fontSize = size;
}
}]
Note: This requires "maintainAspectRatio:" to be set to "true".
There's still one problem however, and that's that the part of the chart containing the y-axis labels will remain at the same pixel width even when resized.
We need to also resize this area to keep it at a constant % of the overall chart width, e.g. 40%, instead of a fixed pixel width (added to yAxes config section):
/* Keep y-axis width proportional to overall chart width */
afterFit: function(scale) {
var chartWidth = scale.chart.width;
var new_width=chartWidth*0.4;
scale.width = new_width;
}
(You might not notice this as a problem with your original example, since there is a oversized line that seems to cause the y-axis width to keep expanding when the window is enlarged. But when the labels don't overflow, then the width stays constant unless the above is used.)
Complete jsFiddle: https://jsfiddle.net/0kxt25v3/2/
(fullscreen)
I'm not sure about wrapping labels on to the next line, you might just need to pre-process the labels to limit the maximum number of characters per label.
I also haven't attempted to scale the x-axis label font sizes, but it should be easy enough to add it in to the "beforeDraw:" section.
If you're using chartjs-plugin-datalabels; here's how i was able to make the labels responsive. Considering the chart may have variable width and height, we can get the average of both (height and width) and calculate the font size. I am also setting the max font size limit to 12.
datalabels: {
font: function (context) {
var avgSize = Math.round((context.chart.height + context.chart.width) / 2);
var size = Math.round(avgSize / 32);
size = size > 12 ? 12 : size; // setting max limit to 12
return {
size: size,
weight: 'bold'
};
},
}
I ran into the clipping problem myself recently and fixed this by setting a suggestedMax value that was wider than the largest value in my dataset.

Plotly.js adds top-margin to graphs inconsistently, how to prevent it

With Plotly.js I'm getting a top-margin added sometimes (not consistently), where the total height of the graph is 300px, but the graph itself is only 150px high. The SVG container then is stretched and the actual graph is smaller. What can I do to prevent this white-space, and why does it only show up selectively?
Plotly Matlab syntax that results in 300px div instead of a 300px graph:
`% PLOT MEAN MOVEMENT
data = {...
struct(...
'x', nScan, ...
'y',fastmotion, ...
'type', 'scatter')...
};
if max(fastmotion) < 0.3
yminval = 0.3;
else
yminval = round(max(fastmotion) + 1);
end
layout = struct(...
'yaxis', struct(...
'title', 'Movement (mm)', ...
'range', [0, yminval]));
header{3} = 'Absolute Movement';
layout.width = 800;
layout.height = 300;
p = plotlyfig;
p.data = data;
p.layout = layout;
p.PlotOptions.FileName = 'plot_5';
html_file = plotlyoffline(p);
html_file;`
You can check this answer on a different question, and here is the fiddle.
The quick code you can use:
var layout = {
margin: {
l: 20,
r: 20,
b: 20,
t: 20,
pad: 5
}, title: false
};
As mfedoten says on his answer: But be careful if you have tick labels, if you set margins to zero the labels will be cropped
So apparently line 68 in plotlyfig.m caused the issue:
obj.PlotlyDefaults.MinTitleMargin = 80;
Even though I had no title, it sometimes added 80 px on top of the graph, maxing out at the specified graph height. Setting this value to 0 solves the problem.
Probably line 68 in plotlyfig.m just set default margins.
You can set the margins manually like that:
p.layout.margin = struct('b', 15,'l', 30, 'r', 0, 't', 0);
You can find documentation on margins here.
But be careful if you have tick labels, if you set margins to zero the labels will be cropped.

keep fixed size of the bars in Highcharts

I want to maintain the same size of the bars. no matter how many there are values.
here is the size I want to have all bars.
when added four values the bars become smaller.
I want all the bars are the same size. no matter that I have to scroll to see the other bars (this is what I want).
this is my code:
http://jsfiddle.net/Laxfsbtb/
$('#container').highcharts({
chart: {
type: 'bar'
},
series: [{
name: 'text1',
data: [1000, 950,920,880,850,234],
color: "#FF0000"
}, {
name: 'text2',
data: [800,770,750,740,730,4324],
color: "#000000"
}, {
name: 'text3',
data: [600,540,535,500,400,324],
color: "#00FF00"
}]
});
});
This can be done with the pointWidth parameter like:
plotOptions: {
series: {
pointWidth: 20 //width of the bar/column/point.
}
},
To allow scrollbar you should probably upgrade to highstock but that only works horizontally. Or you could set up a div that allows the chart to be "larger" on the inside and scroll through that div window.
Not sure precisely what you're looking for, but this might help.
I put together an example a while ago to adjust the height of the chart according to the number of bars, using some preset parameters:
var barCount = chartData.length;
var pointWidth = 20;
var marginTop = 60;
var marginRight = 10;
var marginBottom = 50;
var marginLeft = 100;
var pointPadding = 0.3;
var chartHeight = marginTop
+ marginBottom
+ ((pointWidth * barCount) * (1 + groupPadding + pointPadding));
So, tell it what size you want the bars, how much padding between them, how much margin at top and bottom of chart, and how many data points you have.
Bars will stay the same size and spacing while the chart itself grows to accommodate them.
example:
http://jsfiddle.net/jlbriggs/kpu5d1qf/
To see it work, change the 12 in this line:
var chartData = randomData(12, true);
To whatever number you want.
((Edit
Since you are working with grouped data, you'll have to change the math a little bit.you'll need to account for the number of groups, and multiply hat by the groupPadding, added to the number of points * the pointPadding.
You'll also have to make getting your count of data points slightly more complex.

Categories

Resources