Highcharts Shared Tooltip not appearing for multi-axes chart with positioning - highcharts

I have a chart with multiple y axes. I have moved one chart to bottom using top option. When I hover on the graph moved to bottom, shared tooltip does not appear. When I hover on the space just above the bar chart. Space between the bar and 100 (in Y axis), the tool -tip does not appear. Hover on the space right or left to the bar, tool-tip does not appear.
I don't want to have the graph in its default position. It looks cleaner when I have two graphs separated. Can I make the shared tool tip work when graph is moved down ?
My code:
yAxis: [{
top: 148
},
{
top: 0
}],
tooltip: {
shared: true,
crosshairs: {
color: 'rgba(27,161,218,0.5)',
dashStyle: 'solid',
zIndex: -1
}
},
Here is the fiddle: multi-axes graph with positioning
Any input appreciated.
Thanks

Look at using synchronized charts.
http://www.highcharts.com/demo/synchronized-charts
The JSFiddle is updated to use synchronized charts.
JSFiddle
$(function() {
$('#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];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
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) {
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'
});
}
}
});
}
}
var dataset = [{
"name": "Series 1",
"type": "column",
"data": [29.9, 71.5, 106.4]
}, {
"name": "Series 2",
"type": "line",
"data": [216.4, 194.1, 95.6]
}];
for (var i = 0; i < dataset.length; i++) {
var dataitem = dataset[i];
$("<div class=\"chart\">")
.appendTo('#container').highcharts({
title: {
text: dataitem.name
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar']
},
tooltip: {
crosshairs: {
color: 'rgba(27,161,218,0.5)',
dashStyle: 'solid',
zIndex: -1
}
},
series: [{
data: dataitem.data,
name: dataitem.name,
type: dataitem.type
}]
});
};
});

Related

How to add separate annotation style tooltip for Highcharts marker?

Need to add separate tooltip for point marker.
I am using crosshair for displaying tooltip in Highcharts. Also, for some of the series data points I am adding a marker(in yellow circle). I want to know if it is possible to have a custom tooltip on hovering specifically on the marker point, but I would also like to retain the normal crosshair tooltip behavior on the same point (i.e. while hovering outside the yellow marker area for the same data point, tooltip should respect the tooltip formatter and on hovering exactly on the marker tooltip should show a different text related to the marker). Is it possible to achieve?
[My intention is to create a hoverable annotation marker, but at the same time retain the default tooltip behavior for the same point]
Please see the images below to get an idea about the expected behavior. Please ignore the series data, since they are generated dynamically, and is different on every page refresh. What I want to achieve is to have a crosshair tooltip for the '05-Jan-2019' data point, and also show a different looking or custom tooltip when user hovers specifically on the 'yellow' marker for the same data point.
Any suggestions related to alternative ways to achieve this are also welcome.
Here is how I am adding the marker in my series data :
function formatSeriesData(allSeries, annotations, categories) {
for (let i = 0; i <= allSeries.length; i++) {
let serie = allSeries[i];
if (serie && !serie['color']) {
serie = {
...serie,
color: defaultColors[i]
}
allSeries[i] = serie;
}
//add annotations - if present
if (serie && annotations && annotations.length) {
const applicableAnnotations = _.filter(annotations, {
name: serie.name
});
const annotationDates = _.map(applicableAnnotations, 'date'); //get all annotation dates
let modifiedDataArray = [];
let dataArray = serie.data; //get all series data
for (let j = 0; j < dataArray.length; j++) {
let dateForValue = categories[j]; //get the date corresponding to the value
let annotation = _.find(applicableAnnotations, {
date: dateForValue
});; //pick the annotation object
let ptObj = {
dimension: "",
y: dataArray[j]
};
if (annotation && annotation.annotation) {
ptObj["marker"] = {
enabled: true,
radius: 6,
fillColor: '#FDBE2C',
symbol: 'circle'
};
}
modifiedDataArray.push(ptObj);
}
serie = {
...serie,
data: modifiedDataArray
}
allSeries[i] = serie;
}
}
console.log("allSeries ", allSeries);
return allSeries;
}
To achieve the wanted result you can create a chart with two series - line with disabled enableMouseTracking and scatter with default tooltip and mouse events to control the display of crosshair:
Highcharts.chart('container', {
series: [{
data: [1, 2, 3, 4],
enableMouseTracking: false
}, {
color: 'yellow',
events: {
mouseOver: function() {
this.xAxis.update({
crosshair: {
width: 0,
label: {
enabled: false
}
}
});
},
mouseOut: function() {
this.xAxis.update({
crosshair: {
width: 1,
label: {
enabled: true
}
}
});
}
},
marker: {
radius: 8,
symbol: 'circle'
},
stickyTracking: false,
data: [{
x: 2,
y: 3
}]
}],
xAxis: {
crosshair: {
label: {
enabled: true
},
snap: false
}
}
});
Live demo: http://jsfiddle.net/BlackLabel/k83u0spd/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Axis#update
https://api.highcharts.com/highcharts/series.line.enableMouseTracking
https://api.highcharts.com/highcharts/series.line.stickyTracking

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>

