Highcharts dynamically move dataLabel if it doesnt fit - javascript

Hi I am trying to present the columns values at the top of each column so it is easier for the user to compare values.
I have got this working but when some columns are very close to each other some of the values aren't being dispalyed because I'm presuming highcharts works out that it wqouldnt fit unless it overlapped so it doesnt show the value.
Here is the code for my chart -
var chart_1_Options = {
chart: {
renderTo: 'container_chart_1',
backgroundColor: '#FFFFFF'
},
credits: {
enabled: false
},
title: {
text: ''
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: null
}
},
plotOptions: {
column: {
animation: false,
borderWidth: 0,
dataLabels: {
enabled: true,
formatter: function() {
return '<p style="font-size: 8px;">' + this.y + '% </p>';
}
}
}
},
legend: {
enabled: true
}
};
Here is an image of what the chart looks like, I have circled areas where the value is missing
I just want the value to show even if it can't fit, I want it to place the value somewhere inside the column if it cant fit at the top.
Thanks for any help!

I think that you can try to find those labels and show them by doing something like code below:
events: {
load() {
let chart = this;
chart.series[0].points.forEach(p => {
setTimeout(function() {
if (p.dataLabel.translateY === -9999) {
p.dataLabel.translate(p.dataLabel.alignAttr.x, p.dataLabel.alignAttr.y + 20)
p.dataLabel.css({
opacity: 1
})
}
}, 50)
})
}
}
Demo: https://jsfiddle.net/BlackLabel/unzgsmfr/
API: https://api.highcharts.com/highcharts/chart.events.load

Related

Changing tootip data on pie chart in highcharts

I have been trying to edit the pie chart on this website using the config method:
Change colours (working)
Show legend (working)
Click legend to activate chart section (working)
Donut sizing (working)
Tooltip different data (not working)
Legend showing percentages (not working)
I can't, for the life of me, get the legend to show the percentages and I can't get the tooltip data to change.
Currently, the tooltip says, for example:
Australian equities
Percentage: 40%
I need the tooltip to say:
Australian equities: 40%
Currently, the legend says, for example:
Australian equities
I need the legend to say:
40% Australian equities
<script type="text/javascript">
jQuery(window).on('load',function(){
if( typeof wpDataChartsCallbacks == 'undefined' ){ wpDataChartsCallbacks = {}; }
wpDataChartsCallbacks[1] = function(obj){
obj.options.plotOptions = {
series: {
dataLabels: {
enabled: false
}
},
pie: {
colors: [
'#006769',
'#00b8af',
'#28c3e8',
'#0ee4da',
'#2a97a6'
],
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
size: 340,
innerSize: '50%',
showInLegend: true,
point: {
events: {
legendItemClick: function () {
this.select();
return false;
}
}
}
},
tooltip: {
formatter: function() {
return this.point.name + ': <b>' + Highcharts.numberFormat(this.y, 1) +'%</b>';
}
},
legend: {
labelFormatter: function() {
return '<strong style="display:inline-block;width:45px;">'+Highcharts.numberFormat(this.y, 1) +'%</strong> ' + this.name ;
},
title: {
style: {
fontSize: '18px',
fontFamily: "'neuzeit-grotesk', sans-serif",
color: '#20242b'
},
text : 'By industry'
},
squareSymbol: true,
},
};
};
});
</script>
This chart is feeding from a locally stored excel spreadsheet to reflect live data which is why the config method must be used.
I have read other threads and the highcharts forums but when I copy the codes into the above it still doesn't change the legend and tooltop.
Any help would be greatly appreciated.
You should implement legend and tooltip configuration on the highest level:
{
...,
tooltip: {
formatter: function() {
...
}
},
legend: {
labelFormatter: function() {
...
},
...
}
}
Live demo: http://jsfiddle.net/BlackLabel/9sp4m1cf/
API Reference:
https://api.highcharts.com/highcharts/tooltip.formatter
https://api.highcharts.com/highcharts/legend.labelFormatter

How to get values from all the charts in the tooltip you are currently hovering

