I am trying to customize stacked column chart like this
Here i did all the remaining things but i Don't know how to give that bar lines above every column........I need that bar lines in both positive and negative axis
My code
$(document).ready(function () {
$('#div1').highcharts({
chart: { type: 'column', backgroundColor: 'transparent' },
title: { text: null },
subtitle: { text: null },
credits: {
enabled: false
},
xAxis: {
categories: categories,
labels: {
rotation: 0,
style: {
fontWeight: 'normal',
fontSize: '0.9vw',
fontFamily: 'Verdana, sans-serif',
color: "black"
}
}
},
yAxis: {
title: {
enabled: false
},
lineWidth: 0,
gridLineWidth: 1,
labels: {
enabled: true
},
// gridLineColor: 'transparent',
plotLines: [{
color: '#ddd',
width: 1,
value: 0
}],
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series:seriesforSeniorUPT
});
});
});
Link
Fiddle
To elaborate on Sebastian Bochan's helpful comment, here's an updated version of your fiddle with two "dummy" series to serve as the patterned background: https://jsfiddle.net/brightmatrix/hc8rLy18/2/
A few items to note:
There are two "dummy" series: one for the positive numbers and one for the negative numbers.
Both series have showInLegend and enableMouseTracking set to false so the user cannot interact with them.
Both series have stacking set to false so they will not be part of the "real" data you want to show.
Both series have zIndex set to 0. I explain why below the code block.
The code for the "dummy" series is as follows.
// background for positive values
obj = {};
obj["name"] = 'patternFill';
obj["data"] = [120, 120];
obj["color"] = 'url(#highcharts-default-pattern-3)';
obj["grouping"] = false;
obj["zIndex"] = 0;
obj["enableMouseTracking"] = false;
obj["stacking"] = false;
obj["showInLegend"] = false;
seriesforSeniorUPT.push(obj);
// background for negative values
obj = {};
obj["name"] = 'patternFill';
obj["data"] = [-80, -80];
obj["color"] = 'url(#highcharts-default-pattern-3)';
obj["grouping"] = false;
obj["zIndex"] = 0;
obj["enableMouseTracking"] = false;
obj["stacking"] = false;
obj["showInLegend"] = false;
seriesforSeniorUPT.push(obj);
For the three "real" data series, I set zIndex to 10 to they will appear over the "dummy" series we're using for our patterend backgrounds.
For all of the series, I set grouping to false so they will appear one atop the other, not next to one another.
Here's a screenshot of the output. I hope this is helpful!
Related
I know exactly how to enable legend in Highcharts, but the problem is how to create legends based on the value of the points from the same series since every legend is used to symbolize a series(a collection of points).
There's is a picture(chart type: waterfall) I draw in excel below illustrating what I want, you can see clearly that orange color legend stands for gaining, while blue one stands for loss, but how do I achieve this in Highcharts?
I've searched a lot but ended with disappointment, please help.
One way to do this is with a dummy series.
Create an extra series, with the name and color that you want, with an empty data array:
series: [{
name: 'Actual Series',
data: [...data, with points colored as needed...]
}, {
grouping: false,
name: 'Dummy Series',
color: 'chosen color',
data: []
}]
You'll also want to set grouping to false, so that the dummy series does not take up extra blank space on the plot.
Fiddle:
http://jsfiddle.net/jlbriggs/vjd3p4s0/
(also, the same thing using the Waterfall demo: http://jsfiddle.net/jlbriggs/7vtbzh53/ )
Another way to do this would be to create your own legend, outside of the chart.
Either way, you will lose the functionality of clicking the legend to show/hide the series of for the orange columns. You would have to build a more complex function to edit the data on legendItemClick if you that ability is important to you.
Solution for edited question. You can map your data to two series and set stacking to 'normal'.
const data = [10, 20, -10, 20, 10, -10];
const dataPositive = data.map(v => v >= 0 ? v : 0);
const dataNegative = data.map(v => v < 0 ? v : 0);
const options = {
chart: {
type: 'column'
},
series: [{
color: 'blue',
data: dataPositive,
stacking: 'normal'
}, {
color: 'orange',
data: dataNegative,
stacking: 'normal'
}]
}
const chart = Highcharts.chart('container', options);
Live example:
https://jsfiddle.net/j2o5bdgs/
[EDIT]
Solution for waterfall chart:
const data = [10, 20, -30];
const colors = Highcharts.getOptions().colors;
const options = {
chart: {
type: 'waterfall'
},
series: [{
// Single series simulating 2 series
data: data.map(v => v < 0 ? {
y: v,
color: colors[0]
} : {
y: v,
color: colors[3]
}),
stacking: 'normal',
showInLegend: false
}, {
// Positive data serie
color: colors[3],
data: [10, 20, 0],
visible: false,
stacking: 'normal',
showInLegend: false
}, {
// Negative data serie
color: colors[0],
data: [0, 0, -30],
visible: false,
stacking: 'normal',
showInLegend: false
}, {
// Empty serie for legend item
name: 'Series 1',
color: colors[3],
stacking: 'normal',
events: {
legendItemClick: function(e) {
const series = this.chart.series;
const invisibleCount = document.querySelectorAll('.highcharts-legend-item-hidden').length;
if (this.visible) {
if (invisibleCount === 1) {
series[0].hide();
series[1].hide();
series[2].hide();
} else {
series[0].hide();
series[2].show();
}
} else if (invisibleCount === 2) {
series[0].hide();
series[1].show();
} else {
series[0].show();
series[2].hide();
}
}
}
}, {
// Empty serie for legend item
name: 'Series 2',
color: colors[0],
stacking: 'normal',
events: {
legendItemClick: function(e) {
const series = this.chart.series;
const invisibleCount = document.querySelectorAll('.highcharts-legend-item-hidden').length;
if (this.visible) {
if (invisibleCount === 1) {
// hide all
series[0].hide();
series[1].hide();
series[2].hide();
return;
}
series[0].hide();
series[1].show();
} else {
if (invisibleCount === 2) {
series[0].hide();
series[2].show();
return;
}
series[0].show();
series[1].hide();
}
}
}
}]
}
const chart = Highcharts.chart('container', options);
Live example:
https://jsfiddle.net/2uszoLop/
I have a website which makes use of HighCharts Solid Gauge .
There are two rows of gauges.
The first row of gauges is built as follows.
var workgroups =['WG01','WG02','WG04',
'WG05','WG06','All'];
$(function ()
{
var gaugeOptions = {
chart: {
type: 'solidgauge'
},
title: 'Gauge',
pane: {
// Positioning
center: ['50%', '60%'],
// img size
size: '100%',
// full circle/half circle
startAngle: -90,
endAngle: 90,
// gauge coloring
background: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#000',
// Inner semi circle sizing
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
// Set the limits for coloring
[0.1, '#55BF3B'], // green
[0.4, '#DDDF0D'], // yellow
[0.9, '#DF5353'] // red
],
// Outside Line buffer
lineWidth: 0,
minorTickInterval: null,
tickPixelInterval: 400,
tickWidth: 0,
title: {
// Title Location
y: -30
},
labels: {
style:{
color: "#000000",
fontSize: "13px"
},
// Bottom Label Offset
y: 15,
distance: -10,
}
},
plotOptions: {
solidgauge: {
dataLabels: {
style:{
color: "000000",
fontSize: "15px"
},
borderWidth: 0,
useHTML: true
}
}
}
};
// The gauges
for( i in workgroups){
if(workgroups[i] == 'All'){
header = "All";
gaugeOptions.yAxis['stops'] = [[.5, '#000000']]
}else{
header = "WG" + workgroups[i].slice(-2);
}
$('#'+workgroups[i]).highcharts(Highcharts.merge(gaugeOptions, {
yAxis: {
min: 0,
max: 100,
title: {
style:{
color: "#000000",
fontWeight: 'bold',
fontSize: '22px'
},
text: header
}
},
credits: {
enabled: false
},
series: [{
name: workgroups[i],
data: [0],
dataLabels: {
y: 40,
format: '<div style="text-align:center"><span style="font-size:25px;color:' +
((Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black') + '">{y}</span><br/>' +
'<span style="font-size:12px;color:silver">clients</span></div>'
},
}]
}));
}
}
);
and results in the following image.
This is fine, proper values, all styles fit where they are supposed to.
After doing these gauges, we then do a second row of gauges.
The (Current) Configuration for these gauges are:
var application_array = new Array(3);
application_array['Sapphire'] = 50;
application_array['Magic Bullet'] = 35;
application_array['Boris'] = 30;
$(function ()
{
var gaugeOptions = {
chart: {
type: 'solidgauge'
},
title: 'Gauge',
pane: {
// Positioning
center: ['50%', '85%'],
// img size
size: '150%',
// full circle/half circle
startAngle: -90,
endAngle: 90,
// gauge coloring
background: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#000',
// Inner semi circle sizing
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
// Set the limits for coloring
[0.1, '#55BF3B'], // green
[0.4, '#DDDF0D'], // yellow
[0.9, '#DF5353'] // red
],
// Outside Line buffer
lineWidth: 0,
minorTickInterval: null,
tickPixelInterval: 400,
tickWidth: 0,
title: {
// Title Location
y: -30
},
labels:{
y:13
}
},
};
// Build the gauges here
var license_gauges = document.getElementsByClassName('gaugeCell2');
var myLength = license_gauges.length;
for (i=0; i <myLength; i++){
var header = license_gauges[i].id;
var selector = "[id='"+header+"']";
if (header == 'Boris'){
var max_value = 30;
}else if (header == 'Magic Bullet'){
var max_value = 35;
}else if (header == 'Sapphire'){
var max_value = 50;
}
console.log(header)
$(selector).highcharts(Highcharts.merge(gaugeOptions, {
yAxis: {
min: 0,
max: max_value,
title: {
style:{
color: "#000000",
fontWeight: 'bold',
fontSize: '22px'
},
text: header
}
},
credits: {
enabled: false
},
series: [{
name: header,
data: [0],
}]
}));
}
});
Which Produces the following BAD Gauges
My Question
1) In the second row of gauges, Why is it printing 25 as max for the 2nd and 3rd gauge?
- I have tried an associate array to hold the proper value, same issue occurs
I have tried a function which returns a static value, same issue occurs
I have tried logic in the gauge creation itself, same issue occurs
I have tried writing a static value as max, and all gauges get the proper value
2) In the second row of gauges, why is it that the max Value, for the second and third gauges is inconsistently formatted with the first gauge?
I have tried virtually every layout configuration I can think of, but yet it stays the same issue.
When Using a static max value, this issue does not occur.
Do I need to make an individual gaugeoption for each gauge since they have different max values? I would like to use 1 gauge style for the top row and 1 gauge style for the bottom row (fatter).
A JSFiddle has been created here. There is most likely extraneous code (especially css), as I wanted to get it up and running quickly.
http://jsfiddle.net/v341z7tk/1/
Thanks for reading
Why is it printing 25 as max for the 2nd and 3rd gauge?
It isn't. That is, the max isn't 25, but the drawn axis label shows the value 25, as there is an axis tick at this value. The max value is not showing with a label.
why is it that the max Value, for the second and third gauges is inconsistently formatted with the first gauge?
The position is inconsistent because the 25 label is in varying positions depending on what the max value is. In your case it is 35 and 30 for the last two gauges.
Do I need to make an individual gaugeoption for each gauge since they have different max values?
No. From my understanding you want a label at the start (0) and end (max_value). To get this you need to ensure that the axis ticks (which have associated labels) are at these positions, and only these.
A simple way is this (JSFiddle):
yAxis: {
min: 0,
max: max_value,
tickPositions: [0, max_value], // Ensure position of ticks, which have labels
// ...
}
I was having the same issue, but following what Halvor Strang said solved my problem like so
displayOptions.yAxis.min = widget.display.minimum;
displayOptions.yAxis.max = widget.display.maximum;
displayOptions.yAxis.tickPositions = [widget.display.minimum, widget.display.maximum];
distorted labels
- Minimum and maximum out of place
I've been doing this script for a volunteering university-site job.
Please ignore all parameters apart from wattages and schools. Those are SQL result sets that have been converted to arrays using json_encode(). Result sets have Strings as values, I believe, so both wattages and schools should be arrays of strings.
What I want to do is input my own data for the pie graph, in this case mySeries, which I build/fill up at the start and put as data later.
function createPieChartGradient(data,title,xlabel,ylabel,type,step,div_id,wattages,schools){
var float_watt = new Array();
for(var index = 0; index < wattages.length; index++)
{
float_watt[index] = parseFloat(wattages[index]).toFixed(2);
}
var mySeries = []; //Hopefully this creates a [String, number] array that can be used as Data.
for (var i = 0; i < float_watt.length; i++) {
mySeries.push([schools[i], float_watt[i]]);
}
var options = {
chart: {
renderTo: 'graph',
zoomType: 'x',
defaultSeriesType: type
},
title: {
text: 'Consumption Percentage of IHU Schools, Last 7 days'
},
tooltip: {
//pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
xAxis: {
categories: [],
tickPixelInterval: 150,
// maxZoom: 20 * 1000,
title: {
style: {
fontSize: '14px'
},
text: xlabel
},
labels: {
rotation: -45,
step: step,
align: 'right'//,
// step: temp
}
},
yAxis: {
title: {
style: {
fontSize: '14px'
},
text: ylabel
},
labels: {
align: 'right',
formatter: function() {
return parseFloat(this.value).toFixed(2);
}
},
min: 0
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'center',
floating: true,
shadow: true
},
series: [{
type: 'pie',
name: 'Consumption Percentage',
data: mySeries //Problematic line.
}] //Faculty with the smallest wattage -> Green.
}; //end of var options{} //Next: -> Yellow.
//Last -> Red.
//Draw the chart.
var chart = new Highcharts.Chart(options); //TODO: Change colours.
document.write("FINISHED");
}
The thing is, the above won't work. Since I'm not using an environment (writing in notepad++ and testing on my apache web server, via the results) I have manually aliminated the problematic line to be data: mySeries.
Any idea why that is? Aren't they the same type of array, [String, number]?
Additionally, are there any environments that will help me debug javascript programs? I'm really at my wit's end with this situation and I'd very much prefer to have an IDE tell me what's wrong, or at least point me at the right direction.
You see where you are calling "toFixed"? Let's run a small experiment:
var wattages = [2.0, 3.0];
var float_watt = new Array();
for(var index = 0; index < wattages.length; index++)
{
float_watt[index] = parseFloat(wattages[index]).toFixed(2);
}
console.log(JSON.stringify(float_watt));
The output is not what you expect:
["2.00", "3.00"]
See how it got converted to a string? If you delete the "toFixed" and let your formatter do its job, things will go just fine.
EDIT
Here's how you fix your formatter:
plotOptions: {
pie: {
dataLabels: {
formatter: function() {
return parseFloat(this.y).toFixed(2);
}
}
}
},
The yLabels formatter is doing nothing for the pie.
I am using highcharts to draw a column chart as following:
var chart;
var count = 0;
$(function () {
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'graph',
type: 'column',
margin: [ 50, 50, 100, 80]
},
title: {
text: 'Random Data'
},
xAxis: {
categories: [
'T1',
'T2'
],
startOnTick: true,
endOnTick: true,
labels: {
rotation: -45,
align: 'right',
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Y-Axis'
}
},
legend: {
enabled: false
},
tooltip: {
formatter: function() {
return '<b>'+ this.x +'</b><br/>'+
'Tip is: '+ Highcharts.numberFormat(this.y, 1);
}
},
series: [{
name: 'Population',
data: [34.4, 21.8],
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
x: 4,
y: 10,
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
});
});
});
I added the following function in order to add new points to the chart
function addPoints(name,acc)
{
var series = chart.series[0];
series.addPoint(acc, false, true);
categories = chart.xAxis[0].categories;
categories.push(name+count);
count++;
chart.xAxis[0].setCategories(categories, false);
chart.redraw();
}
The problem is that everytime I add a new point, one column shifts out of the chart. I would like to keep all columns in the chart view, so when I add a new point the chart just zooms out.
Check it on JSFiddle
Thanks in Advance ....
addPoint (Object options, [Boolean redraw], [Boolean shift], [Mixed animation])
Add a point to the series after render time.
Parameters
options: Number|Array|Object
The point options. If options isa single number, a point with that y value is appended to the series.If it is an array, it will be interpreted as x and y values respectively, or inthe case of OHLC or candlestick, as [x, open, high, low, close]. If it is an object, advanced options as outlined under series.data are applied.
redraw: Boolean
Defaults to true. Whether to redraw the chart after the point is added. When adding more thanone point, it is highly recommended that the redraw option beset to false, and instead chart.redraw() is explicitly calledafter the adding of points is finished.
shift: Boolean
Defaults to false. When shift is true, one point is shifted off the start of the series as one is appended to the end. Use this option for live charts monitoring a value over time.
animation: Mixed
Defaults to true. When true, the graph will be animated with default animationoptions. The animation can also be a configuration object with properties durationand easing.
series.addPoint(acc, false, true);
/\ here's the problem, it should be false
Reference
http://api.highcharts.com/highstock#Series
Updated demo
Not getting any errors from firebug. Not showing in any browser. Was working previously and stopped working about a week ago. Sample of the code...
$(document).ready(function () {
//Generic names for multiple graphs
var First = $('#hfFirstOrder').val().split(",");
var Second = $('#hfSecondOrder').val().split(",");
var Third = $('#hfThirdOrder').val().split(",");
var ticks = $('#hfDaysOrder').val().split(",");
var maxValue = parseInt($('#hfMaxOrder').val());
var FirstArray = [];
var SecondArray = [];
var ThirdArray = [];
for (i = 0; i < First.length; i++) {
FirstArray.push(parseInt(First[i]));
SecondArray.push(parseInt(Second[i]));
ThirdArray.push(parseInt(Third[i]));
}
plotGraph("stackedPurchase", [FirstArray, SecondArray, ThirdArray], true, ticks, "Orders", maxValue, '#000', "Completed",
'#00F', "Ship/Pick", '#F00', "Back Order");
function plotGraph(chartName, total, stackBool, tick, yLabel, maxValue, SC1, SL1, SC2, SL2, SC3, SL3) {
plot = $.jqplot(chartName, total, {
stackSeries: stackBool,
seriesDefaults: {
renderer:$.jqplot.BarRenderer,
rendererOptions: { barMargin: 20, barWidth: 10 },
showMarker: false,
pointLabels: { show: false }
},
axes: {
xaxis: {
label: "Days",
renderer: $.jqplot.CategoryAxisRenderer,
ticks: tick
},
yaxis: {
label: yLabel,
padMin: 0,
tickInterval: parseInt(maxValue * .1),
min: 0,
max: maxValue,
tickOptions: { formatString: '%d' }
}
},
series: [{ color: SC1, label: SL1 },
{ color: SC2, label: SL2 },
{ color: SC3, label: SL3 }
],
legend: {
show: true,
location: 'e',
placement: 'outside'
}
});
}
});
And then there's a call in the html for
<div id="stackedPurchase" style="height:450px;width:900px;" runat="server"></div>
And the various hidden values are csv strings from the code behind. According to firebug they are being passed in correctly (right formats and correct number of each variable). Judging from my coding experiences recently, its probably something obvious.
Got a partial answer, the first two graphs work now because someone else at work moved the folders that the jqplot stuff was in without informing me. Changing the address in the scripts at top fixed the problem.
But for some reason the third one isn't working.
plotGraph("graphQuote", [FirstArray, SecondArray, ThirdArray], false, ticks, "Quotes", maxValue, '#F00', "Request RFQ", '#00F', "RFQ", '#0F0', "Customer Quote");
SecondArray is all zero values, FirstArray is mostly zero and ThirdArray has a value in most of its fields. Ticks has correct dates.
Alright, found the problem. Apparently
parseInt(maxValue * .1)
gets pissy and returns 0 if maxValue is less than 10, and jqplot doesn't like 0 as a tick interval. Found a better way to do intervals and now everything works.