Can we disable zoom on highchart graph while graph is loading

Can we disable zoom on highchart graph while graph is loading.
I have multiple graphs therfore would like to disable the zoom option until all graphs gets loaded.
It is possible to change zoomType of a chart dynamically, but it is not a part of official API. That way after all charts are loaded you will be able to change their zoomType from none to some.
$(function () {
$('#container').highcharts({
chart: {
zoomType: ''
},
xAxis: {
minRange: 1
},
series: [{
data: [1,2,3,4,5,6,7]
}]
});
function enableZoom(zoomType) {
var chart = $('#container').highcharts(),
zoomX = /x/.test(zoomType),
zoomY = /y/.test(zoomType);
chart.options.zoomType = zoomType;
chart.pointer.zoomX = zoomX;
chart.pointer.zoomY = zoomY;
chart.pointer.zoomHor = zoomX;
chart.pointer.zoomVert = zoomY;
}
$('#zoomX').click(function () {
enableZoom('x');
});
$('#zoomY').click(function () {
enableZoom('y');
});
$('#zoomXY').click(function () {
enableZoom('xy');
});
$('#noZoom').click(function () {
enableZoom('');
});
});
JSFiddle: http://jsfiddle.net/pearp126/
you can do so by simple setting zoomType as null in your chart config
zoomType: null
See the documentation here for more details
Basically the only thing you need to get done is removing the chart and replacing it with one with the settings you like.
See the code below:
var chart = $('#container').highcharts();
function renderChart(){
chart = new Highcharts.Chart(chart.options);
chart.render();
}
Once you want to enable zooming (or any other setting):
$('#container').highcharts().options.chart.zoomType = 'xy';
renderChart();
To be honest I'm not sure what happens to the old chart. Hopefully it's just overwritten and doesn't it impose a big memory issue.
I created a fiddle you can find here
Basically you can stop the "selection" event (zoom), when the loading label of the chart is displayed.
Using the default Highcharts function .showLoading() for show the loading label, and the default variable loadingShown, for verify is the loading label is displayed or not.
So, by using the function .showLoading(), let's say before doing an AJAX request, and validating with the variable loadingShown if the loading label is displayed or not, we can stop the selection event.
Another way, is to use a thirdparty loading mask, and add it to the chart's container.
In the next example you'll find how to cancel the zoom using the .showLoading() function and how to use jQuery plugin: pLoading https://github.com/joseshiru/p-loading (for show the loading mask)
$(function () {
var setEvents;
var chart;
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=usdeur.json&callback=?', function (data) {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
zoomType: 'x',
events: {
selection: function () {
//Quit the selection event, while the loading spinner is displayed.
if (chart.loadingShown) {
return false;
}
}
}
},
title: {
text: 'USD to EUR exchange rate over time'
},
subtitle: {
text: document.ontouchstart === undefined ?
'Click and drag in the plot area to zoom in' : 'Pinch the chart to zoom in'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'Exchange rate'
}
},
legend: {
enabled: false
},
plotOptions: {
area: {
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')]
]
},
marker: {
radius: 2
},
lineWidth: 1,
states: {
hover: {
lineWidth: 1
}
},
threshold: null
}
},
series: [{
type: 'area',
name: 'USD to EUR',
data: data
}]
});
});
setEvents = function () {
var $showLoadingBtn = $('.show-loading');
var $hideLoadingBtn = $('.hide-loading');
var $showExternalMask = $('.show-toggle-mask');
var $hideExternalMask = $('.hide-toggle-mask');
$showLoadingBtn.on('click.showLoading', function () {
chart.showLoading();
});
$hideLoadingBtn.on('click.hideLoading', function () {
chart.hideLoading();
});
$showExternalMask.on('click.toggleMask', function () {
$('#container').ploading({action: 'show'});
});
$hideExternalMask.on('click.toggleMask', function () {
$('#container').ploading({action: 'hide'});
});
}();
});
Example in jsfiddle: http://jsfiddle.net/8p2fzbxw/3/

