I am using the columnrange type from Highcharts-more.
The default data labels formatter puts the min / max data at both ends of the range, which is nice.
Is there a way to attach another label to each point? (for example : the data name, right in the middle of the bar)
Please see my work at:
JSFiddle
This is a family tree with life ranges.
I'd like to display the names shown in tooltips at the center of bars.
(FYI I tried to overload the chart with text using the renderer : it worked... but the texts were attached to the chart, not to the points, and zooming left them in place, while the points moved around. Is there maybe a way to attach text labels to the each point on the chart onLoad event?)
Thank you.
$(function () {
$('#container').highcharts({
chart: {
type: 'columnrange',
inverted: true,
marginLeft: 40,
zoomType: 'xy'
},
title: {
text: 'My family tree'
},
xAxis: {
labels: {
enabled: false
},
min: 0,
max: 10
},
yAxis: {
type: 'datetime',
min: new Date().setYear(1900).valueOf(),
max: new Date().valueOf(),
title: {
text: 'Year'
},
endOnTick: false
},
legend: {
enabled: false
},
plotOptions: {
columnrange: {
grouping: false,
pointPadding: 0,
dataLabels: {
enabled: true,
useHTML: true,
formatter: function () {
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.y).setHours(0, 0, 0, 0)) return '<span style="color:black">' + Highcharts.dateFormat('%Y', this.y) + '</span>';
else return '';
}
}
}
},
tooltip: {
headerFormat: '{series.name}<br/>',
formatter: function () {
var l = this.point.name + '<br/>' + Highcharts.dateFormat('%e/%m/%Y', this.point.low);
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.point.high).setHours(0, 0, 0, 0)) l += '<br/>' + Highcharts.dateFormat('%e/%m/%Y', this.point.high);
return l;
}
},
series: [{
color: 'rgb(100,100,255)',
pointWidth: 150,
data: [{
name: 'Yann B',
low: Date.UTC(1976, 1, 27),
high: new Date().valueOf(),
x: 1 * 10 / 2
}]
}, {
color: 'rgb(150,150,255)',
pointWidth: 70,
data: [{
name: 'Jean-Yves B',
low: Date.UTC(1947, 3, 26),
high: Date.UTC(2006, 2, 10),
x: 1 * 10 / 4
}, {
name: 'Josiane M',
low: Date.UTC(1946, 8, 21),
high: Date.UTC(1998, 11, 26),
x: 3 * 10 / 4
}]
}, {
color: 'rgb(200,200,255)',
pointWidth: 30,
data: [{
name: 'Guillaume B',
low: Date.UTC(1907, 7, 4),
high: Date.UTC(1988, 1, 11),
x: 1 * 10 / 8
}, {
name: 'Marie-Jeanne S',
low: Date.UTC(1911, 7, 17),
high: Date.UTC(1986, 2, 3),
x: 3 * 10 / 8
}, {
name: 'Joseph M',
low: Date.UTC(1921, 3, 11),
high: Date.UTC(1996, 4, 23),
x: 5 * 10 / 8
}, {
name: 'Marie K',
low: Date.UTC(1925, 4, 4),
high: new Date().valueOf(),
x: 7 * 10 / 8
}]
}]
});
});
The use of the "inside" propriety is indeed relevant here. But I had to bypass the bug inherent to its use (see comment to last answer).
Here is a piece of code that works for datalabels. There still is a zIndex issue with the tool tips, and I'll try to post a more complete solution soon.
http://jsfiddle.net/SineDie/TREwr/1/
dataLabels: {
inside: true,
enabled: true,
useHTML: true,
formatter: function () {
if (this.y === this.point.low) {
var l = '<div style="text-align:center;color:black;width:' + (this.point.plotLow - this.point.plotHigh) + 'px">'
+ Highcharts.dateFormat('%Y', this.point.low) + ' - '
+ this.point.name;
// to avoid marking as dead if still living...
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.point.high).setHours(0, 0, 0, 0))
l += ' - ' + Highcharts.dateFormat('%Y', this.point.high);
l += '</div>';
return l;
}
else return '';
}
}
I did some modifications on formatter funcution. set datalabels inside property true and attach datanames to point's high values.
dataLabels: {
inside:true,
enabled: true,
useHTML: true,
formatter: function () {
if (new Date().setHours(0, 0, 0, 0) !== new Date(this.y).setHours(0, 0, 0, 0)) {
if (this.y == this.point.high){
return '<span style="color:black">' + Highcharts.dateFormat('%Y', this.y) +' - '+ this.point.name + '</span>';
}
return '<span style="color:black">' + Highcharts.dateFormat('%Y', this.y) + '</span>';
}
else return '';
}
}
Related
I need to change the series color to uniformly be green and when the data range is high ,say I have data from Oct 2018 to Sep 2021 for one data point and the other data is Aug 20 2021 to Aug 22 2021,
the latter looks very small and barely noticeable . At this instance I want to set the minimum width and shape to the smallest data point in advanced accessible graph. How do I do that.
Any suggestion is appreciated
Image1
Image2
Code:function DrawRemoteRequestPSRChart(seriesData, yAxisCategories) {
// Define custom series type for displaying low/med/high values using boxplot as a base
Highcharts.seriesType('lowmedhigh', 'boxplot', {
keys: ['low', 'high'],
tooltip: {
}
}, {
// Change point shape to a line with three crossing lines for low/median/high
// Stroke width is hardcoded to 1 for simplicity
drawPoints: function () {
var series = this;
this.points.forEach(function (point) {
var graphic = point.graphic,
verb = graphic ? 'animate' : 'attr',
shapeArgs = point.shapeArgs,
width = 0,
left = Math.floor(shapeArgs.x) + 0.5,
right = left + width,
crispX = left + Math.round(width / 2) + 0.5,
highPlot = Math.floor(point.highPlot) + 0.5,
// Sneakily draw low marker even if 0
lowPlot = Math.floor(point.lowPlot) +
0.5 - (point.low === 0 ? 1 : 0);
if (point.isNull) {
return;
}
if (!graphic) {
point.graphic = graphic = series.chart.renderer
.path('point')
.add(series.group);
}
graphic.attr({
stroke: point.color || series.color,
"stroke-width": 4
});
graphic[verb]({
d: [
'M', left, highPlot,
'H', right,
'M', left, lowPlot,
'H', right,
'M', crispX, highPlot,
'V', lowPlot
]
});
});
}
});
// Create chart
var chart = Highcharts.chart('container', {
chart: {
type: 'lowmedhigh',
inverted: true
},
credits: {
enabled: false
}, legend: {
enabled: false
},
title: {
text: 'Daily company fruit consumption 2019'
},
tooltip: {
shared: false, formatter: function () {
return this.point.category + ', ' + new Date(this.point.options.low).toGMTString() +
' to ' + new Date(this.point.options.high).toGMTString() + '.';
}
},
accessibility: {
point: {
descriptionFormatter: function (point) {
var ix = point.index + 1,
category = point.category,
from = new Date(point.low),
to = new Date(point.high);
return ix + '. ' + category + ', ' + from.toDateString() +
' to ' + to.toDateString() + '.';
}
},
typeDescription: 'Low, high. Each data point has a low and high value, depicted vertically as small ticks.' // Describe the chart type to screen reader users, since this is not a traditional boxplot chart
},
xAxis: [{
accessibility: {
description: 'Months of the year'
},
categories: ['January', 'February'],
crosshair: true
}],
yAxis: {
type: 'datetime'
},
responsive: {
rules: [{
condition: {
minWidth: 550
},
chartOptions: {
xAxis: {
categories: ['Jan', 'Feb']
}
}
}]
},
plotOptions: {
series: {
stickyTracking: true,
whiskerWidth: 5
}
},
series: [{
name: 'Plums', color: 'lime',
data: [
[1416528000000,
1417478400000
],
[
Date.UTC(2014, 10, 1, 10, 16, 58),
Date.UTC(2014, 12, 2, 10, 16, 58)
]]
}, {
name: 'Bananas',
color: 'blue',
data: [
[Date.UTC(2014, 10, 21, 10, 16, 58),
Date.UTC(2014, 11, 22, 10, 16, 58)
],
[
Date.UTC(2014, 10, 15, 10, 16, 58),
Date.UTC(2014, 12, 12, 10, 16, 58)
]
]
}, {
name: 'Apples',
color: 'red',
type: 'scatter',
marker: { symbol: 'diamond' },
data: [
[Date.UTC(2014, 10, 20, 10, 16, 58),
Date.UTC(2014, 11, 27, 10, 16, 58)
],
[
Date.UTC(2014, 10, 24, 10, 16, 58),
Date.UTC(2014, 10, 24, 12, 17, 58)
]
]
}]
});
// Remove click events on container to avoid having "clickable" announced by AT
// These events are needed for custom click events, drag to zoom, and navigator
// support.
chart.container.onmousedown = null;
chart.container.onclick = null;
//Highcharts.chart('GraphHere', {
// chart: {
// type: 'xrange'
// },
// credits: {
// enabled: false
// },
// legend: {
// enabled: false
// },
// tooltip: {
// pointFormat: ''
// },
// title: {
// text: 'Mass Remote Request PSR'
// },
// xAxis: {
// type: 'datetime'
// },
// yAxis: {
// title: {
// text: ''
// },
// categories: yAxisCategories,
// min: 0,
// max: 5,
// scrollbar: {
// enabled: true
// },
// reversed: true
// },
// series: seriesData
//});
}
It would be best to add a point there using a scatter series, disable or hide the point you want to otherwise show in chart.event.load and redraw the chart.
chart: {
events: {
load: function() {
var chart = this;
chart.series[0].update({
borderColor: 'green',
pointWidth: 0,
}, false);
chart.redraw();
}
}
},
Demo:
https://jsfiddle.net/BlackLabel/sx2u0epw/
API References:
https://api.highcharts.com/highcharts/chart.events.load
https://api.highcharts.com/highcharts/series.scatter
Im doing a chart with 2 series. One of the series is 'scatter' type and the other is 'column' type.
The problem i have, is that when i only have the scatter series, datetime labels on x axis, starts on the extreme left, but when i add the column series, is like all labels are pushed to the center, and i dont know why.
This is my fiddle examen: https://jsfiddle.net/cswpgq8u/7/
Highcharts.chart('container', {
chart: {
},
xAxis: {
type: 'datetime',
min: 1633057200000,
max: 1634353200000,
tickPositioner: function () {
var ticklist = [];
var extremes = this.getExtremes();
var startDate = extremes.min;//this.min;
var endDate = extremes.max; // this.max;
var diff = moment.duration(endDate - startDate);
if (diff.days() * 1 > 10)
increment = moment.duration(2, 'days').asMilliseconds();
else
increment = Math.ceil((endDate - startDate) / 10);
for (var timeline = startDate; moment(timeline) <= moment(endDate); timeline += increment) {
ticklist.push(timeline);
}
return ticklist;
},
maxPadding: 0,
minPadding: 0,
crosshair: {
enabled: true,
events: {
}
},
plotLines: [{
value: 1634266800000,
color: 'green',
width: 1,
dashStyle: 'ShortDash',
label: {
text: "AHORA", // Content of the label.
verticalAlign: 'bottom',
rotate: -90,
textAlign: 'right',
x: -2,
y: 30,
style: { color: '#6d6d6d', fontSize: '8px', fontWeight: 'bold', backgroundColor: 'white' }
},
}],
plotBands: null,
labels: {
formatter: function () {
var xMin = this.axis.min;
var xMax = this.axis.max;
var labeltick = Highcharts.dateFormat('%d. %B', this.value);
if ((moment(xMax).diff(moment(xMin), 'days')) < 10) {
labeltick = Highcharts.dateFormat('%d. %B %H:%M:%S', this.value);
}
return labeltick;
},
x: -10
}
},
yAxis:[
{
plotLines: [{
id: 'ln-' + 'idEje1',
color: '#9FA0A2',
width: 0,
value: 0,
dashStyle: 'longdashdot'
}],
labels: {
enabled:true,
x: -5,
y: -3,
},
title: {
enabled: false,
},
lineColor: 'lightgray',
lineWidth: 0,
tickInterval: 1
}, {
title: {
enabled: false,
},
lineColor: 'lightgray',
opposite: true,
labels: {
enabled: false,
x: -15,
y: -3,
},
lineWidth: 0,
tickInterval: 1
}
],
plotOptions: {
},
series: [
{
yAxis: 0,
type: 'scatter',
minPointLength: 1,
allowPointSelect: false,
stack: true,
data: [{
x: 1634007600000,
y: 2,
value: 2,
marker: {
symbol: 'circle',
radius: 3,
fillColor: 'red',
},
type: "ttf"
},
{
x: 1633748400000,
y: 5,
value: 2,
marker: {
symbol: 'circle',
radius: 3,
fillColor: 'red',
},
type: "ttf"
},
{
x: 1633143600000,
y: 2,
value: 2,
marker: {
symbol: 'circle',
radius: 3,
fillColor: 'red',
},
type: "ttf"
},
{
x: 1633402800000,
y: 2,
value: 2,
marker: {
symbol: 'circle',
radius: 3,
fillColor: 'red',
},
type: "ttf"
}],
name: 'On YAxis 0',
tooltip: {
pointFormatter: function () {
var point = this;
return "Valor TTF:" + ' <b>' + point.y + ' Días</b><br/>';
},
}
},
{
yAxis: 1,
type: 'column',
allowPointSelect: false,
minPointLength: 1,
data: [{
x: 1633708800000,
y: 5,
type: "duracion",
value: 5
},
{
x: 1633881600000,
y: 3,
type: "duracion",
value: 3
}],
name: 'On YAxis1',
tooltip: {
pointFormatter: function () {
var point = this;
return "Duración:" + ' <b>' + point.y + ' minutos</b><br/>';
},
},
pointWidth: 1
}
]
});
With 2 series
With one series
I think this is happening because Column Series. But dont know how to solve it.
The additional space is caused by the default calculation of pointRange for column series. You need to define it by yourself:
series: [{
type: 'scatter',
...
},
{
type: 'column',
pointRange: 1,
...
}
]
Live demo: https://jsfiddle.net/BlackLabel/hsrxtjaw/
API Reference: https://api.highcharts.com/highcharts/series.column.pointRange
How can I move the below datalabel football in the top right of the variable pie chart instead of showing in bottom. I tried these options
alignTo: 'connectors' or alignTo: 'toPlotEdges'
But nothing worked for me. Any help will be appreciated
var total = 80;
Highcharts.chart('container', {
chart: {
type: 'variablepie',
height: 370,
marginBottom: 50
},
credits: {
enabled: false
},
title: {
text: 'Football vs cricket',
align: 'center',
y: -5,
verticalAlign: 'bottom',
style: {
fontFamily: 'proxima_nova_bold',
fontSize: '20px',
fontWeight: 'normal',
color: '#8d99ab',
}
},
subtitle: {
text: ' ' + total + '<br/> Total',
useHTML: true,
verticalAlign: 'middle',
y: -20
},
xAxis: {
labels: {
rotation: 0
}
},
plotOptions: {
variablepie: {
size: 220,
dataLabels: {
enabled: true,
connectorColor: '#979797',
useHTML: true,
formatter: function () {
var key;
if(this.key == 'football'){
key = 'as football / Lionel Messi';
}else if(this.key == 'cricket'){
key = 'as cricket / Sachin Tendulkar';
}else{
key = this.key;
}
return '<span class=cls1>' + this.y + '</span>' + '<span class=cls2>' + key + '</span>';
}
},
showInLegend: true,
}
},
tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ this.y +' %';
}
},
legend: {
enabled: false
},
series: [{
minPointSize: 10,
innerSize: '70%',
zMin: 0,
data: [{name: "football", y: 71, z: 30}, {name: "cricket", y: 2, z: 18}]
}]
});
https://jsfiddle.net/anikettiwari/Lr3zy8qc/2/
You can try to implement one of the options showed here: https://www.highcharts.com/docs/advanced-chart-features/pie-datalabels-alignment
Or use the render callback and set the y position of this particular label manually.
Demo: https://jsfiddle.net/BlackLabel/2oskhmnd/
events: {
render() {
let chart = this;
chart.series[0].points[0].dataLabel.attr({y: 10});
chart.series[0].points[0].connector.hide();
}
}
Unfortunately, this solution requires to render the custom connector to moved dataLabel. You can do it by using some of the methods shown in the above link (pie-datalabels-alignment) or by using SVGRenderer tool to render a path: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#path
API: https://api.highcharts.com/highcharts/chart.events.render
I'm new to highcharts, but I seem to have an issue with the display of the large heatmap. The colors in the legend don't seem to match the colors in the actual chart.
The following is my chart configuration code.
function load_team_effort_by_day_of_week_heat_map(ele, config)
{
var self = $(ele);
var days = ["Monday", "Tuesday", "Wednesday", "Thursday","Friday", "Saturday", "Sunday"]
load_data(self, function(response)
{
var div = $("<pre/>")
.attr("id","csv")
.css("display","none");
div.html(response.data);
$("body").append(div);
var chart_container = self.attr("chart-container");
$("#"+chart_container).css("width","100%");
var min = new Date(response.min)
var max = new Date(response.max)
var max_value = response.max_range
var mid_range = parseFloat(max_value/4);
Highcharts.chart(chart_container, {
data: {
csv: document.getElementById('csv').innerHTML
},
chart: {
type: 'heatmap',
margin: [60, 10, 80, 50]
},
boost: {
useGPUTranslations: true
},
title: {
text: '',
align: 'left',
x: 40
},
subtitle: {
text: '',
align: 'left',
x: 40
},
xAxis: {
title: {
text: config.xlabel
},
type: 'datetime',
min: Date.UTC(min.getFullYear(), min.getMonth(), min.getDate()),
max: Date.UTC(max.getFullYear(), max.getMonth(), max.getDate()),
labels: {
align: 'left',
x: 5,
y: 14,
format: '{value:%b-%d-%Y}' // long month
},
showLastLabel: false,
tickLength: 16
},
yAxis: {
title: {
text: config.ylabel
},
labels: {
format: '{value}'
},
minPadding: 0,
maxPadding: 0,
startOnTick: false,
endOnTick: false,
tickPositions: [0, 1, 2, 3, 4, 5, 6],
tickWidth: 1,
min: 0,
max: 6,
reversed: true
},
colorAxis: {
stops: [
[0, '#EEEEEE'],
[mid_range, '#00ee33'],
[max_value, '#00ee33']
],
min: 0,
max: max_value,
startOnTick: false,
endOnTick: false,
labels: {
format: '{value}'
}
},
tooltip: {
formatter: function () {
var d = new Date(this.point.x)
var todate=d.getDate();
var tomonth=d.getMonth()+1;
var toyear=d.getFullYear();
var original_date=tomonth+'/'+todate+'/'+toyear;
return '<b>' + original_date + ', <b>' +
this.point.value + '</b> on <br><b>' + days[this.point.y] + '</b>';
}
},
series: [{
boostThreshold: 100,
borderWidth: 0,
nullColor: '#EEEEEE',
colsize: 7 * 24 * 36e5, // one week
turboThreshold: Number.MAX_VALUE // #3404, remove after 4.0.5 release
}]
});
self.parents('.white-background').removeClass("loadingdv");
self.parents('.white-background').find(".lodimg").remove();
//Remving extra div for legends on rite side
self.parents('.white-background').find(".legendcontainer").remove();
});
}
I would like to be able to plot a chart data which has the usual Open High low and Close plus the Volumes and Open Interest. These are to be represented in 3 panes:
Pane 1: Open High Low Close
Pane 2: Volumes
Pane 3: Open Interest.
The 'Two Panes, Candlesticks and Volumes' example from HighCharts (highStock) only deals with Pane 1 and 2. So the question is if possible to plot a third pane under the Volumes pane where I can have my Open Interest Bars?
Thanks
Yes, this is possible - just add more axis like in example you mentioned.
I am also trying to have 3 or more pane in highstock but facing an issue with scrollbar.The scrollbar is in sync with first chart only and it'snot in sync with rest of the two charts.
The code is as below:
$(function () {
$('#container').highcharts('StockChart', {
rangeSelector : {
buttons : [],
inputEnabled : false
},credits : {
enabled : false
},tooltip: {
formatter: function () {
var series = this.series;
if(null != series){
if(null != this.point.custom){
return Highcharts.dateFormat('%A %b %d %H:%M:%S',
new Date(this.x)) + '<br> ' + "<b> Alarm Criticality : </b>" +this.point.custom;
}
return Highcharts.dateFormat('%A %b %d %H:%M:%S',
new Date(this.x)) + '<br> ' + "<b> Severity : </b>" +this.y;
}else {
return Highcharts.dateFormat('%A %b %d %H:%M:%S',
new Date(this.x)) + '<br> ' + "<b> Health : </b>" +this.y;
}
}
},
yAxis: [
{
opposite : false,
min: 10,
labels: {
enabled: false
},
title: {
text: 'Alarm'
},
top: 0,
height: '25%',
offset: 0,
lineWidth: 2
},{
opposite : false,
min: 0,
//max: 100,
labels: {
align: 'left',
x: -5
},
title: {
text: 'Health'
},
top: '15%',
height: '25%',
offset: 0,
lineWidth: 2
},{
opposite : false,
min: 0,
max:10,
labels: {
align: 'left',
x: -5
},
title: {
text: 'Anomaly Score'
},
top: '50%',
height: '25%',
offset: 0,
lineWidth: 2
}
],
series: [
{
type: 'scatter',
name: 'Alarm',
cursor: 'pointer',
id: 'alarm',
data: data :[someData],
turboThreshold: 3600,
yAxis: 0
},{
name : 'Health',
data :[someData],
yAxis: 1,
type : 'areaspline',
id: "health",
fillColor : {
linearGradient : {
x1 : 0,
y1 : 0,
x2 : 0,
y2 : 1
},
stops : [
[
0, Highcharts.getOptions().colors[ 0 ]
], [
1, Highcharts.Color( Highcharts.getOptions().colors[ 0 ] ).setOpacity( 0 ).get( 'rgba' )
]
]
}
},{
type: 'scatter',
name: 'Anomaly Score',
data: data :[someData],
yAxis: 2,
id : 'anomalies',
lineWidth : 0,
marker : {
enabled : true,
radius : 4,
symbol: 'circle',
fillColor:'#8EBCEB'
}
}
]
});
});