I am using Highcharts in the vue.js environment. I use https://www.highcharts.com 7.2.0 and Highcharts-Vue https://github.com/highcharts/highcharts-vue#readme 1.3.5.
I have multiple highstock charts in the same page. I am trying to get the values from all the charts into the tooltip of the highstock that I am currently hovering.
Based on this http://jsfiddle.net/mjsdnngq/14/ I am trying to create my code
This is what I have now
vue template
<template>
<div class="vessChart" v-on:mousemove="updateCoordinates" >
<v-card :loading=!this.getStreamPlots.done>
<highcharts ref="chart" :constructor-type="'stockChart'" :callback="chartcallback" :options="options" ></highcharts>
</v-card>
</div>
</template>
This is the "options" as I define it for the chart as a vue data object
options: {
tooltip: {
shared: true,
pointFormat: '{series.name}: {point.y}<br>'
},
chart: {
type: "line",
zoomType: 'x'
},
title: {
text: this.streamChart.title
},
rangeSelector: {
inputEnabled: false
},
xAxis: {
ordinal: false,
type: 'datetime',
tickInterval: 5 * 60 * 1000 ,
labels: {
enabled:false
},
events : {
afterSetExtremes : this.afterSetExtremes
}
},
yAxis: {
title: {
text: this.streamChart.title
},
labels: {
enabled:true
},
alignTicks:'left',
textAlign:'left',
align:'middle',
opposite:false
},
plotOptions: {
series: {
animation: false
}
},
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
chart: {
height: 300
},
subtitle: {
text: null
},
navigator: {
enabled: false
},
legend: {
enabled: true
},
yAxis: {
title: {
enabled: false
}
}
}
}]
},
series: [
{
name: this.streamChart.title,
pointStart: 1546300800000,
pointInterval: 5 * 60 * 1000
}
]
},
when the Highstock loads, I use callback, to get it and set it as a local vue var and also push it in an array in the vuex store, so I can have all charts available.
chartcallback(hc){
this.chart=hc;
this.currentId = this.streamChart.id;
this.chartData = this.chartData.concat(this.getStreamPlots[this.currentId].data);
this.addStreamCharts(hc); //push it to an array in vuex store
this.chart.series[0].setData(this.chartData, true, true, true);
},
and then I use the updateCoordinates to get all the values from all the charts I saved in vuex store, using the searchPoint. Then, feed the values to the tooltip of the chart I am currently hovering
updateCoordinates(e){
if (this.getStreamPlots.done && this.chart != null) {
let hce = this.chart.pointer.normalize(e);
let points=[];
this.getStreamCharts.forEach(chart => {
let point = chart.series[0].searchPoint(hce, true);
points.push(point);
});
this.chart.tooltip.refresh(points);
}
}
Problems :
1- This works but it shows all the values to the first chart I hovered. For example, I hover to the first chart, I get all the values into the tooltip as I should. But then I hover to the third chart and the values are still showed in the first chart tooltip. No tooltip in the third chart.
2- The values are in different tooltips. I would like for all the values be in one tooltip. (check the image)
Thank you

Dynamic update multible series Highcharts with single point XML file

