Highcharts position tooltip at the middle of stacked bar - javascript

I've been trying to use the tooltip positioner to get the tooltip at the middle of each stacked bar instead of the right side but I've not been able to find any variable that could be use to calculate the x of the appropiate point.
tooltip: {
positioner: function (labelWidth, labelHeight,point) {
return {
x: point.plotX - this.chart.hoverPoint.pointWidth,
y: point.plotY + this.chart.plotTop - labelHeight
};
}
}
Here is a codepen that show how it fails on the last point:
http://jsfiddle.net/vw7ebd4k/1/

To calculate the tooltip position you can use point.h and labelWidth. Try something like that:
tooltip: {
positioner: function (labelWidth, labelHeight, point) {
return {
x: point.plotX - point.h/2 + labelWidth/2,
y: point.plotY
};
}
}
To remove the unnecessary line between tooltip and point you can use tooltip.shape property.
shape: 'rect'

Related

Highcharts - overlapping values with the x-Axis

I am trying to create a line graph, wherein if all the values for the particular series is zero then, I want the line to be drawn on the bottom over the x-axis line. But it seems like the line of the x-axis takes the preference than the series line. Is there any way to change that?
Below is my configuration:
xAxis: {
type: "datetime",
tickmarkPlacement: "on",
lineWidth: 10,
lineColor: 'red',
},
yAxis: {
min: 0,
minRange : 0.1,
title: {
text: ""
}
},
plotOptions: {
line: {
softThreshold: false
}
},
Example:
http://jsfiddle.net/shivajyothibalavikas/twxs7mL2/3
In the above example the axis line color is red and series line color is black. but red takes the preference. I want the black line to take the preference while displaying
It is not possible to move a series line above an axis line by options in Highcharts API. As a solution, you can use the Highcharts.SVGRenderer class and draw a custom line at the chart bottom.
chart: {
...,
events: {
render: function() {
const chart = this;
const x1 = chart.plotLeft;
const x2 = x1 + chart.plotWidth;
const y = chart.plotTop + chart.plotHeight;
if (!chart.customLine) {
chart.customLine = chart.renderer
.path().attr({
stroke: 'red',
'stroke-width': 10
}).add();
}
chart.customLine.attr({
d: ['M', x1, y, 'L', x2, y]
});
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/70d6sg2o/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer

D3 annotations in wrong place along x axis

I am using the wonderful plugin d3 annotations and I'm having a hard time trying to figure out why are my annotation being placed in the wrong area along my x axis. I'm using a time scale to determine the range of my axis and I'm using the same for the annotations but somehow it isn't working. I've followed the same process found in the documentation (https://bl.ocks.org/susielu/23dc3082669ee026c552b85081d90976).
X scale:
const xScale = d3
.scaleTime()
.domain(d3.extent(data, xAccessor))
.range([0, dimensions.boundedWidth])
.nice();
Annotations:
const annotations = [
{
note: {
label: 'National emergency is declared',
align: 'center',
wrap: 100,
},
subject: {
y1: dimensions.margin.top + 40,
y2: dimensions.height - dimensions.margin.bottom,
},
y: dimensions.height - dimensions.boundedHeight,
data: { x: dateParser('2020-3-13') }, // position the x based on an x scale
},
{
note: {
label: `Florida's stay at home rule is declared`,
align: 'right',
wrap: 120,
},
subject: {
y1: dimensions.margin.top + 40,
y2: dimensions.height - dimensions.margin.bottom,
},
y: dimensions.height - (dimensions.boundedHeight - 10),
data: { x: dateParser('2020-4-1') },
},
];
const type = d3.annotationCustomType(d3.annotationXYThreshold, {
note: {
lineType: 'none',
orientation: 'top',
},
});
// 12 - render the annotations
const makeAnnotations = d3
.annotation()
.type(type)
.accessors({
x(d) {
return xScale(d.x);
},
y(d) {
return yScale(d.y);
},
})
.annotations(annotations)
.textWrap(30);
wrapper
.append('g')
.attr('class', 'annotation-group')
.call(makeAnnotations);
If you look at your dataviz, both annotations are off (to the left) by the same amount. The code you posted is not enough to see what's happening, but since you have this as the scale's range...
.range([0, dimensions.boundedWidth])
... I bet you are appending the axis and the other elements to a groups which is translated by the left-marging amount you set while appending the annotations to another group (inside wrapper, whatever that is), which is not translated by the same amount.
That being said, the solutions are:
Append the annotations to the same (translated) group you put the axis in;
Set the scale's range with the margin...
.range([leftMargin, dimensions.boundedWidth - leftMargin - rightMargin])
... and then append everything to a non-translated group.

Putting the Z-Coordinate in the Highcharts Tooltip

I have three graphs. All three graphs have the same x axis values (category), different y-values, and the same z-value (date). The graphs have synced tooltips when you hover over a point. I want to be able to populate the tooltip with the z-coordinate for each point. I do not want to plot the z coordinate... just have it show in the tooltip. I am not sure how to do this because there are more multiple graphs with synced tooltips.
I made a basic example to show how to put the z-value (date) in a tooltip for one graph. https://codepen.io/austeng/pen/ZEGxWyK
Highcharts.chart('container', {
tooltip: {
formatter: function() {
return 'x: ' + this.x + ', y: ' + this.y + ', z: ' + Highcharts.dateFormat('%b/%e/%Y',
new Date(this.point.z));
}
},
xAxis:{
type: 'category'
},
series: [{
data: [{
x: 0,
y: 0,
z: 1564358400000
},
{
x: 1,
y: 5,
z: 1564531200000
},
{
x: 2,
y: 2,
z: 1564963200000
}
]
}]
});
This is my codepen for the three graphs: https://codepen.io/austeng/pen/gOppRWY
Any help on how to extend my example for one graph to my current code of three graphs w/sync tooltip would be very appreciated. Thanks.
I think that it will be better to achieve it in a different way.
Create some global function, let's say setTooltip which will take a point as a parameter.
For each chart config set the tooltip.pointFormatter callback which returns above function.
tooltip: {
pointFormatter() {
let point = this;
return setTooltip(point)
}
},
Use the keys feature to get the z value in the point object.
API: https://api.highcharts.com/highcharts/series.line.keys
Final output: https://jsfiddle.net/BlackLabel/sjv18rbn/

drawing multi colored custom symbols in highcharts

I need to draw custom markers on a highchart at particular intervals.
I have managed to create a custom bar using the following javascript:
Highcharts.Renderer.prototype.symbols.hline =
function(x, y, width, height) {
return ['M',x-30 ,y + height / 2,'L',x+width+30,y + width / 2];
};
https://jsfiddle.net/jimmain/9gqca584/5/
My problem is that I need to also draw a single pixel border around the pink box.
I am using a stacked bar chart for the chart.
Ideally I would also like to increase the padding underneath the bar (between the bar and the x-axis) but I am not sure it can be independently increased.
It's not clear to me how I can use the renderer to change color. I could just draw one black box, and then another smaller inset pink box on top, but I am not clear on how to change colors in the SVG renderer.
SVG's path can not have border, so solution is to use renderer.rect(): https://jsfiddle.net/BlackLabel/9gqca584/43/
Note: It's bar series, so chart is inverted, that means we need to swap x with y and height with width.
Snippet:
function addRect(chart) {
return chart.renderer.rect(
chart.yAxis[0].toPixels(5) - 4, // 4 = half width
chart.xAxis[0].toPixels(0),
8,
5
).attr({
fill: 'rgba(253,0,154,0.9)',
stroke: 'black',
'stroke-width': 2,
zIndex: 5
}).add();
}
function positionRect(chart, rect) {
rect.animate({
x: chart.yAxis[0].toPixels(5) - 4, // 4 = half width
y: chart.xAxis[0].toPixels(0) - chart.series[0].points[0].pointWidth / 2,
height: chart.series[0].points[0].pointWidth
});
}
$(function() {
$('#container').highcharts({
legend: {
enabled: false
},
chart: {
type: 'bar',
events: {
load: function() {
this.customRect = addRect(this);
positionRect(this, this.customRect);
},
redraw: function() {
positionRect(this, this.customRect)
}
}
},
...
});
});

Is any possible to custom split tooltip position?

Expect
shared series have independent position tooltip
Tried
According to the Highcharts document, I know the Highcharts.tooltip.positioner can make some custom to the tooltip, but while I search around, all of them are un-split tooltip. and failed in the split situation, so Is there any possible to custom split tooltip position?
http://jsfiddle.net/TabGre/fyxqsq4L/
UPD:
each point's tooltip just above it, just like positioner:
positioner: function () {
return {
x: this.plotX;
y: this.plotY + 100;
}
}
As I mentioned in the comment, currently a positioner callback does not affect a split tooltip. However, it is possible to overwrite the function which is responsible for rendering a split tooltip. It requires calculating position on your own.
If you want a split tooltip to be in the top left corner as in your fiddle
you need to overwrite Highcharts.Tooltip.prototype.renderSplit = function(labels, points) with the desired position for each box.
var yPos = 0;
each(boxes, function(box, i) {
var point = box.point,
series = point.series;
// Put the label in place
box.tt.attr({
// visibility: box.pos === undefined ? 'hidden' : 'inherit',
x: (rightAligned || point.isHeader ?
//box.x :
0 :
point.plotX + chart.plotLeft + pick(options.distance, 16)),
// y: box.pos + chart.plotTop,
y: yPos,
anchorX: point.isHeader ?
point.plotX + chart.plotLeft : point.plotX + series.xAxis.pos,
anchorY: point.isHeader ?
box.pos + chart.plotTop - 15 : point.plotY + series.yAxis.pos
});
yPos += box.size;
});
example: http://jsfiddle.net/tbguemvL/

Categories

Resources