Chart shrink when updating data - javascript

I have a strange behavior using highchart. Once while when updating some point my chart shrink and I have some empty value at the beginning and at the end. See the difference in the picture below.
This happen only once a while and I have no error log in the console.
Here is the configuration of my chart:
container.highcharts({
chart: {
animation: false,
type: 'column',
spacingRight: 0
},
noData: {
position: {x: 10, y: 10},
style: { color: "white" }
},
legend: {
enabled: false
},
tooltip: {
animation: false
},
credits: {
enabled: false
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
minorGridLineWidth: 0,
minorTickLength: 0,
maxPadding: 0,
minTickInterval: 60000,
showFirstLabel: false,
showLastLabel: false
},
yAxis: {
minRange: 10,
floor: 0,
gridLineColor: "#000000",
gridZIndex: 7,
title: {
text: widgetModel.title
}
},
plotOptions: {
column: {
pointInterval: 0,
pointPadding: 0,
borderWidth: 1,
borderColor: '#000000',
groupPadding: 0,
grouping: false,
shadow: false
},
series: {
pointInterval: 0,
stacking: 'normal',
events : {
click : function() {
var seriesArray = this.chart.series;
for (var i = 0; i < seriesArray.length; i++) {
var series = seriesArray[i];
if (series.name != this.name) {
if (series.visible) {
series.setVisible(false, false);
} else {
series.setVisible(true, false);
}
}
}
self.chart.redraw();
}
}
}
},
series: []
});
The code for updating the point is below:
addPointToSerie: function (serie, date, value) {
var pointId = serie.name + "_" + date.getTime().toString();
var point = undefined;
var points = serie.points || [];
// Allow fast access of point.
if (this.pointMap.hasOwnProperty(pointId)) {
point = this.pointMap[pointId];
}
else {
for (var j = 0; j < points.length; j++) {
if (points[j].id === pointId) {
point = points[j];
this.pointMap[pointId] = point;
}
}
}
if (point != undefined) {
// Optimize to update only point that have change
if (point.y != value) {
point.update(value, false);
}
} else {
serie.addPoint({x:date, y:value, id:pointId}, false, false, false);
}
},
And after adding or updating all the point I do a
this.chart.redraw();
So does someone know why the shrink of the chart happen ?

Related

How to set maximum and minimum value color of highcharts?

I'm trying to set the color of maximum and minimum in highcharts. Unfortunately, I'm unable to do it. I've searched a lot but unable to get the answer. From data, I'll know maximum and minimum value of each row & I want to set the color for minimum and maximum values of each row using highcharts.
This is my current output:
but I want this:
Here is my code:
Highcharts.SparkLine = function (a, b, c) {
var hasRenderToArg = typeof a === 'string' || a.nodeName,
options = arguments[hasRenderToArg ? 1 : 0],
defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 120,
height: 20,
style: {
overflow: 'visible'
},
// small optimalization, saves 1-2 ms each sparkline
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
title: {
text: null
},
startOnTick: false,
endOnTick: false,
tickPositions: []
},
yAxis: {
endOnTick: false,
startOnTick: false,
labels: {
enabled: false
},
title: {
text: null
},
tickPositions: [0]
},
legend: {
enabled: false
},
tooltip: {
hideDelay: 0,
outside: true,
shared: true
},
plotOptions: {
series: {
animation: false,
lineWidth: 1,
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
marker: {
radius: 1,
states: {
hover: {
radius: 2
}
}
},
fillOpacity: 0.25
},
column: {
negativeColor: '#910000',
borderColor: 'silver'
}
}
};
options = Highcharts.merge(defaultOptions, options);
return hasRenderToArg ?
new Highcharts.Chart(a, options, c) :
new Highcharts.Chart(options, b);
};
Find the minimum and maximum number from data and than color.
Paste the following code in do chunk function.
a = Math.max(...data);
b = Math.min(...data);
for(j = 0; j < data.length; j++) {
if (data[j] == a) {
data[j] = { y: parseInt(a), color: '#A9D08E' };
}
if (data[j] == b) {
data[j] = { y: parseInt(b), color: '#F4B084' };
}
}
Use colorAxis property, you can define minColor and maxColor in ColorAxis. See example here https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/maps/coloraxis/mincolor-maxcolor/
colorAxis: {
min: 1,
max: 1000,
type: 'logarithmic',
minColor: '#efecf3',
maxColor: '#990041'
},

Display two labels for each bar in highcharts(one inside and one outside)

