how to add extra labels at load event in highcharts - highcharts

Code is as below
chart: {
type: "funnel",
marginBottom: 25,
backgroundColor: "transparent",
events: {
load: function() {
var chart = this;
Highcharts.each(chart.series[0].data, function(p, i) {
chart.options.labels.items.push({
html: "less confident" + i,
style: { left: 550, top: 50 }
});
p.dataLabel.attr({
x: (chart.plotWidth - chart.plotLeft) / 2,
"text-anchor": "middle"
});
});
}
}
},

I see that you're trying to add a label for every point. Highcharts has build in functionality for this called data labels: https://api.highcharts.com/highcharts/series.line.dataLabels
Another approach is to use SVGRenderer.label: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#label

Related

How to set alignment of individual x-axis labels in Highcharts

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

xAxis Image Disappears in Highcharts After First Refresh

I have a page with a variety of select menus. The select options are used in an ajax call to build a Highcharts bar graph. Every time a filter changes, the graph gets recreated. I did this instead of updating the series data, because in the past I have noticed that destroying and recreating was more efficient than updating.
I want images to show on the x-axis, so I used a nice little trick of creating two x axes, used formatter to return an image on the first axis, and linked the second axis to the first. This works on first refresh. However, every time the chart gets recreated thereafter, the image disappears. I checked my console and I don't see any errors.
And idea of what's going on here?
/**
* Whenselection changes
*/
$(document).on('change', '.filter', function(){
getChartData($params)
})
});
/**
* API call to get data that will populate charts.
* #param {obj} params
*/
function getChartData(params)
{
//Get chart data
$.ajax({
url: apiURL + '/chartdata/',
data: params,
dataType: 'json',
cache: false,
success: function(data) {
initChart(data[0]);
}
});
function initChart(chartData)
{
var chart = Highcharts.chart('container', {
chart: {
type: 'bar',
backgroundColor: 'transparent', //#E8EAF6',
height: '23%',
marginLeft: 35
},
title: {
text: null
},
xAxis: {
categories: [category1, category2],
lineColor: 'transparent',
min: 0,
tickColor: 'transparent',
title: {
text: null
},
labels: {
x: -35,
useHTML: true,
overflow: 'allow',
formatter: function () {
if(this.isFirst == true)
return '<img src="../assets/img/nat-jr-grad-gold.png"><br/>';
else
return '<img src="../assets/img/nat-jr-grad-purple.png"><br/>';
}
}
},
yAxis: {
min: 0,
title: {
useHTML: true,
text: null
},
labels: {
enabled: false
},
lineWidth: 0,
minorGridLineWidth: 0,
gridLineWidth: 0,
lineColor: 'transparent',
gridLineColor: 'transparent',
},
legend: {
enabled: false
},
series: [{
name: category1,
data: [{name: category1, y:Math.round(chartData.p_grad_nongap * 100), {y: null}],
}, {
name: category2,
data: [null, {name: category2, y: Math.round(chartData.p_grad_gap * 100)}]
}]
});
}
I reproduced your problem on a simplified example: http://jsfiddle.net/BlackLabel/sm2r684n/
For the first time, the image is loaded asynchronously and the chart does not take it into account when calculating the margins. Every next time the result is different, so you should wait until the picture is loaded:
var img = new Image();
img.onload = function() {
initChart();
}
img.src = "https://www.highcharts.com/samples/graphics/sun.png";
Live demo: http://jsfiddle.net/BlackLabel/m09ok2cg/
I think ppotaczek had the cortrect root cause of the problem; the image is loaded asynchronously and the chart does not take it into account when calculating the margins. His suggestion used setTimeout function to continuously redraw the graph, which is rather inefficient. My work-around for this was to just add the images as avg elements using chart.renderer after the chart was created.
/* Render X-Axis images */
chart.renderer.image('../assets/img/img1.png', 0, 40, 32, 36)
.css({
class: 'icon-img',
zIndex: 10
})
.add();
chart.renderer.image('../assets/img/img2.png', 0, 130, 32, 36)
.css({
class: 'icon-img',
zIndex: 10
})
.add();

Can you make an eeg chart with highchart?

We are going to buy a high chart.
We are going to implement the medical chart eeg chart on the web.
Can I implement the shape of an eeg chart with a high chart?
The EEG chart shows that the X axis is time and the Y axis
It has 19 channels with individual ranges.
https://www.researchgate.net/figure/Case-6-EEG-in-a-38-year-old-woman-with-refractory-complex-partial-seizures-and-left_fig3_233806823
By using Highcharts, you can create as many axes as you need. I have prepared a simple example with multiple yAxes and different ranges:
var series = [],
data,
seriesCount = 20,
pointsCount = 100,
axisTop = 50,
range,
axisHeight = 1100 / seriesCount,
yAxis = [];
for (var i = 0; i < seriesCount; i++) {
range = Math.round(Math.random() * 100);
data = [];
for (var j = 0; j < pointsCount; j++) {
data.push(Math.floor(Math.random() * range));
}
series.push({
data: data,
yAxis: i
});
yAxis.push({
title: {
text: ''
},
height: axisHeight,
top: axisTop,
offset: 0
});
axisTop += axisHeight + 12.5
}
Highcharts.chart('container', {
chart: {
height: 1500
},
series: series,
yAxis: yAxis
});
Live demo: http://jsfiddle.net/BlackLabel/425xctvw/
You can try for synchronized charts where x axis can be common across all the graphs.
https://www.highcharts.com/demo/synchronized-charts
Reference Code: https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/demo/synchronized-charts/
/*
The purpose of this demo is to demonstrate how multiple charts on the same page
can be linked through DOM and Highcharts events and API methods. It takes a
standard Highcharts config with a small variation for each data set, and a
mouse/touch event handler to bind the charts together.
*/
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
$('#container').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
// Find coordinates within the chart
event = chart.pointer.normalize(e.originalEvent);
// Get the hovered point
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and
* crosshairs.
*/
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
Highcharts.Point.prototype.highlight = function (event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(
e.min,
e.max,
undefined,
false,
{ trigger: 'syncExtremes' }
);
}
}
});
}
}
// Get the data. The contents of the data file can be viewed at
$.getJSON(
'https://cdn.rawgit.com/highcharts/highcharts/057b672172ccc6c08fe7dbb27fc17ebca3f5b770/samples/data/activity.json',
function (activity) {
$.each(activity.datasets, function (i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function (val, j) {
return [activity.xData[j], val];
});
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} min'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
positioner: function () {
return {
// right aligned
x: this.chart.chartWidth - this.label.width,
y: 10 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
}
);
.chart {
min-width: 320px;
max-width: 800px;
height: 220px;
margin: 0 auto;
}
</style>
<!-- http://doc.jsfiddle.net/use/hacks.html#css-panel-hack -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>

How to place ranking like top 10 and put x axis labels on right of horizontal bar chart?

Current Chart
xAxis: {
categories: ['Africa', 'America', 'Asia', 'Europe', 'Oceania'],
title: {
text: null
},
labels: {
x : 25,
align: 'left'
}
},
My Script in here
http://jsfiddle.net/puff0211/dtcLn8sm/14/
Desired Chart
Does anyone know to accomplish this?
Thank you!
One of the solutions here is to slightly change the position of both axes via left property (it's not documented but it works) and create additional labels using SVG Renderer. chart.events.load is a good place for it because when it launches ticks values and positions are already computed - we can use them to create additional labels:
load: function() {
var ticks = this.xAxis[0].ticks,
renderer = this.renderer;
for (var prop in ticks) {
var t = ticks[prop];
if (t.label) {
var coords = t.label.xy,
label = renderer.text(t.pos + 1, coords.x - additionLabelsOffset, coords.y).add();
}
}
}
(...)
xAxis: {
left: axesOffset
(...)
},
yAxis: {
left: axesOffset
(...)
}
Live demo: http://jsfiddle.net/kkulig/cq2otgr1/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text
My solution is simple.
Let chart margin keep width with left lable.(api use chart.margin)
Allow X Axis can display 2 lable. (api use useHTML and formatter )
Code:
chart: {
type: 'bar',
margin: [ 0, 0, 70, 70]
},
{...},
xAxis: {
labels: {
x : 0,
align: 'left',
useHTML: true,
formatter: function() {
return '<div style="position: relative; top: 0px; right: 50px"> No. '+ (this.pos + 1) +'</div>\
<div style="position: absolute; top: 0px; left: 20px"><b>'+ this.value +'</div>';
}
}
Live demo: http://jsfiddle.net/puff0211/pv84nLub/
API Reference:
https://api.highcharts.com/highcharts/chart.margin
https://api.highcharts.com/highcharts/xAxis.labels.useHTML
https://api.highcharts.com/highcharts/xAxis.labels.formatter

Auto chart height

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.

Resources