I am a bit out of my comfort zone, since I normally do analytics and not fancy front-ends. However, I would like to have a real-time demo of some of my work, so it becomes easier to understand and not just numbers in a matrix. I have looked around and found something semi-relevant and come this far:
(It has four series like I want to and it iterates - to some degree)
https://jsfiddle.net/023sre9r/
var series1 = this.series[0],
series2 = this.series[1],
series3 = this.series[2],
series4 = this.series[3];
But I am totally lost on how to remove the random number generators without loosing nice things like the number of data points in a view (seems to depend on the for loop?!). Remove the extra title "Values" right next to my real y-axis title. And of cause how to get a new data point from a XML-file every second.
Ideally I want to have an XML-file containing 4 values, which I update approximately every 200ms in MATLAB. And every second I would like my 4 series chart to update. Is it not relatively easy, if you know what you are doing?! :-)
Thanks in advance!
I simplified your example and added clear code showing how to fetch data from server and append it to your chart using series.addPoint method. Also if you want to use XML, just convert it to JS object / JSON.
const randomData = () => [...Array(12)]
.map((u, i) => [new Date().getTime() + i * 1000, Math.random()])
Highcharts.chart('container', {
chart: {
renderTo: 'container',
type: 'spline',
backgroundColor: null,
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load () {
const chart = this
setInterval(() => {
// Fetch example below (working example: https://github.com/stpoa/live-btc-chart/blob/master/app.js)
// window.fetch('https://api.cryptonator.com/api/ticker/btc-usd').then((response) => {
// return response.json()
// }).then((data) => {
// chart.series[0].addPoint({ x: data.timestamp * 1000, y: Number(data.ticker.price) })
// })
chart.series.forEach((series) => series.addPoint([new Date().getTime(), Math.random()], true, true))
}, 3000)
}
}
},
title: {
text: null
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: [{
title: {
text: 'Temperature [°C]',
margin: 30
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
}, {
}],
tooltip: {
formatter: function() {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' + Highcharts.numberFormat(this.y, 4);
}
},
legend: {
enabled: true
},
exporting: {
enabled: false
},
rangeSelector: {
enabled: false
},
navigator: {
enabled: false
},
scrollbar: {
enabled: false
},
series: [{
name: 'Setpoint',
data: randomData()
}, {
name: 'Return',
data: randomData()
}, {
name: 'Supply',
data: randomData()
}, {
name: 'Output',
data: randomData()
}]
})
Live example: https://jsfiddle.net/9gw4ttnt/
Working one with external data source: https://jsfiddle.net/111u7nxs/

Unable to USE tooltips when viewing svg code

I've searched around for several days and have not been able to find a solution to this issue. I'm generating highcharts with not problem. Inaddition, I'm using the below simple function to get the svg code for each chart.
function generateSVG (){
var svg_xml = $('#container').highcharts().getSVG();
document.getElementById('svg_code').innerHTML = svg_xml;
}
My issue is that with the chart originally generated by highcharts I am able to mouseover the chart and see tooltips. However, when I later embed the generated svg code, even with including all the external resources, the tooltips do not work - everything becomes like a static image. After inspecting the svg code extracted next to the code used to generate the initial chart, I noticed that the line of code which includes the tooltip class for highcharts was missing in the extracted code. Am I missing something here. Below is an example of one of the functions used to generate a chart.
function highArea(theD){
setHighSize();
var theData = theD;
$.get(theData, function(data) {
Highcharts.chart('chartDisplay', {
colors: ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff"],
chart: {
type: "area",
useHTML: true
},
exporting: {
buttons: {
contextButton: {
enabled: false
}
}
},
title: {
text: chart_title
},
data: {
csv: data
},
title: {
text: chart_title
},
subtitle: {
text: ''
},
xAxis: {
allowDecimals: false,
labels: {
formatter: function () {
return this.value;
}
}
},
yAxis: {
title: {
text: some_label
},
},
tooltip: {
pointFormat: '{series.name} <b>{point.y:,.0f}</b><br/> {point.x}'
},
plotOptions: {
area: {
marker: {
enabled: true,
symbol: 'circle',
radius: 2,
states: {
hover: {
enabled: true
}
}
}
}
}
});
generateSVG();
});
}
Is what I'm trying to do even possible? I would really appreciate any feedback on this matter.
Thanks :)

How to display several labels in Highchart.js?

I have basic Waterfall chart (HighChart.js) basic Waterfall chart image example
How display two labels on each column? Besides, first label must be at top of column and another label must be on bottom of column. So it should be exactly like on image.
Now I have two ideas:
First label is rendered on first chart, second value will be rendered on additional hidden chart (link to example: [http://jsfiddle.net/gk14kh3q/1/][3])
$(function () {
$('#container').highcharts({
chart: {
type: 'waterfall'
},
title: {
text: 'Highcharts Waterfall'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'USD'
}
},
legend: {
enabled: false
},
series: [{
dataLabels: {
enabled: true,
// here need align label
}
}, {
dataLabels: {
enabled: true,
// here need align label
}
}]
});
});
Combine two label in one by using formatting function and useHTML property. And after that set position to labels by using css or external js
May be some others practices exist? I'll be very pleased for help. Even discussion can be usefull. Thank you!
P.S. How I could insert icons to chart like on provided image?
You can use chart.renderer.label for adding new dataLabels for your column points. You can also use chart.renderer.image for adding arrows to your chart:
var addLabels = function(chart) {
$('.custom').remove();
var series = chart.series[0],
url;
Highcharts.each(series.data, function(p, i) {
if (i) {
chart.renderer.label(p.secondLabel, p.plotX + chart.plotLeft, p.yBottom + chart.plotTop).attr({
'text-anchor': 'middle'
}).addClass('custom').add();
if (p.y > 0) {
url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Arrow_up.svg/1000px-Arrow_up.svg.png';
} else {
url = 'https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png'
}
chart.renderer.image(url, p.plotX + chart.plotLeft, chart.plotTop + chart.plotHeight - 15, 8, 13).addClass('custom').add()
}
});
};
Here you can find an example how it can work:
http://jsfiddle.net/zc2fb8vt/

Categories