Chart rendering issue when hiding all series via clicking on legends

Steps to reproduce.
We have a chart that display 4 series of data, and we have the corresponding legends with each series.
THe initial chart is loaded with 1 years worth of data.
We then remove all data-series from the chart by clicking on the 4 legends
We then change the Zoom level of the chart - e.g. going from a 6 month zoom, to a 3 month zoom. (NOTE: We change Zoom with no data-series being displayed).
We then re-enable the data-series by clicking on the legends.
The chart does not redraw correctly. To get the chart to redraw we have to reload the entire page.
<script src="http://code.highcharts.com/stock/highstock.js"></script>
<script src="http://code.highcharts.com/stock/modules/exporting.js"></script>
<div id="container" style="height: 500px; min-width: 600px"> </div>
$(function() {
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'],
colors = Highcharts.getOptions().colors;
$.each(names, function(i, name) {
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename='+ name.toLowerCase() +'-c.json&callback=?', function(data) {
seriesOptions[i] = {
name: name,
data: data
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if (seriesCounter == names.length) {
createChart();
}
});
});
// create the chart when all data is loaded
function createChart() {
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container'
},
navigator: {
enabled: false
},
legend: {
enabled: true
},
rangeSelector: {
selected: 4
},
scrollbar: {
enabled: false
},
yAxis: {
labels: {
formatter: function() {
return (this.value > 0 ? '+' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: seriesOptions
});
}
});
JsFiddle Example
It looks like a bug, so I've reported it to our devs here: https://github.com/highslide-software/highcharts.com/issues/1568
A simple workaround :
After some trial and error, I found out that if you do not disable the navigator, the above bug is not exhibited. (Navigator is enabled by default.)
Comment the line as shown below:
navigator: {
//enabled: false
}
Js Fiddle : http://jsfiddle.net/msjaiswal/FDXBu/1/
Certainly this is a bug in Highcharts but we can live with this above simple workaround.
This issue has been resolved in version 1.3.2 of HighStock.

Highstock returns incorrect x value (datetime) after zoom for column chart

After any sort of zoom (mouse drag, range selector, date input) the datetime returned from the point click event is usually incorrect. I've not yet found this problem when using an area chart, have found it using both bar and column chart.
To recreate: run the fiddle, zoom using the mouse across a few of the columns, click a datapoint. The alert will show the datetime returned. Notice it's different from the tooltip (which is correct).Usually fails after first click, even for the same datapoint.
BTW useUTC setting doesn't matter.
Fiddle: http://jsfiddle.net/jrEDT/
Code for completeness:
$(function() {
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
names = ['MSFT'],
colors = Highcharts.getOptions().colors;
$.each(names, function(i, name) {
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename='+ name.toLowerCase() +'-c.json&callback=?', function(data) {
seriesOptions[i] = {
name: name,
data: data,
type: 'column'
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if (seriesCounter == names.length) {
createChart();
}
});
});
// create the chart when all data is loaded
function createChart() {
Highcharts.setOptions({
global: {
useUTC: false // datetime reflects time on db (ie, local) rather than GMT
}
});
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
zoomType: 'x'
},
exporting: {
enabled: false
},
rangeSelector: {
selected: 4
},
yAxis: {
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}],
offset: 25
},
plotOptions: {
series: {
cursor: 'pointer',
allowPointSelect: true,
point: {
events: {
click: function() {
var series = this.series.name;
var utc = this.x;
var d = Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x);
alert(d);
}
}
}
}
},
tooltip: {
formatter:function(a,b,c){
var d = Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x);
return d;
},
enable:true
},
series: seriesOptions
});
}
});
Thanks!
Have you tried to disable datagrouping http://api.highcharts.com/highstock#plotOptions.series.dataGrouping ?

Resources