How to show mouse pointer coordinates on mouse move in angular highchart? - highcharts

I want to show tooltip on mouse hover of every coordinate in angular-highchart, it should show x and y axis value in tooltip or label.
how we can show the tooltip on every coordinate of high chart.

It can be add scatter series and enabled markers, to imitate showing tooltip when axiss are crossing. Additionally, I added wrapp and extend to get a possibility to chart coordinate inside tooltip.formatter callback function.
(function(H) {
H.Tooltip.prototype.getAnchor = function(points, mouseEvent) {
var ret,
chart = this.chart,
inverted = chart.inverted,
plotTop = chart.plotTop,
plotLeft = chart.plotLeft,
plotX = 0,
plotY = 0,
yAxis,
xAxis;
points = H.splat(points);
// Pie uses a special tooltipPos
ret = points[0].tooltipPos;
// When tooltip follows mouse, relate the position to the mouse
if (this.followPointer && mouseEvent) {
if (mouseEvent.chartX === undefined) {
mouseEvent = chart.pointer.normalize(mouseEvent);
}
ret = [
mouseEvent.chartX - chart.plotLeft,
mouseEvent.chartY - plotTop
];
}
// When shared, use the average position
if (!ret) {
H.each(points, function(point) {
yAxis = point.series.yAxis;
xAxis = point.series.xAxis;
plotX += point.plotX + (!inverted && xAxis ? xAxis.left - plotLeft : 0);
plotY += (point.plotLow ? (point.plotLow + point.plotHigh) / 2 : point.plotY) +
(!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151
});
plotX /= points.length;
plotY /= points.length;
ret = [
inverted ? chart.plotWidth - plotY : plotX,
this.shared && !inverted && points.length > 1 && mouseEvent ?
mouseEvent.chartY - plotTop : // place shared tooltip next to the mouse (#424)
inverted ? chart.plotHeight - plotX : plotY
];
}
// Add your event to Tooltip instances
this.event = mouseEvent;
return H.map(ret, Math.round);
}
})(Highcharts)
Highcharts.chart('container', {
title: {
text: 'Logarithmic axis demo'
},
xAxis: {
tickInterval: 0.1,
gridLineWidth: 1,
type: 'logarithmic',
accessibility: {
rangeDescription: 'Range: 1 to 10'
}
},
yAxis: [{
type: 'logarithmic',
minorTickInterval: 0.1,
accessibility: {
rangeDescription: 'Range: 0.1 to 1000'
}
}],
tooltip: {
followTouchMove: true,
followPointer: true,
formatter: function(mouseEvent) {
let event = mouseEvent.event
return `chartX:${event.chartX} <br> chartY:${event.chartY}`;
}
},
series: [{
data: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512],
pointStart: 1
},
{
type: 'scatter',
data: [{
x: 1,
y: 10
}, {
x: 2,
y: 10
}, {
x: 5,
y: 10
}, {
x: 4,
y: 10
}, {
x: 8,
y: 10
}],
}
],
plotOptions: {
scatter: {
states: {
inactive: {
enabled: false
}
},
marker: {
enabled: false
},
enableMouseTracking: true,
showInLegend: false
},
}
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="container"></div>
Demo: https://jsfiddle.net/BlackLabel/t05uqfvm/

Related

How to put shadow inside of bar chart in highcharts?

How to put shadow inside of bar chart like box-shadow inset(css) in hightcharts as image below.
Thank you. Have a good day~
enter image description here
You can use two overlap series, one with default shadow property and translate both of them by a few pixels in load event:
Highcharts.chart('container', {
chart: {
...,
events: {
load: function() {
this.series[0].points[0].graphic.attr({
translateX: -2
});
this.series[1].points[0].graphic.attr({
translateX: -2
});
}
}
},
...,
series: [{
...,
data: [100],
shadow: {
color: 'gray',
opacity: 0.8,
width: 2
}
}, {
data: [50]
}]
});
Live demo: http://jsfiddle.net/BlackLabel/b7hp0r6s/
API Reference: https://api.highcharts.com/highcharts/series.bar.shadow
Unfortunately, Highcharts doesn't have an inset shadow implemented in the core. However, it can be done by adding custom logic to Highcharts.SVGElement.prototype.shadow method. Check the code and demo posted below and let me know if something is unclear for you.
Additionally, to add a partial fill to columns with the inner shadow you have to make a custom column elements and insert them to the DOM between shadows and particular points.
Code:
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
(function(H) {
H.SVGElement.prototype.shadow = function(shadowOptions, group, cutOff) {
var shadows = [],
i, shadow, element = this.element,
strokeWidth, shadowWidth, shadowElementOpacity,
// compensate for inverted plot area
transform,
elemBBox = element.getBBox(),
translateX,
translateY;
if (!shadowOptions) {
this.destroyShadows();
} else if (!this.shadows) {
shadowWidth = H.pick(shadowOptions.width, 3);
shadowElementOpacity = (shadowOptions.opacity || 0.15) /
shadowWidth;
transform = this.parentInverted ?
'(' + H.pick(shadowOptions.offsetY, 1) * -1 + ', ' +
H.pick(shadowOptions.offsetX, 1) * -1 + ')' :
'(' + H.pick(shadowOptions.offsetX, 1) + ', ' +
H.pick(shadowOptions.offsetY, 1) + ')';
if (!shadowOptions.inside) {
for (i = 1; i <= shadowWidth; i++) {
shadow = element.cloneNode(0);
strokeWidth = (shadowWidth * 2) + 1 - (2 * i);
H.attr(shadow, {
stroke: (shadowOptions.color ||
'#000000'),
'stroke-opacity': shadowElementOpacity * i,
'stroke-width': strokeWidth,
transform: 'translate' + transform,
fill: 'none'
});
shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow');
if (cutOff) {
H.attr(shadow, 'height', Math.max(H.attr(shadow, 'height') - strokeWidth, 0));
shadow.cutHeight = strokeWidth;
}
if (group) {
group.element.appendChild(shadow);
} else if (element.parentNode) {
element.parentNode.insertBefore(shadow, element);
}
shadows.push(shadow);
}
} else {
for (i = shadowWidth; i >= 1; i--) {
shadow = element.cloneNode(0);
translateX = i / 2 - shadowOptions.offsetY;
translateY = i / 2 - shadowOptions.offsetX;
H.attr(shadow, {
stroke: (shadowOptions.color ||
'#000000'),
'stroke-opacity': shadowElementOpacity * (shadowWidth - i + 1),
'stroke-width': i,
transform: 'translate(' + translateX + ',' + translateY + ')',
fill: 'none'
});
H.css(shadow, {
width: elemBBox.width - i,
height: elemBBox.height - i,
});
shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow');
if (cutOff) {
H.attr(shadow, 'height', Math.max(H.attr(shadow, 'height') - strokeWidth, 0));
shadow.cutHeight = strokeWidth;
}
if (group) {
group.element.appendChild(shadow);
} else if (element.parentNode) {
insertAfter(shadow, element);
}
shadows.push(shadow);
}
}
this.shadows = shadows;
}
return this;
};
})(Highcharts)
Highcharts.chart('container', {
chart: {
type: 'column',
inverted: true,
events: {
render: function() {
var chart = this,
yAxis = chart.yAxis[0],
partialFillWidth,
elem,
bBox;
if (chart.customElements && chart.customElements.length) {
chart.customElements.forEach(custElem => {
custElem.parentNode.removeChild(custElem);
})
chart.customElements.length = 0;
} else {
chart.customElements = [];
}
chart.series[0].points.forEach(point => {
bBox = point.graphic.getBBox();
elem = point.graphic.element.cloneNode(0);
partialFillWidth = yAxis.toPixels(point.partialFill);
Highcharts.attr(elem, {
fill: point.partialFillColor,
transform: 'translate(0, ' + (bBox.height - (point.partialFill / point.y) * bBox.height) + ')'
});
Highcharts.css(elem, {
height: (point.partialFill / point.y) * bBox.height
});
insertAfter(elem, point.graphic.element);
chart.customElements.push(elem);
});
}
}
},
title: {
text: 'Efficiency Optimization by Branch'
},
xAxis: {
categories: [
'Seattle HQ',
'San Francisco',
'Tokyo'
]
},
yAxis: [{
min: 0,
title: {
text: 'Employees'
}
}, {
title: {
text: 'Profit (millions)'
},
opposite: true
}],
legend: {
shadow: false
},
tooltip: {
shared: true
},
plotOptions: {
column: {
grouping: false,
shadow: false,
borderWidth: 0,
pointPadding: 0,
groupPadding: 0
}
},
series: [{
color: '#efefef',
id: 'main',
data: [{
y: 120,
partialFill: 100,
partialFillColor: '#bbb'
}, {
y: 50,
partialFill: 10,
partialFillColor: '#bbb'
}, {
y: 70,
partialFill: 20,
partialFillColor: '#bbb'
}],
pointPadding: 0.4,
shadow: {
color: 'rgba(0, 0, 0, 0.5)',
opacity: 0.3,
width: 5,
offsetX: 0,
offsetY: 0,
inside: true
}
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/kvrjd48w/
API reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement
https://api.highcharts.com/class-reference/Highcharts#.attr

Keep Scroll on the Right Highchart

Is there a way to keep the scroll on the most right?
I am trying live update on highchart and it seems that sometimes I am encountering scroll being left behind.
$(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
// Create the chart
$('#container').highcharts('StockChart', {
chart: {
events: {
load: function() {
// set up the updating of the chart each second
var series = this.series[0],
hasPlotLine = false,
$button = $('#button'),
chart = $('#container').highcharts(),
yAxis = chart.yAxis[0],
plotLine,
d,
newY;
yAxis.addPlotLine({
value: 66,
color: 'red',
width: 2,
id: 'plot-line-1',
label: {
text: 66,
align: 'right',
y: newY,
x: 0
}
});
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
plotLine = yAxis.plotLinesAndBands[0].svgElem;
d = plotLine.d.split(' ');
newY = yAxis.toPixels(y) - d[2];
plotlabel = yAxis.plotLinesAndBands[0].label;
plotlabel.animate({
translateY:newY,
text:y
},400),
plotLine.animate({
translateY: newY
}, 400);
}, 1000);
}
}
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 0
},
title: {
text: 'Live random data'
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -999; i <= 0; i += 1) {
data.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data;
}())
}]
});
});
I know it a little bit hard to explain my concern, but check this image
I have search setExtremes but I am not sure if how it works or how it will be set up on future dated in case this is the function that I am looking for.
Here is the jsfiddle http://jsfiddle.net/kttfv1h3/3/
Appreciate your help
setExtremes() will work - see API http://api.highcharts.com/highcharts/Axis.setExtremes.
The only thing you need to adjust is the min value - you can calculate it from the last point or set some fixed value.
xAxis.setExtremes(x - 1000 * 60, x)
example: http://jsfiddle.net/nmx5hruo/