I wanted to display two labels on bars. I am able to display one label right now. I want something like this.
Instead I am getting like this
The code snippet which I am using to show the labels is
plotOptions: {
column: {
dataLabels: {
enabled: true,
color: "black",
style: {
textOutline: false
}
}
}
}
how Can I show these percentage value on the bars? Thanks in Advance.
For placing label with percentage inside the particular column you should give dataLabels inside that series, for rest of the column use common dataLabels as defined by you in plotOptions. Below code is for idea only Fiddle link
var data = [7, 12, 16, 32];
var dataSum = 0;
for (var i = 0; i < data.length; i++) {
dataSum += data[i]
}
var data2 = [5, 19, 14, 13];
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: ''
},
xAxis: {
type: 'category',
},
yAxis: {
min: 0,
},
legend: {
enabled: false
},
plotOptions: {
column: {
dataLabels: {
enabled: true,
color: "black",
style: {
textOutline: false
}
}
}
},
series: [{
name: 'first',
data: data,
dataLabels: {
y: 20, /*for placeing lables values inside column*/
enabled: true,
formatter: function() {
var pcnt = (this.y / dataSum) * 100;
return Highcharts.numberFormat(this.y , 0) +'<br>'+Highcharts.numberFormat(pcnt) + '%';
}
}
}, {
name: 'Second',
data: data2,
}]
});

WinJS - Highcharts isn't loaded in Google Chrome

Good morning,
I'm working on small dashboard and using WinJS, but I have problem with Highcharts. They can't load inside WinJS.UI.HubSection and only in google chrome. I tried firefox and there is showed. I have second graph where I'm using Highstock and then works fine everywhere. I tried almost everything and don't know why the highchart isn't loaded inside HubSection. Thanks for your answers and help.
RainbowShaggy
You are trying to create a chart in div #vehicles, but jQuery (in your demo) nor Highcharts (I tested) are able to find that container.
It seems that when Highstock chart is created all divs are available, so if you will be creating all charts in createChart function, then they should be created successfully.
Example: https://jsfiddle.net/r6twbj0z/6/
var clientsArray = [];
stationsArray = [];
companiesArray = [];
WinJS.Namespace.define("ListView.Clients", {
data: new WinJS.Binding.List(clientsArray)
});
WinJS.Namespace.define("ListView.Stations", {
data: new WinJS.Binding.List(stationsArray)
});
WinJS.Namespace.define("ListView.Companies", {
data: new WinJS.Binding.List(companiesArray)
});
WinJS.UI.processAll();
$(function() {
var seriesOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'];
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createChart() {
$('#companyvalue').highcharts('StockChart', {
/*chart : {
events : {
load : function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, false);
}, 1000);
}
}
},*/
rangeSelector: {
selected: 4
},
yAxis: {
labels: {
formatter: function() {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: seriesOptions
});
$('#vehicles').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Použité vozidla'
},
xAxis: {
categories: ['Vlaky', 'Autobusy', 'Nákl. auta', 'Lodě', 'Letadla']
},
yAxis: {
min: 0,
title: {
text: 'Počet vozidel'
},
stackLabels: {
enabled: true,
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
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black'
}
}
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
});
}
$.each(names, function(i, name) {
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function(data) {
seriesOptions[i] = {
name: name,
data: data
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter += 1;
if (seriesCounter === names.length) {
createChart();
}
});
});
});

Highchart js click rotate and expand arc

