I have a chart where basically I want to set the alignment of the first/last labels on the x-axis to be left/right and any labels in between would be the default center. From what I can tell there is only a way to set the Labels.alignment property to apply to all labels and no clear way to individually align them
here is a before and after pic of what I am trying to achieve:
xAxis: {
title: {
enabled: false,
text: ''
},
crosshair: {
width: 2,
color: '#C4C4C4',
dashStyle: 'shortdot'
},
lineColor: 'transparent',
tickLength: 1,
labels: {
//overflow: 'justify',
step: 1,
formatter: function() {
console.log(this.value)
//if(this.value == 0 || this.value == 9)
return Highcharts.dateFormat("%b<br/>%Y", new Date(chartData.Dates[this.value]));
},
//align: 'center',
style: {
fontSize: '14px'
}
},
//tickPositions: [0,3,5,7,9]
},
any help would be appreciated, here is my working fiddle:
fiddle
You can use the render callback to find those labels and use the translate feature to move them.
chart: {
height: 300,
events: {
render() {
const xAxis = this.xAxis[0];
const ticksPositions = xAxis.tickPositions;
const ticks = xAxis.ticks;
const firstTickLabel = ticks[0].label;
const lastTickLabel = ticks[ticksPositions.length - 1].label;
firstTickLabel.translate(firstTickLabel.getBBox().width / 2, 0)
lastTickLabel.translate(-lastTickLabel.getBBox().width / 2, 0)
}
}
},
Demo: https://jsfiddle.net/BlackLabel/krL5ey1o/
API: https://api.highcharts.com/highcharts/chart.events.render
API: https://api.highcharts.com/class-reference/Highcharts.SVGElement#translate
Related
I have implemented a plot line that's showing an average of all values:
"yAxis": {
plotLines: [{
color: 'red',
value: 22,
width: '1',
label: {
text: 'Average: 22'
}
}]
},
I want to change the average-value on legendItemClick. Is it possible to change some plotLine-properties programatically?
What I tried so far is this:
plotOptions: {
series: {
events: {
legendItemClick: function (event) {
var average = 15;
event.target.chart.userOptions.yAxis.plotLines[0].value = average;
event.target.chart.userOptions.yAxis.plotLines[0].label.text = 'Average: ' + average;
}
},
}
},
The value and the label-text aren't changing in the chart. Also I tried to redraw the chart but it still isn't changing the plot line. Is there a way to accomplish this?
I now have found an acceptable answer to my own question:
var average = 15;
event.target.chart.yAxis[0].removePlotLine('average');
event.target.chart.yAxis[0].addPlotLine({
id: 'average',
color: 'red',
width: 1,
value: average,
zIndex: 200,
label: {
text: 'Average: ' + average
}
});
I have to specify an ID for the plotLine, destroy it and create a new one.
I would like to make something like a dashboard (kinda like the one that you see in many financial site), using Highcharts.
I've got the hang of adding 1 chart to a page, using a container, so I told myself that many containers, duplicating the code for one graph, will do; but I can't get it to work.
I have at least 8 graph, and I would like to organize them either in 2X4 arrangement, or just stacked on top of each other.
Mainly my confusion is coming from the fact that I need a general options section (to group common options), but I also need to customize the graphs, and I need to load data from CSV, so the order in which you do what, is causing me some problems.
I tried to follow an example here, where it was suggested to use setOptions and jQuery.extend, but I was not successful in making it work.
Is there an example that show a skeleton of the webpage, so I can see where to put each function, in which order and what kind of code do I have to put in?
Here you can find example how to add multiple chart like a dashboard: http://www.highcharts.com/demo/sparkline
And copy&paste code:
$(function () {
/**
* Create a constructor for sparklines that takes some sensible defaults and merges in the individual
* chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine').
*/
Highcharts.SparkLine = function (options, callback) {
var 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'
},
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: {
backgroundColor: null,
borderWidth: 0,
shadow: false,
useHTML: true,
hideDelay: 0,
shared: true,
padding: 0,
positioner: function (w, h, point) {
return { x: point.plotX - w / 2, y: point.plotY - h};
}
},
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 new Highcharts.Chart(options, callback);
};
var start = +new Date(),
$tds = $("td[data-sparkline]"),
fullLen = $tds.length,
n = 0;
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length;
for (i = 0; i < len; i++) {
var $td = $($tds[i]),
stringdata = $td.data('sparkline'),
arr = stringdata.split('; '),
data = $.map(arr[0].split(', '), parseFloat),
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('th').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
n++;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
// Print a feedback on the performance
if (n === fullLen) {
$('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms');
}
}
}
doChunk();
});
For a more simplistic start to this problem, take a look at this example:
http://jsfiddle.net/jlbriggs/4GaVj/
It's a very simple set up that defines data arrays first (you can do this as part of your CSV parsing), then defines global options via Highcharts.setOptions(), and then defines the individual charts.
There are several different ways to go about this, from this simple example up to more complex, flexible and dynamic approaches. But if you're looking to start with the basics, this should help.
How to make markers disabled while data > 1 after insert new data? It's really confusing me..
In this case, I want to make a Grow Chart (chart example source: CDC-Weight for age percentiles)
Should I use this?
if(dataChartWeight.length > 1)
{
chart.series[19].update({
marker: {
enabled: false
}
}, true);
}
if(dataChartLength.length > 1)
{
chart.series[18].update({
marker: {
enabled: false
}
}, true);
}
Sebastian's answer is good but it can become a little more complicated to fix if you are using multiple series, using a custom tooltip, or when the chart is redrawn. In stead of using destroy(); on the graphic, I used hide();
I wrapped it up in a function and then called the function on first load, and also on the redraw event. It loops through each series first, then loops through the data to "hide" the markers with zero as value.
$(function () {
function hideZeroDots(chart) {
$.each(chart.series, function (series) {
$.each(chart.series[series].data, function () {
if(this.y === 0 && this.graphic) {
this.graphic.hide();
}
});
});
}
$('#container').highcharts({
title: {
text: 'Hide Zero Dots'
},
chart: {
events: {
redraw: function () {
hideZeroDots(this);
}
}
},
tooltip: {
useHTML: true,
hideDelay: 0,
shared: true,
backgroundColor: '#fff',
borderColor: '#eee',
shadow: false,
crosshairs: {
width: 2,
color: 'gray',
dashStyle: 'shortdot'
}
},
series: [{
name: 'responses',
data: [0, 0, 0, 0, 0, 0, 36.5, 33.3, 0, 23.9, 0]
}, {
name: 'views',
data: [0, 0, 0, 0, 0, 0, 26.5, 23.3, 0, 13.9, 0]
}]
}, hideZeroDots);
});
See Demo
Generally marker cannot be disabled for single point, but you can use workaround with hiding SVG element.
$.each(chart.series[0].data, function (point, i) {
if(this.y <10) {
this.graphic.destroy();
}
});
See example: http://jsfiddle.net/Y5HzV/2/
Instead of trying to disable the marker, you can hide it...
marker: {
radius:0,
lineWidth:0,
}
The default highstock chart has height = 400px.
How can height chart be set for auto size based on chart axis and its sizes ?
See the example bellow, the navigation bar is over the volume panel.
http://jsfiddle.net/BYNsJ/
I know that I can set the height for the div but I have a solution that insert/remove axis/series dynamically in the chart and would be nice an auto height chart.
The example is the same Candlestick/Volume demo from Highchart site, but without height property in the div container.
// split the data set into ohlc and volume
var ohlc = [],
volume = [],
dataLength = data.length;
for (i = 0; i < dataLength; i++) {
ohlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
])
}
// set the allowed units for data grouping
var groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]];
// create the chart
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Historical'
},
yAxis: [{
title: {
text: 'OHLC'
},
height: 200,
lineWidth: 2
}, {
title: {
text: 'Volume'
},
top: 300,
height: 100,
offset: 0,
lineWidth: 2
}],
series: [{
type: 'candlestick',
name: 'AAPL',
data: ohlc,
dataGrouping: {
units: groupingUnits
}
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
}
}]
});
});
});
Regards.
here is one example which is resize chart according screen.
http://jsfiddle.net/davide_vallicella/LuxFd/2/
Just don't set the height property in HighCharts and it will handle it dynamically for you so long as you set a height on the chart's containing element. It can be a fixed number or a even a percent if position is absolute.
http://api.highcharts.com/highcharts/chart.height
By default the height is calculated from the offset height of the containing element
find example here:- http://jsfiddle.net/wkkAd/149/
#container {
width:100%;
height:100%;
position:absolute;
}
hey I was using angular 2+ and highchart/highstock v.5, I think it will work in JS or jQuery also, here is a easy solution
HTML
<div id="container">
<chart type="StockChart" [options]="stockValueOptions"></chart>
</div>
CSS
#container{
height: 90%;
}
TS
this.stockValueOptions = {
chart: {
renderTo: 'container'
},
yAxis: [{
height: '60%'
},{
top: '65%',
height: '35%'
}]
}
Its working, and a easy one. Remove chart height add height in '%' for the yAxis.
Highcharts does not support dynamic height, you can achieve it by $(window).resize event:
$(window).resize(function()
{
chart.setSize(
$(document).width(),
$(document).height()/2,
false
);
});
See demo fiddle here.
You can set chart.height dynamically with chart.update method.
http://api.highcharts.com/highcharts/Chart.update
function resizeChartFromValues (chart) {
const pixelsForValue = 10
const axis = chart.yAxis[0]
chart.update({ chart: { height: (axis.max - axis.min) * pixelsForValue } })
}
const options = {
chart: {
events: {
load () {resizeChartFromValues(this)}
}
},
series: [{
data: [30, 70, 100],
}]
}
const chart = Highcharts.chart('container', options)
setTimeout(() => {
chart.series[0].setData([10, 20, 30])
resizeChartFromValues(chart)
}, 1000)
Live example: https://jsfiddle.net/a97fgsmc/
I had the same problem and I fixed it with:
<div id="container" style="width: 100%; height: 100%; position:absolute"></div>
No special options to the chart. The chart fits perfect to the browser even if I resize it.
I can change the marker color based on if it's above (red) or below (green) or between (yellow), but cannot change the color of the line in between the markers. Is this possible? Right now, it just displays as a blue line.
function makeRun(divId, last, current, goal, title, yAxisTitle) {
var width = 1000; var SizeOfFont = '14px';
var min = checkMinMaxArray(current, last, goal, 'min') * 995 / 1000; //sets min closely below the real min. **consider changing to 4/5 digits**
var max = checkMinMaxArray(current, last, goal, 'max') * 1005 / 1000; //sets max closely above the real max
//if there are projections, color code the columns here
preprocessData = function (data, last, goal) {
var nData = [];
var colorGood = 'green'; var colorBad = '#E42217'; var colorUse;
for (var i = 0; i < data.length; i++) {
if (data[i] <= goal[i]) { colorUse = colorGood; }
else if (data[i] > last[i]) { colorUse = colorBad; }
else { colorUse = '#FFE303'; }
nData.push({
y: data[i],
x: i,
fillColor: colorUse,
color: colorUse
});
}
return nData;
};
var chart = new Highcharts.Chart({
chart: {
renderTo: divId,
height: 275, //little bigger than alotted height to make more readable
width: width //dependent on #gauges
},
title: {
text: title, //should all be the same, can make a parameter if need to be different
style: { //size of text above
fontSize: SizeOfFont
}
},
xAxis: {
//categories: xAxisTitles,
labels: { //size of the Text above^^
style: {
fontSize: SizeOfFont
}
}
},
yAxis: {
min: min,
max: max,
title: {
text: yAxisTitle, //parameter since some are days, percents, etc
style: {//size of y axis title
fontSize: SizeOfFont
}
},
labels: {
style: {//size of the y axis tick labels
fontSize: SizeOfFont
}
}
},
credits: {//gets rid of the highcharts logo in bottom right
enabled: false
},
legend: {//the legend at the bottom
style: {
fontSize: '12px'
}
},
series: [{
type: 'spline',
name: '2012',
data: last,
color: 'orange',
marker: {
symbol: 'diamond'
}
}, {
type: 'spline',
name: '2013',
data: preprocessData(current, last, goal),
marker: {
symbol: 'diamond'
}
}, {
type: 'spline',
name: 'Goal',
data: goal,
color: 'blue',
marker: {
symbol: 'diamond'
}
}]
});
}
It is not possible in one serie, you should prepare two separate serie with different colors.