Highcharts - center placement of columns - javascript

I have a Highcharts column chart and I am trying to reduce the distance between each column on the X axis whilst pulling them towards the center so that the columns appear more grouped.
So for example in my example above, the red and the blue column would be much closer together and positioned towards the center.
Below is my chart configuration. The seriesData parameter is just a custom object I pass in at render.
chartConfig.js
function chartConfig(seriesData) {
return {
barColor: seriesData.color,
data: seriesData,
credits: { enabled: false },
chart: {
width: seriesData.width,
defaultSeriesType: 'column',
backgroundColor: '#EAEFF6'
},
tooltip: { enabled: false },
colorAxis: {
dataClassColor: 'category'
},
colors: [],
legend: {},
title: {
useHTML: true,
text: (seriesData.name === 'n/a' || seriesData.name === 'N/A') ? '_' : seriesData.name,
style: {
color: (seriesData.name === 'n/a' || seriesData.name === 'N/A') ? '#E9EFF4' : '#666666',
fontSize: '14px',
fontFamily: 'Roboto',
fontWeight: 'bold',
paddingTop: '10px',
lineHeight: '1em'
},
align: 'center',
x: 0,
y: 2
},
plotOptions: {
column: {
stacking: 'normal',
animation: true,
borderColor: 'grey',
borderWidth: 0
},
series: {
borderRadius: 15,
dataLabels: {
enabled: false
},
states: {
hover: {
enabled: false
}
}
}
},
yAxis: [{
max: Math.max.apply(null, seriesData.scaleValues),
min: Math.min.apply(null, seriesData.scaleValues),
title: false,
minorGridLineColor: '#FFF',
gridLineColor: '#8E8E8E',
minPadding: 0,
tickPositions: (seriesData.scalePercentageValues || null),
labels: {
formatter: function () {
if (seriesData.usePercentage) {
return `${this.value} %`;
}
return this.value;
}
}
}],
xAxis: {
lineWidth: 0,
minorGridLineWidth: 0,
lineColor: 'transparent',
minorTickLength: 0,
tickLength: 0,
categories: seriesData.elements.map((x) => { return x.name; }),
labels: {
style: {
color: '#666666',
fontSize: '12px',
fontFamily: 'Roboto'
}
}
},
series: [{
dataLabels: {
style: {
fontSize: '12px',
fontWeight: 'normal',
textShadow: 'none',
color: 'black',
fontFamily: 'Roboto',
backgroundColor: 'blue'
},
enabled: true,
formatter: function () {
if (seriesData.usePercentage) {
return `${this.y}%`;
}
return this.y;
}
},
showInLegend: false,
name: 'Fill Series',
color: '#F2F6F9',
pointWidth: 28,
animation: true,
data: seriesData.elements.map((x) => {
return { name: x.name, y: x.value, color: x.color };
}),
borderRadiusTopLeft: 10,
borderRadiusTopRight: 10,
borderColor: '#C0C0C0',
borderWidth: '1'
}]
};
}
module.exports = chartConfig;
The only solution I have tried so far is to use pointPadding and groupPadding. However this does not seem to have the desired effect.

Related

Highcharts angular wrapper labels.items don't refresh