Hi I'm looking to create a pie chart with highchart js that expands twolayers, and rotates to the center whenever I click a section.
So far I have a pie chart that expands one layer, and a click function that brings the arcs to the center (-90). I also have a click function that rotates the pie by degrees. My inner arc stays in the center and im having a hard time moving the arc to the same position of the out rings. The inner arc do not follow the click rotate aswell.
I would like to make a pie that rotates smoothly to center (-90) and expands with two extra layers. with the inner arch to follow the outer arch and be in the same starting point as the outer arch
Thank you in advance
here is what my code executes and looks like :
pie chart with what im currently running
Here is my script
$(function () {
var lastHighlight = -1;
var lastPos = [10,10,10];
$('#mouseMoveDiv').click(function () {
var theChart = $('#container').highcharts();
var currStartAngle = theChart.series[0].options.startAngle;
//console.log('currStartAngle: ' + currStartAngle);
var newStartAngle = currStartAngle + 5;
if (newStartAngle > 359) {
newStartAngle = 5;
}
//console.log(newStartAngle);
theChart.series[0].update({
startAngle: newStartAngle
});
var someData = theChart.series[0].data;
var N = someData.length;
var highLight = -1;
for (var i = 0; i < N; i++){
var startAngle = someData[i].angle + (((someData[i].percentage/100) * 6.28318)/2);
var dis = 1.5795 - startAngle;
if (lastPos[i] > 0 && dis < 0){
highLight = i;
lastPos[i] = dis;
break;
}
lastPos[i] = dis;
}
if (highLight != -1){
var someRows = $('#dataTable tr');
someRows.eq(lastHighlight).css('backgroundColor','white');
someRows.eq(highLight).css('backgroundColor','yellow');
lastHighlight = highLight;
}
});
$('#container').highcharts({
chart: {
type: 'pie',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
format: '{point.name}',
center: ["50%", "50%"],
connectorWidth: 0,
startAngle: 90,
animation: false
}
}
},
exporting: {
enabled: false
},
tooltip: {
enabled: false
},
credits: {
enabled: false
},
title: {
text: null
},
series: [{
type: 'pie'
data: [
{ name: 'Planning', y: 33.3 },
{ name: 'Sprints', y: 33.3 },
{ name: 'Release', y: 33.3 }
],
size: '60%',
innerSize: '40%',
point: {
events: {
click: function () {
var chart = this.series.chart,
series = chart.series,
len = series.length,
index = this.x + 1,
i;
for (i = 1; i < len; i++) {
if (i === index) {
series[i].update({
size: '100%',
dataLabels: {
enabled: true
}
}, false);
} else {
series[i].update({
size: '0%',
dataLabels: {
enabled: false
}
}, false);
}
}
var points = this.series.points;
var startAngle = 0;
for (var i = 0; i < points.length; i++) {
var p = points[i];
if (p == this) {
break;
}
startAngle += (p.percentage / 100.0 * 360.0);
}
this.series.update({
startAngle: -startAngle + 90 - ((this.percentage / 100.0 * 360.0) / 2) // center at 180
})
chart.redraw();
}
}
},
dataLabels: {
distance: 90, //distance name
style: {
color: 'Black'
},
enabled: true
},
zIndex: 1
},
{
zIndex: 0,
type: 'pie',
size: '60%',
innerSize: '0%',
data: [{
y: 2,
color: 'rgba(250,0,0,1)',
name: 'Training'
},
{
y: 2,
color: 'rgba(250,0,0,1)',
name: 'Secure'
},
{
y: 8,
color: 'rgba(0,0,0,0)',
dataLabels: {
enabled: false
}
}],
dataLabels: {
distance: -30,
enabled: false,
style: {
color: 'black'
}
},
enableMouseTracking: false
},
{
zIndex: 0,
type: 'pie',
size: '0%',
data: [{
y: 3,
color: 'rgba(0,0,0,0)',
dataLabels: {
enabled: false
}
}, {
y: 1,
color: 'rgba(0,200,0,1)',
name: 'test'
}, {
y: 1,
color: 'rgba(0,200,0,1)',
name: 'test'
}, {
y: 1,
color: 'rgba(0,200,0,1)',
name: 'test'
}, {
y: 3,
color: 'rgba(0,0,0,0)',
dataLabels: {
enabled: false
}
}],
dataLabels: {
distance: -30,
enabled: false
style: {
color: 'black'
}
},
enableMouseTracking: false
},
{
zIndex: 0,
type: 'pie',
size: '0%',
data: [{
y: 6,
color: 'rgba(0,0,0,0)',
dataLabels: {
enabled: false
}
}, {
y: 1,
color: 'rgba(0,0,200,1)',
name: 'test'
}, {
y: 1,
color: 'rgba(0,0,200,1)',
name: 'test'
}, {
y: 1,
color: 'rgba(0,0,200,1)',
name: 'test'
}],
dataLabels: {
distance: -30,
enabled: false,
style: {
color: 'black'
}
},
enableMouseTracking: false
}]
});
});
I suggest to change logic a bit: use one series for each of the circles, and manage manually visibility of the slices instead. For example: http://jsfiddle.net/vkhvvs5d/3/
And to answer the second question, rotate animation is not supported when using series.update(), however it have an easy workaround: http://jsfiddle.net/8x54efu6/3
var chart = $("#container").highcharts(),
pie = chart.series[0];
pie.options.startAngle = new_angle;
pie.isDirty = pie.isDirtyData = true;
chart.redraw();

( Highcharts ) How to make dataLabels disappear if there is, a higher column?