Highcharts pie graph with two rings filtering

I have a pie chart here that I'm working on that has two "rings" in it. The inner ring is just a summation of the outer ring for that given category.
Here is the fiddle: http://jsfiddle.net/jeffvan576/a50859s7/1/
(Apologies for the code - it's a bit of a mess right now)
I've been messing around with the showInLegend functionality but that will (as it's intended) only pull out the given piece of the pie chart. So, for instance, if you click google, it pulls out that piece of the pie chart but leaves the outer ring. To completely eliminate google you need to click "google", "match", "funds added" and "organic" for google.
My question is, is there a way to remove the entire slice (google and all it's children) from the chart at once?
The issue is that in order to get the functionality / layout on the chart that I need, this pie chart is actually built out of two series.
ShowInLegend code:
pie: {
shadow: false,
center: ['50%', '50%'],
showInLegend: true
}
I started building a custom visibility function at the bottom of the fiddle but dialed it back until I understood showInLegend a little better.
Thanks in advance!
you can achieve this by getting name of series on which clicked by using http://api.highcharts.com/highcharts#plotOptions.pie.events.click of plotoptions -> pie.
after that calling visibility function to hide Channel series along with its children to hide/show.
Event:
plotOptions: {
pie: {
shadow: false,
center: ['50%', '50%'],
showInLegend: true,
point: {
events: {
}
}
}
}
also static line put into visibility function to hide/show need to remove.
// chart.series[0].data[0].visible = false;
http://jsfiddle.net/a50859s7/27/
Full code:
$(function () {
var dataObject = {
facebook: {
'organic': 10.85,
'match': 7.35,
'fundsadded': 33.06,
'total': 0,
'status': 'disabled'
},
google: {
'organic': 10.85,
'match': 7.35,
'fundsadded': 33.06,
'total': 0,
'status': 'disabled'
},
email: {
'organic': 10.85,
'match': 7.35,
'fundsadded': 33.06,
'total': 0,
'status': 'enabled'
},
colorSelections: {
'facebook': '#3b5998',
'google': '#dd4b39',
'disabled': '#c6c6c6'
}
}
var sumObjects = function () {
for (var channel in dataObject) {
if (channel === 'colorSelections') continue;
var sum = 0;
for (var key in dataObject[channel]) {
if (key === 'status') continue;
sum += dataObject[channel][key];
}
dataObject[channel].total = sum;
}
}
sumObjects();
var colors = Highcharts.getOptions().colors,
categories = ['Facebook', 'Google', 'Email'],
data = [{
y: dataObject.facebook.total + 1,
//color: dataObject.facebook.status === 'disabled' ? dataObject.colorSelections.disabled : dataObject.colorSelections.facebook,
color: 'rgba(59, 89, 152, 0.3)',
drilldown: {
name: 'Facebook',
categories: ['organic', 'match', 'funds added'],
data: [
dataObject.facebook.organic,
dataObject.facebook.match,
dataObject.facebook.fundsadded],
color: 'rgba(59, 89, 152, 0.3)'
},
}, {
y: dataObject.google.total + 1,
color: '#dd4b39',
drilldown: {
name: 'Google',
categories: ['organic', 'match', 'funds added'],
data: [
dataObject.google.organic,
dataObject.google.match,
dataObject.google.fundsadded],
color: '#e46f61'
}
}, {
y: dataObject.email.total + 1,
color: colors[2],
drilldown: {
name: 'Email',
categories: ['organic', 'match', 'funds added'],
data: [
dataObject.email.organic,
dataObject.email.match,
dataObject.email.fundsadded],
color: colors[2]
}
}],
browserData = [],
versionsData = [],
i,
j,
dataLen = data.length,
drillDataLen,
brightness;
// Build the data arrays
for (i = 0; i < dataLen; i += 1) {
// add browser data
browserData.push({
name: categories[i],
y: data[i].y,
color: data[i].color
});
// add version data
drillDataLen = data[i].drilldown.data.length;
for (j = 0; j < drillDataLen; j += 1) {
brightness = 0.2 - (j / drillDataLen) / 5;
versionsData.push({
name: data[i].drilldown.categories[j],
y: ((data[i].drilldown.data[j] / browserData[0].y) * 100),
color: Highcharts.Color(data[i].color).brighten(brightness).get()
});
}
}
// Create the chart
$('#container').highcharts({
chart: {
type: 'pie'
},
title: {
text: 'Browser market share, April, 2011'
},
yAxis: {
title: {
text: 'Total percent market share'
}
},
plotOptions: {
pie: {
shadow: false,
center: ['50%', '50%'],
showInLegend: true,
point: {
events: {
click: function (event) {
var seriesIndex;
var secondarySeriesIndex;
if (this.name == 'Facebook') {
seriesIndex = 0;
secondarySeriesIndex = 0;
} else if (this.name == 'Google') {
seriesIndex = 1;
secondarySeriesIndex = 3;
} else if (this.name == 'Email') {
seriesIndex = 2;
secondarySeriesIndex = 6;
}
var chart = $('#container').highcharts();
visibility(chart.series[0].data[seriesIndex]);
visibility(chart.series[1].data[secondarySeriesIndex]);
visibility(chart.series[1].data[secondarySeriesIndex + 1]);
visibility(chart.series[1].data[secondarySeriesIndex + 2]);
}
}
}
}
},
tooltip: {
valueSuffix: '%'
},
series: [{
name: 'Channel',
type: 'pie',
data: browserData,
size: '120%',
dataLabels: {
formatter: function () {
return this.y > 5 ? this.point.name : null;
},
color: 'white',
distance: -30
}
}, {
name: 'Added',
type: 'pie',
data: versionsData,
size: '120%',
innerSize: '80%',
dataLabels: {
formatter: function () {
// display only if larger than 1
return this.y > 1 ? '<b>' + this.point.name + ':</b> ' + this.y + '%' : null;
}
}
}]
});
var visibility = function (series) {
series.visible ? series.graphic.hide() : series.graphic.show();
// chart.series[0].data[0].visible = false;
}
var chart = $('#container').highcharts();
$('.update').click(function () {
visibility(chart.series[0].data[0]);
visibility(chart.series[1].data[0]);
visibility(chart.series[1].data[1]);
visibility(chart.series[1].data[2]);
chart.redraw();
});
function synchronizePieSeries(event, slice) {
debugger;
$(chart.series[1].data).each(function (i, e) {
if (slice.name === e.name) {
slice.visible ? e.graphic.hide() : e.graphic.show();
}
});
}
//$('.update').click(function (event) {
// synchronizePieSeries(event, this);
//});
});

Disables Crosshair for one series of two

I'm using a chart with two series as you can see in http://jsfiddle.net/Charissima/zo5j94qz/4/
Is it possible to disable crosshairs for the second series? The problem is, that when the moise pointer is near the black series s2, there is no crosshair for the blue series s1 and I don't need/want crosshairs for the black series but for the blue.
var myData = [];
for (var i = 2; i < 10; i++) {
myData.push([i, i + Math.random() * 3]);
}
var myDataLine = [];
myDataLine.push([0,6]);
myDataLine.push([23,6]);
chart = $('#container').highcharts('StockChart', {
chart : {
zoomType: 'x',
},
series: [{
name: 's1',
data: myData,
type: 'line'
},{
name: 's2',
data: myDataLine,
type: 'line'
}]
});
Defaulty it is not built-in, but you can prepare your own crosshair function like in the example:
mouseOver: function () {
var chart = this.series.chart,
r = chart.renderer,
left = chart.plotLeft,
top = chart.plotTop,
width = chart.plotWidth,
height = chart.plotHeight,
x = this.plotX,
y = this.plotY;
if (this.series.options.enabledCrosshairs) {
crosshair = r.path(['M', left, top + y, 'L', left + width, top + y, 'M', left + x, top, 'L', left + x, top + height])
.attr({
'stroke-width': 1,
stroke: 'red'
})
.add();
}
},
mouseOut: function () {
if (crosshair.d !== UNDEFINED) crosshair.destroy();
}
http://jsfiddle.net/u4ha3cxw/7/
Yes, this is very possible. Use 2 x-axes, one with crosshair's enabled and the other with crosshairs disabled. Then specify which series you would like to use which axis:
Highcharts.chart('container', {
xAxis: [{
crosshair: {
enabled: true,
width: 5
}
}, {
crosshair: false,
visible: false
}],
series: [{
name: 'Series w/ Crosshair',
xAxis: 0, // You could omit this, highcharts uses the first axis in array by default
data: [99.9, 81.5, 76.4, 129.2, 144.0]
},
{
name: 'Series w/o Crosshair',
xAxis: 1,
data: [42.1, 47.5, 150.4, 42.2, 64.0]
}
]
})
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 250px"></div>

jqplot tooltip not working for large number of x axis data labels

I am rendering a bar chart in my code but since I have too many x axis data points, the tooltip doesnt show. Can anyone help here?
My code is:
plot = $.jqplot(chartID, [xAndyVals],
{
title: tempKey,
seriesDefaults: {
pointLabels: { show: true },
},
series: [{ renderer: $.jqplot.BarRenderer }],
axesDefaults: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
angle: -30,
fontSize: '10pt',
}
},
axes: {
xaxis: {
ticks: xTicks,
},
yaxis: {
min: 0,
max: yMaxVal,
}
},
highlighter: {
show: true,
sizeAdjust: 7.5,
tooltipContentEditor: tooltipContentEditor
},
cursor: {
show: false,
showTooltip: true
},
});
function tooltipContentEditor(str, seriesIndex, pointIndex, plot) {
var plotData = plot.data[seriesIndex][pointIndex];
var tooltip = mapping.get(plotData[0]);
return tooltip + ", " + plotData[1];
}
Sample xAndyVals is [0, 152518], where 0 is the x axis value and 152158 is the y axis value.

Resources