I'm using angular6 and the office highcharts angular wrapper (https://github.com/highcharts/highcharts-angular) in version 2.4.0.
Everything is working good except the labels that can be placed manually on the chart.
I just don't manage to get them refreshed.
I have a graph that can be filtered through the back-end. When I get the new generated data I update the data in my chartOptions which are used in the html as [options]="chartOptions" for the angular component.
The chartOptions are instanciated from my default class like this: this.chartOptions = new GraphConfigSeqAtteptedVsAchived().chartOptions;
The Class looks like this:
`import * as Highcharts from 'highcharts';
export class GraphConfigSeqAtteptedVsAchived{
public chartOptions: any;
constructor(){
this.chartOptions = {
chart: {
height: 600,
width: 620,
events:{load: function(){
this.myTooltip = new Highcharts.Tooltip(this, this.options.tooltip);
}
},
backgroundColor: 'transparent',
},
credits: {
text: 'charname',
href: ''
},
labels: {
},
exporting:{
chartOptions:{
title: {
text:'not set',
style:{
color: '#000000'
},
margin: 0
}
}
},
tooltip: {
enabled: false
},
xAxis: {
min: -10,
max: 0,
width: 535,
title: {
text: 'Rainfall (mm)',
style: {
fontWeight: "bold",
color: '#000000'
}
},
reversed: true,
tickInterval: 1
},
yAxis: {
min: -10,
max: 0,
title: {
text: 'Rainfall (mm)',
style: {
fontWeight: "bold",
color: '#000000'
}
},
reversed: true,
tickInterval: 1
},
title: {
text: ' as',
margin: 0,
style:{
color: 'transparent'
}
},
legend: {
layout: 'vertical',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 90,
floating: true,
backgroundColor: '#FFFFFF',
borderWidth: 1,
navigation: {
enabled: false
}
},
plotOptions: {
scatter: {
stickyTracking: false,
allowPointSelect: true,
marker: {
radius: 3,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '',
hideDelay: 500
},
symbol: "circle",
events: {
mouseOut: function() {
this.chart.myTooltip.hide();
this.chart.myTooltip.options.enabled = false;
},
mouseOver: function() {
if(this.halo) {
this.halo.attr({
'class': 'highcharts-tracker'
}).toFront();
}
},
click: function(event) {
this.chart.myTooltip.options.enabled = true;
this.chart.myTooltip.refresh(event.point, event);
}
}
},
line:{
events: {
legendItemClick: function () {
return false;
}
}
},
series:{
allowPointSelect: true
}
},
series: [{
type: 'line',
data: [[30, 30], [-30, -30]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 1
}
},
showInLegend: false,
color: "rgba(0, 0, 0, 0.6)",
enableMouseTracking: false
},{
type: 'line',
data: [[30, 29.5], [-29.5, -30]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(125, 162, 159, 0.35)",
enableMouseTracking: false
},{
type: 'line',
data: [[29.5, 30], [-30, -29.5]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(125, 162, 159, 0.35)",
enableMouseTracking: false
},{
type: 'line',
data: [[29, 30], [-30, -29]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(197, 144, 161, 0.35)",
enableMouseTracking: false
},{
type: 'line',
data: [[30, 29], [-29, -30]],
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
showInLegend: false,
dashStyle: 'ShortDash',
color: "rgba(197, 144, 161, 0.35)",
enableMouseTracking: false
}]
}
}
}`
The generated data is in the typescript dynamically added and all of that works just fine. Everything is refreshed after I set the updateFlag for [(update)]="updateGraph". The axis titles are also fine.
The only thing that's not refreshed for me are the labels i dynamically added to the chart like this:
let labelTotalNumberOfEyes = {
html : this.translate.instant('GRAPHS.TOTAL_NUMBER_OF_EYES') + ': ' + (scatterSeries.data.length + scatterSeriesRetreatment.data.length),
style : {
left : '330px',
top : '368px',
fontSize : '14px',
backgroundColor: '#FFFFFF',
borderWidth: 1,
}
}
this.chartOptions.labels.items.push(labelTotalNumberOfEyes);
Does someone have any idea what I'm might doing wrong? I don't see any further option than just setting this update flag and it works fine for everything but the labels.
Please let me know if you're missing any information.
Thanks in advance.
This issue is actually a Highcharts bug. I've reported it here: https://github.com/highcharts/highcharts/issues/10429.
As a workaround, you can use Highcharts.SVGRenderer to add a custom label and store reference to it in your component. Next, when updating, call attr() method on the label (Highcharts.SVGElement) and set new options. Check demo and code posted below.
Add a label on chart callback:
constructor() {
const self = this;
this.chartCallback = chart => {
self.chart = chart;
self.label = chart.renderer
.text("test", 100, 100)
.css({
fill: "#555",
fontSize: 16
})
.add()
.toFront();
};
}
call attr() on the label while updating:
update_chart() {
const self = this,
chart = this.chart;
chart.showLoading();
setTimeout(() => {
chart.hideLoading();
self.chartOptions.series = [
{
data: [10, 25, 15],
name: "updatedSerieName"
}
];
self.chartOptions.yAxis.title.text = "updatedData";
self.label
.attr({
text: "test1",
x: 150,
y: 120
})
.css({
fill: "red",
fontSize: 20
});
self.updateFromInput = true;
}, 2000);
}
Demo:
https://codesandbox.io/s/8zo0yvqqwj
API reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr

Highcharts stacked column charts ( Parse json string for series)

I am getting following json string on Ajax call from javascript:-
var json = [{"date":"2018-05-16","MsgType":"xyz","count":4},
{"date":"2018-05-16","MsgType":"tyu","count":15},
{"date":"2018-05-15","MsgType":"sdf","count":5},
{"date":"2018-05-14","MsgType":"mnb","count":9},
{"date":"2018-05-14","MsgType":"xyz","count":8},
{"date":"2018-05-14","MsgType":"tyu","count":14}];
I want to fill series of my highchart with the above given data. My requirement is to make "date" as X-Axis, "MsgType" as name and "Count" as data. I have for two objects when i needed to put count for MsgTypes. But here first i need to group data based on date and then need to place each MsgType with count in stack. Please help me with this as i am not able to figure out anything. Any help will be appreciated. I have implemented following for other scenario : -
Highcharts.chart('MP_Chart', {
chart: {
type: 'column'
},
title: {
text: 'Market Processes',
style: { "fontSize": "16px", "font-weight": "bold" }
},
credits: {
enabled: false
},
xAxis: {
categories: Date,
labels: {
style: {
fontWeight: 'bold'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Total Queued messages',
style: {
fontWeight: 'bold'
}
},
stackLabels: {
enabled: false,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
itemStyle: {
fontSize: '12px',
font: '12pt',
}
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'Queued',
data: JSON.parse("[" + QueuedMPCount + "]")
}, {
name: 'Polled',
data: JSON.parse("[" + PolledMPCount + "]")
}]
});
Assuming I understood your question correctly, you need to pre-process the data a bit before passing it to Highcharts, for example, like this:
var json = [{"date":"2018-05-16","MsgType":"xyz","count":4},
{"date":"2018-05-16","MsgType":"tyu","count":15},
{"date":"2018-05-15","MsgType":"sdf","count":5},
{"date":"2018-05-14","MsgType":"mnb","count":9},
{"date":"2018-05-14","MsgType":"xyz","count":8},
{"date":"2018-05-14","MsgType":"tyu","count":14}];
json = json.reverse() //reverse incomming json because highcharts expectes sorted dates
var series = [];
var names = [];
for (let i = 0; i < json.length; i++) { //loop through all incoming records
if (names.indexOf(json[i].MsgType) !== -1) { //check if we have a record with this messageType yet, if yes, add to that messagetypes array
series[names.indexOf(json[i].MsgType)].data.push({
x: new Date(json[i].date),
y: json[i].count
})
} else { //add new messageTypes
names.push(json[i].MsgType)
series.push({
name: json[i].MsgType,
data: [{
x: new Date(json[i].date),
y: json[i].count
}]
})
}
}
Coupled with this, I changed the xAxis type to datetime and series definition to take the variable we created earlier:
xAxis: {
type: 'datetime',
...
},
series: series
We then get this:
var json = [{"date":"2018-05-16","MsgType":"xyz","count":4},
{"date":"2018-05-16","MsgType":"tyu","count":15},
{"date":"2018-05-15","MsgType":"sdf","count":5},
{"date":"2018-05-14","MsgType":"mnb","count":9},
{"date":"2018-05-14","MsgType":"xyz","count":8},
{"date":"2018-05-14","MsgType":"tyu","count":14}];
json = json.reverse()
var series = [];
var names = [];
for (let i = 0; i < json.length; i++) {
if (names.indexOf(json[i].MsgType) !== -1) {
series[names.indexOf(json[i].MsgType)].data.push({
x: new Date(json[i].date),
y: json[i].count
})
} else {
names.push(json[i].MsgType)
series.push({
name: json[i].MsgType,
data: [{
x: new Date(json[i].date),
y: json[i].count
}]
})
}
}
Highcharts.chart('MP_Chart', {
chart: {
type: 'column'
},
title: {
text: 'Market Processes',
style: {
"fontSize": "16px",
"font-weight": "bold"
}
},
credits: {
enabled: false
},
xAxis: {
type: 'datetime',
labels: {
style: {
fontWeight: 'bold'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Total Queued messages',
style: {
fontWeight: 'bold'
}
},
stackLabels: {
enabled: false,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
itemStyle: {
fontSize: '12px',
font: '12pt',
}
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: series
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="MP_Chart"></div>
JSfiddle working example: https://jsfiddle.net/ewolden/Lbyq4k0n/19/

How to make a square and horizontal lines in highcharts?

Need help with highchartsJs. I need chart like on screenshots. For lines i found this, but not fully what i needed. For square i don't have any ideas. Square is most priority.
Any help will be appreciated. Thanks.
square
horizontal lines
If someone need something like this
https://jsfiddle.net/gdgb941o/20/
chart: {
type: 'column'
},
title: {
text: false
},
tooltip: {
enabled: false
},
credits: {
enabled: false
},
xAxis: {
tickWidth: 0,
lineWidth: 0,
type: 'category',
gridLineWidth: 0
},
yAxis: {
lineWidth: 0,
gridLineWidth: 0,
labels: {
enabled: false
},
max: 100,
title: {
text: false
}
},
navigation: {
buttonOptions: {
enabled: false
}
},
legend: {
enabled: false
},
plotOptions: {
column: {
borderWidth: 0,
grouping: false
},
series: {
}
},
series: [{
data: [{
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'Yes',
y: 100,
dataLabels: {
formatter: function() {
return "33" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
}, {
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'The email did not come',
y: 100,
dataLabels: {
formatter: function() {
return "80" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
}, {
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'Error in verification',
y: 100,
dataLabels: {
formatter: function() {
return "55" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
},
{
borderWidth: 2,
borderColor:'#41bc9b',
color: 'white',
name: 'No',
y: 100,
dataLabels: {
formatter: function() {
return "20" + "%"
},
enabled: true,
inside: true,
align: 'center',
color: 'black',
style: {
fontSize: 20,
textOutline: false
}
}
}]
}, {
pointPadding: 0.125,
data: [{
color: '#41bc9b',
name: 'Yes',
y: 33
}, {
color: '#41bc9b',
name: 'The email did not come',
y: 80
}, {
color: '#41bc9b',
name: 'Error in verification',
y: 55
},
{
color: '#41bc9b',
name: 'No',
y: 20
}]
}]

Highcharts AreaSpline - Adding padding in between the chart and plot area

I am trying to add padding in between my chart and plot area, as you can see in the screenshot below, the markers are overflowing across the borders of the plot area.
Is there a way for me to add padding to the bottom of the plot area, or a way to move up the chart series slightly so that it doesn't overflow?
Here is a fiddle: http://jsfiddle.net/H3Asy/5/
Here is the JS code:
$('#container').highcharts({
chart: {
type: 'areaspline',
marginLeft: 25,
plotBorderWidth: 2,
plotBackgroundColor: {
linearGradient: [0, 0, 0, 178],
stops: [
[0.5, 'rgb(255, 255, 255)'],
[1, 'rgb(221, 221, 221)']
]
},
events: {
load: function(){
this.plotBackground.attr({ rx: 15, ry: 15 });
this.plotBorder.attr({ rx: 15, ry: 15 });
}
}
},
legend: {
enabled: false
},
credits: {
enabled: false
},
exporting: {
enabled: false
},
title: {
text: ''
},
subtitle: {
text: ''
},
xAxis: {
categories: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],
lineWidth: 0,
minorGridLineWidth: 0,
lineColor: 'transparent',
minorTickLength: 0,
tickLength: 0,
labels: {
rotation: -90,
align: 'right',
style: {
fontSize: '12px',
fontWeight: 'bold',
fontFamily: 'Sterling, sans-serif',
color: '#999'
},
x: 5,
y: 28
}
},
yAxis: {
title: {
text: ''
},
labels: {
formatter: function() {
if(this.isFirst) {
return this.value;
}
return bytesToSize(this.value, 0, true);
},
style: {
fontSize: '12px',
fontWeight: 'bold',
fontFamily: 'Sterling, sans-serif',
color: '#999'
},
align: 'center',
x: -16,
y: 12
},
gridLineColor: 'transparent'
},
tooltip: {
shared: true,
formatter: function() {
var tooltip = $('<div>');
var total = 0;
$.each(this.points, function(i, point){
total += this.y;
tooltip.append($('<div style="color: ' + point.series.area.fill + ';">').html(point.series.name + ': ' + bytesToSize(this.y,2)));
if(!(i % 2)){
tooltip.append('<br />');
}
});
tooltip.prepend($('<div style="color: #999;">').html('Total: ' + bytesToSize(total,2) + '<br />'));
return tooltip.get(0).outerHTML;
}
},
plotOptions: {
areaspline: {
lineWidth: 1.3,
marker: {
states: {
hover: {
radius: 5
}
}
},
states: {
hover: {
lineWidth: 1.3
}
}
}
},
series: [{
name: 'Download',
fillColor: 'rgba(0, 140, 194, 0.3)',
lineColor: '#008cc2',
data: [0,4815834355,23055591595,0,0,15404821463,0,20217522975,5521887522,0,0,1371666239,2134496,0,2948406184,12384283037,8231543133,9268703354,11368292543,1747717890,4540649201,4705338812]
}, {
name: 'Upload',
fillColor: 'rgba(117, 0, 198, 0.4)',
lineColor: '#7500c6',
marker: {
enabled: false,
states: {
hover: {
enabled: false
}
}
},
data: [0,201112067,1160271286,0,0,748962337,0,2289905587,211355292,0,0,64669389,559747,0,368939264,954704437,385646325,453112460,251406236,131414580,312915384,153890742]
}]
});
There is no perfect solution for that, but only two workarounds:
set min and startOnTick for xAxis, demo: http://jsfiddle.net/H3Asy/6/
yAxis: {
min: -1024 * 1024 * 1024,
startOnTick: false,
}
set threshold for series and startOnTick for xAxis, demo: http://jsfiddle.net/H3Asy/7/
yAxis: {
startOnTick: false
},
plotOptions: {
areaspline: {
threshold: -1
}
}

High Charts Rendering on Internet Explorer 10

Highcharts Bar chart doesn't render well when they are put inside HTML Table. Issue is reproduced in this Fiddle. Rendering problem can be seen when opened in IE 10(works well in chrome).
var options = {
colors: ["#3ACB35", "#DE3A15", "#FF9A00", "#00B8F1"],
chart: {
renderTo: 'Chart3container',
type: 'bar',
backgroundColor: 'black',
borderColor: 'black',
borderWidth: 0,
className: 'dark-container',
plotBackgroundColor: 'black',
plotBorderColor: '#000000',
plotBorderWidth: 0
},
credits: {
enabled: false
},
title: {
text: 'Count Per Category',
style: {
color: 'white',
font: 'normal 22px "Segoe UI"'
},
align: 'left'
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
style: {
color: '#F0F0F0'
}
},
categories: {
enabled: 'true'
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0,
itemStyle: {
font: '9pt Segoe UI',
color: 'white'
},
itemHoverStyle: {
color: 'grey'
}
},
xAxis: {
categories: BarData.categories,
tickInterval: 1,
labels: {
enabled: true,
style: {
color: 'white'
}
},
title: {
enabled: false
},
gridLineColor: '#222222'
},
yAxis: {
title:
{
enabled: true,
text: "Document Count",
style: {
fontWeight: 'normal',
color: 'white'
}
},
labels: {
style: {
color: 'white'
}
},
gridLineColor: '#222222'
},
exporting: {
enabled: false
},
plotOptions: {
series: {
stacking: 'normal',
cursor: 'pointer'
}
},
series: []
};
options.series = BarData.bardataarray;
chart1 = new Highcharts.Chart(options);
});
When put outside table, it works well. Here is the related Fiddle.
I need table for proper alignment.
You can disable animation or use CSS styles like here:
<table>
<tr>
<td style="width:287px;height: 278px; vertical-align: top;position:relative;">
<div id="container1" style="position:absolute;height: 270px; width:287px;overflow: hidden;"></div>
</td>
</tr>
</table>
Related topic: https://github.com/highslide-software/highcharts.com/issues/1157

Categories

Resources