I have a chart which has attribute column.grouping set to false,
and I would like to show data labels only on highest columns.
Here is an example
dataLabels: {
enabled: true
}
I have tried to find solution for couple hours now, I would appreciate any help.
I think it would be the easiest to use point.dataLabels.enabled option. Just preprocess data before rendering the chart, to determine which points should display values, see: http://jsfiddle.net/9f1maj3x/
And code:
function enableLabels(d_1, d_2) {
// compare two data series and enable dataLabel for a higher column:
$.each(d_1, function (i, point) {
if (point > d_2[i]) {
d_1[i] = {
dataLabels: {
enabled: true
},
y: d_1[i]
}
} else {
d_2[i] = {
dataLabels: {
enabled: true
},
y: d_2[i]
}
}
});
return [d_1, d_2];
}
Data example:
var data = [
[150, 73, 20],
[140, 90, 40],
[103.6, 178.8, 198.5],
[203.6, 198.8, 208.5]
];
var leftColumns = enableLabels(data[0], data[1]),
rightColumns = enableLabels(data[2], data[3]);
And example in Highcharts:
series: [{
name: 'Employees',
color: 'rgba(165,170,217,1)',
data: leftColumns[0],
pointPadding: 0.3,
pointPlacement: -0.2
}, {
name: 'Employees Optimized',
color: 'rgba(126,86,134,.9)',
data: leftColumns[1],
pointPadding: 0.4,
pointPlacement: -0.2
}, {
name: 'Profit',
color: 'rgba(248,161,63,1)',
data: rightColumns[0],
tooltip: {
valuePrefix: '$',
valueSuffix: ' M'
},
pointPadding: 0.3,
pointPlacement: 0.2,
yAxis: 1
}, {
name: 'Profit Optimized',
color: 'rgba(186,60,61,.9)',
data: rightColumns[1],
tooltip: {
valuePrefix: '$',
valueSuffix: ' M'
},
pointPadding: 0.4,
pointPlacement: 0.2,
yAxis: 1
}]
you can use
chart.yAxis[0].max;
or
this.dataMax
to get maximum value. to compare , in formatter function compare both and retrun larger one.
You can write a formatter for the dataLabel that checks if it's the highest for that yAxis, here's the API documentation:
http://api.highcharts.com/highcharts#plotOptions.series.dataLabels.formatter
After comments: You can take the data out of the chart object and use a formatter to pick the largest one, fiddle: http://jsfiddle.net/7zc5peyf/1/
var em = [150, 73, 20];
var eo = [140, 90, 40];
data label code:
data: em,
dataLabels:{
enabled: true,
formatter: function(){
if(this.y > eo[this.point.index]){
return this.y;
}
}
}
Here is my solution:
$(function () {
var something = {
chart: {
type: 'column'
},
title: {
text: 'Efficiency Optimization by Branch'
},
xAxis: {
categories: [
'Seattle HQ',
'San Francisco',
'Tokyo']
},
yAxis: [{
min: 0,
title: {
text: 'Employees'
}
}, {
title: {
text: 'Profit (millions)'
},
opposite: true
}],
legend: {
shadow: false
},
tooltip: {
shared: true
},
plotOptions: {
column: {
grouping: false,
shadow: false,
borderWidth: 0
},
series: {
events: {
hide: function () {
console.log(this);
},
show: function () {
console.log(this);
},
legendItemClick: function () {
for (var i = 0; i < something.series.length; i++) {
if (something.series[i].name === this.name) {
something.series[i].visible = !this.visible;
}
}
console.log(this.name);
}
}
}
},
series: [{
name: 'Employees',
color: 'rgba(165,170,217,1)',
visible: true,
data: [150, 73, 20],
pointPadding: 0.3,
pointPlacement: -0.2,
dataLabels: {
enabled: true,
formatter: function () {
var index = something.xAxis.categories.indexOf(this.x);
if ((this.y > something.series[1].data[index]) || !something.series[1].visible) {
console.log(something.series.visible);
return this.y + '*';
}
return '';
}
}
}, {
name: 'Employees Optimized',
color: 'rgba(126,86,134,.9)',
visible: true,
data: [140, 90, 40],
pointPadding: 0.4,
pointPlacement: -0.2,
dataLabels: {
enabled: true,
formatter: function () {
var index = something.xAxis.categories.indexOf(this.x);
if ((this.y > something.series[0].data[index]) || !something.series[0].visible) {
console.log(something.series.visible);
return this.y + '*';
}
return '';
}
}
}, {
name: 'Profit',
color: 'rgba(248,161,63,1)',
visible: true,
data: [193.6, 128.8, 144.5],
tooltip: {
valuePrefix: '$',
valueSuffix: ' M'
},
pointPadding: 0.3,
pointPlacement: 0.2,
yAxis: 1,
dataLabels: {
enabled: true,
formatter: function () {
var index = something.xAxis.categories.indexOf(this.x);
if ((this.y > something.series[3].data[index]) || !something.series[3].visible) {
return this.y + '*';
}
return '';
}
}
}, {
name: 'Profit Optimized',
color: 'rgba(186,60,61,.9)',
visible: true,
data: [123.6, 198.8, 208.5],
tooltip: {
valuePrefix: '$',
valueSuffix: ' M'
},
pointPadding: 0.4,
pointPlacement: 0.2,
yAxis: 1,
dataLabels: {
enabled: true,
formatter: function () {
var index = something.xAxis.categories.indexOf(this.x);
if ((this.y > something.series[2].data[index]) || !something.series[2].visible) {
console.log(something.series.visible);
return this.y + '*';
}
return '';
}
}
}]
};
$('#container').highcharts(something);
});
http://jsfiddle.net/7zc5peyf/4/

Categories