Basically i want to use pointPadding with custom bar width (pointWidth) both at the same time. But i can't, here is my problem:
I want a chart with no-padding in the bars of one group when showing grouped chart. For this purpose i used pointPadding: "0" and it shows me exactly right chart. like:
if(chart_json.chart.defaultSeriesType=='column'){
if(chart_json.xAxis.categories.length >= 1 ){
chart_json.plotOptions.column.groupPadding = "0.05";
chart_json.plotOptions.column.pointPadding = "0.00";
}
}
var chart=new Highcharts.Chart(chart_json,startupObj.startupFunction);
chartObjArray.push(chart);
But when i set my custom width it adds some spaces in between bars of one group.
Actually i want to put max and min limit on bar width, but i can't find any support from Highchart library. So for this purpose when highchart generate the chart, if the generated chart bar width exceeds my max-limit i set it to my max-limit and same for lower limit.
if(chart_json.chart.defaultSeriesType=='column'){
if(chart_json.xAxis.categories.length >= 1 ){
chart_json.plotOptions.column.groupPadding = "0.05";
chart_json.plotOptions.column.pointPadding = "0.00";
}
}
var chart=new Highcharts.Chart(chart_json,startupObj.startupFunction);
chartObjArray.push(chart);
//set bar width
if(chart_json.chart.defaultSeriesType=='column' || chart_json.chart.defaultSeriesType=='bar'){
setChartBarMaxMinWidth(chart,chart_json);
}
setChartContainerWidth(chart_json,chart);
////************************************///////////////////
function setChartBarMaxMinWidth(chart,json){
var maximumBarWidth=70;
var minimumBarWidth=15;
chart_json=eval('('+json.chart_json+')');
for(var j=0;j<chart.series.length;j++){
var series=chart.series[j];
if (series.data[0].pointWidth > maximumBarWidth) {
chart.series[j].options.pointWidth = maximumBarWidth;
isMaxMin='MAX';
}
if (series.data[0].pointWidth < minimumBarWidth) {
chart.series[j].options.pointWidth = minimumBarWidth;
isMaxMin='MIN';
}
};
function setChartContainerWidth(chartOptions,chart){
// calculate # of bars
var numberOfBars=seriesGroupLength*categoriesLength;
// calculate container width
// var containerWidth=numberOfBars*43;
// get chart bar width
var containerWidth=numberOfBars*barWidth;
chart.setSize($(container).width(),$(container).height());
};
In setChartContainerWidth() i used highchart setSize() method to resize chart..
Thanks if someone can help me to remove spaces in between bars of one group.
Thanks
I used the spacingTop attribute to enforce a maximum pointWidth:
if (series[0].data[0].pointWidth > maximumBarWidth) {
this.options.chart.spacingTop = this.options.chart.height - (maximumBarWidth * series.length) - 30;
this.isDirtyBox = true;
this.redraw();
}
So if there is one Bar over a certain Width the spacing will be adjusted and the chart is drawn smaller.
This does not change the size of the container but keeps the bars beneath a certain size and your pointPadding and groupPadding will not be affected.
You will have to adjust the calculation of the spacingTop depending on your data structure and the size of your axis titles.
Related
I am working with XRange charts in High Charts where I have custom data labels for my data points. I face a similar problem in 2 scenarios:
When data label text is longer than width of corresponding data point range, it overflows outside and onto adjacent data points and hides their label, like this:
When scrolling across the x-axis, the data labels slide across and overflow even when the data point range isn't wide enough to show. This looks quite confusing;
.
You would notice it looks even worse here;
.
How do I fix this so that the data labels never flow outside the extent of the data point?
I have tried tweaking the "inside" parameter but it only ensures that the label doesn't flow into an adjacent row. Similarly, I looked at the crop and overflow options in the API but couldn't get it to work for me as needed.
I understand the width option in style might let me address the first problem, but I can't have a common absolute value in pixels for all labels as the width of each is dynamic. Also, the second problem still wouldn't be solved.
You can find both issues re-created here : https://jsfiddle.net/td0bsxg1/4/ . I need to handle both of them as gracefully as possible.
Do I need to change some parameter for the data labels?
dataLabels: {
enabled: true,
defer: false,
inside: true,
formatter: function () {
return 'Too Long Data Label';
}
}
You can dynamically set individual width style for each data label and define rules for them:
events: {
render: function() {
if (redrawEnabled) {
var points = this.series[0].points,
chart = this,
dataLabelWidth,
width;
redrawEnabled = false;
Highcharts.each(points, function(point) {
width = point.shapeArgs.width;
if (width < 20) {
point.dataLabel.hide();
} else {
point.dataLabel.show();
}
point.dataLabel.css({
width: width
});
});
chart.series[0].isDirty = true;
chart.redraw();
redrawEnabled = true;
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/wo0q9nzr/
I have a column chart that has yAxis labels inside the plot area. DEMO: http://jsfiddle.net/o4abatfo/
This is how I have set up the labels:
yAxis: {
labels: {
align: 'left',
x: 5,
y: -3
}
}
The problem is that the leftmost column is so near the plot area edge that labels are overlapping it. Is there a way to adjust the plot area padding so that the columns would start a bit further on the right?
You can set min value as -0.49.
http://jsfiddle.net/o4abatfo/2/
One possible solution:
Keep the labels on the outside, and apply the plotBackgroundColor as the chart backgroundColor.
This means that the legend will be encased in the background color too, but, again, it's on option.
Example:
http://jsfiddle.net/jlbriggs/o4abatfo/11/
I asked the same thing in the Highcharts forum and got this solution as a reply from #paweł-fus:
var chartExtraMargin = 30;
Highcharts.wrap(Highcharts.Axis.prototype, 'setAxisSize', function (p) {
p.call(this);
if (this.isXAxis) {
this.left += chartExtraMargin;
this.width -= chartExtraMargin;
this.len = Math.max(this.horiz ? this.width : this.height, 0);
this.pos = this.horiz ? this.left : this.top;
}
});
However, adding this made the tooltips appear in the wrong position. This was fixed by overriding the Tooltip.prototype.getAnchor() method and adding the extra margin in the x coordinate:
Highcharts.wrap(Highcharts.Tooltip.prototype, 'getAnchor', function(p, points, mouseEvent) {
var anchor = p.call(this, points, mouseEvent);
anchor[0] += chartExtraMargin;
return anchor;
});
Is there anyway to dynamically set a specific width of legend items when resizing the chart? I have some really long item names possible in the legend so I need to specify a width to force the text to wrap, but I would like to change the width when the width the chart changes. Thanks.
I found a better work around for this:
chart.legend.options.width = newwidth;
chart.legend.itemStyle.width = newwidth;
for(var index in this.chart.series) {
chart.legend.destroyItem(chart.series[index]);
}
chart.legend.render()
Generally it is not possible, but you can disable highcharts legend, and prepare your own div (positioned absolutely) which will include list of all series and click event. Simple example is available here
$legend = $('#customLegend');
$.each(chart.series[0].data, function (j, data) {
$legend.append('<div class="item"><div class="symbol" style="background-color:'+data.color+'"></div><div class="serieName" id="">' + data.name + '</div></div>');
});
$('#customLegend .item').click(function(){
var inx = $(this).index(),
point = chart.series[0].data[inx];
if(point.visible)
point.setVisible(false);
else
point.setVisible(true);
});
http://jsfiddle.net/N3KAC/10/
Than only what you need is adapt this to your chart by catching $(window).resize() function and resize element.
I have a highstock chart witch candlestick data type.
When I mouseover the data point, I want to highlight the background of the point.
This is what tooltip -> crosshairs do:
tooltip: {
crosshairs: true
}
But the only width option to set is the fixed width. See http://jsfiddle.net/8YBd7/.
This fixed width works with initial zoom, but when I change the zoom, the width is not updated with new point width.
When I set 100% width, the crosshair would fill entire chart area:
tooltip: {
crosshairs: {
width: '100%'
}
}
Is there another option how to highlight current data point by changing its background or setting the width to the pointPixelInterval or something else?
Meanwhile, I produced a dirty workaround, so improvements are welcomed:
xAxis: {
events: {
afterSetExtremes: function() {
this.chart.tooltip.crosshairs = [];
this.chart.options.tooltip.crosshairs.width = (this.width / (this.series[0].points.length-1));
}
}
}
http://jsfiddle.net/QbdEu/1/
Whenever the zoom is changed, the width is recounted according to chart width and number of displayed data points. The width is not updated when calling redraw(), so the old crosshair needs to be removed.
Have you tried to use Renderer http://api.highcharts.com/highstock#Renderer.rect() which allows to plot any shapes and defined width? Only what you need is getting point width in pixels frpm(chart.series[0].data[0].graphic) and then setting correct widht of "shape".
Is it possible to style individual data labels for a bar chart?
I would like to position each data label at the 0 axis point(for the chart) underneath each bar. However, if i signify x:0 for the data labels, it is different for each bar length. Can i get it to the 0 axis for the chart(with 5px padding:)
Thanks!
In such case you can translate that labels using simple hack, see:
events: {
load: function(){
for(var i = 0; i < this.series[0].data.length; i++) {
var d = this.series[0].data[i];
d.dataLabel.translate(0, d.dataLabel.y);
}
}
}
Live example: http://jsfiddle.net/zLE5R/2/