Highcharts: Positioning the toolip with chart.plotLeft - highcharts

In the highchart documentation is says:
positioner: Function
A callback function to place the tooltip in a default position. The callback receives three parameters: labelWidth, labelHeight and point, where point contains values for plotX and plotY telling where the reference point is in the plot area.
Add chart.plotLeft and chart.plotTop to get the full coordinates.
http://api.highcharts.com/highcharts#tooltip.positioner
But I'm not sure where I am supposed to add plotLeft, or plotTop
I don't see it on the scope, and I can't see it in the "chart" property options.
Can anyone explain?

Example for you: http://jsfiddle.net/j92p2/
tooltip: {
positioner: function (w, h, p) {
var chart = this.chart, // get chart
plotLeft = chart.plotLeft, // get plotLeft
plotTop = chart.plotTop; // get plotTop
console.log(this, plotTop, plotLeft); // watch console while hovering points
return { x: 80, y: 50 };
}
}
See inline comments. Let me know if you have any more questions.

Related

How to get clicked element's position and id to change color and draw lines on it

I'm developing a basic window frame configurator. I splitted glasses in function below. I want to change color when i clicked and get the position of clicked glass to draw openin direction lines.
I tried to understand and implement Lavrton's method(https://codesandbox.io/s/0xj7zml2zl?file=/src/index.js) but i couldn't succeed.
function glassDraw(piece, frameWidth, frameHeight) {
var glassGroup = new Konva.Group();
for (i = 0; i <piece; i++) {
var glass = new Konva.Rect({
name: 'Rect',
x: padding + (frameWidth / piece) * i,
y: padding,
width: frameWidth / piece,
height: frameHeight - padding * 2,
fill: 'lightblue',
id: 'glass'+i,
});
glassGroup.add(glass);
}
glassGroup.find("Rect").on('click', function (e) {
// get id of the cube i drag
var clickedId = e.target.attrs.id;
$('#theId').html(clickedId);
})
return glassGroup;
}
When i use getelementbyid method with id of konva element("glass"+i), it returns null. I think i need to get as a konva element.
You have to create a click listener for all of your rectangles.
for (let rect of glassGroup.children) {
rect.on('click', () => {
console.log(rect.x(), rect.y()); // current position of the object
console.log(rect.id()); // log id of the object
rect.fill('green'); // set color to green
layer.batchDraw(); // update layer (batchDraw just for better performance .draw() would work to)
})
}
Make sure you always update the stage by either call stage.draw() or layer.draw() (or batchDraw() for better performance) after changing something, otherwise your stage will not show anything of what you do.
If something with this code don't work feel free to ask.
Have a nice day.

Redrawing the tooltip inside of the tooltip positioner callback

I'm using the I'm currently using the tooltip formatter function to control the look of the tooltip, including adding some custom css to create an arrow on the side of the tooltip box facing the mouse. I am also using the positioner callback to not only determine the placement of the tooltip, but when it changes from one side of the mouse to the other I'm updating the formatter callback to switch the side of the tooltip the arrow lies on (see code below). Everything works fine, except for the very first point which causes the tooltip to switch sides of the mouse. Its clear that a tooltip's "formatter" function is called before the tooltips "positioner" function ( for reasons that are probably obvious ). However, it prevents me from correctly drawing the tooltip when it changes sides. What I really need to be able to do in the positioner callback is to update the formatter function, and then redraw the tooltip. Is that possible?
positioner: function (boxWidth, boxHeight, point) {
// Set up the variables
var chart = this.chart;
var plotLeft = chart.plotLeft;
var plotTop = chart.plotTop;
var plotWidth = chart.plotWidth;
var plotHeight = chart.plotHeight;
var distance = 40;
var pointX = point.plotX;
var pointY = point.plotY;
// Determine if we need to flip the tooltip from following on the left to
// following on the right
if ((pointX - boxWidth - distance) < plotLeft) {
x = pointX + distance;
chart.tooltip.options.formatter = function () {
// UPATE THE TOOLTIP FORMATTER HERE
};
}
}
Here is a js fiddle example of the issue
http://jsfiddle.net/bteWs/
If you go slowly, and notice the very first point where the switch happens the arrow will be point the wrong direction. After that it corrects ( as described in my post ). Just looking for a solution to get the correct behavior in this case.
You can always have enabled both classes for tooltip, and just remove inproper in positioner, see: http://jsfiddle.net/bteWs/3/
Default formatter:
formatter: function () {
var s = '<div id="custom-tooltip" class="tooltip-left tooltip-right">';
var chart = null;
s += "<div style='padding:5px;color:white'>Some Tooltip</div></div>";
return s;
},
And removing:
if ((pointX - boxWidth - distance) < plotLeft) {
x = pointX + 60;
$("#custom-tooltip").removeClass('tooltip-right');
}
else {
x = Math.max(plotLeft, pointX - boxWidth - 10);
$("#custom-tooltip").removeClass('tooltip-left');
}
I had the same issue. The problem is that positioner is begin called after the formatter. I made a fix to your jsfiddle. It's a huge hack but you can see how you can overcome your problem.
In the fix, I made use of a global. You don't need to but I hacked your fiddle in a hurry. I also got rid of some of your duplicate code.
The trick is to force a refresh on the tooltip after the tooltip switch sides.
positioner: function (boxWidth, boxHeight, point) {
// Set up the variables
var chart = this.chart;
var plotLeft = chart.plotLeft;
var plotTop = chart.plotTop;
var plotWidth = chart.plotWidth;
var plotHeight = chart.plotHeight;
var distance = 40;
var pointX = point.plotX;
var pointY = point.plotY;
var refreshTooltip = false;
var previousAlign = chart.align;
if ((pointX - boxWidth - distance) < plotLeft) {
x = pointX + 60;
chart.align = "left";
}
else {
x = Math.max(plotLeft, pointX - boxWidth - 10);
chart.align = "right";
}
y = Math.min(plotTop + plotHeight - boxHeight, Math.max(plotTop, pointY - boxHeight + plotTop + boxHeight / 2));
if (previousAlign != null && chart.align != previousAlign) {
chart.tooltip.refresh(activePoint);
}
return { x: x, y: y };
}
See the complete fiddle here:
http://jsfiddle.net/anber500/bteWs/1/

What are the plotX, plotY values of a point in HighCharts?

What are the plotX, plotY values of a point in HighCharts? I can't find them in the documentation. I read the values but couldn't make sense of them when using a pixel ruler on the graph.
plotX and plotY are not part of API - just inner properties to get coordinates where plot point. Using them is shorthand for getting values from point:
http://api.highcharts.com/highcharts#Point.x
http://api.highcharts.com/highcharts#Point.y
And translating to position via:
http://api.highcharts.com/highcharts#Axis.toPixels()
plotX and plotY are the reference point in the plot area, chart.plotLeft and chart.plotTop get the full coordinates.
Check the API for tooltip->positioner
http://api.highcharts.com/highcharts#tooltip.positioner
jsFiddle: http://jsfiddle.net/m9L5j/
tooltip: {
positioner: function () {
return { x: 80, y: 50 };
}
}

highcharts 3 addPoint Point order

In Highcharts 2, it was easy to add a point using series.addPoint(p) where the x value of that point fell between the x-values of two existing points.
Example: Let's say you wanted to create a chart with one series containing two points:
var p1 = {x: 100, y: 50};
var p2 = {x: 200, y: 40};
var data = [];
data.push(p1);
data.push(p1);
var c = new Highcharts.Chart({
...//code omitted
type: 'line',
data: data,
...//code omitted
});
In version two you could call add a point between those two by going:
var p3 = {x: 150, y: 60};
c.series[0].addPoint(p3, true);
For 'line' charts, highcharts 2 would automatically determine that the x value of p3 falls between the x values of p1 and p2 and so the line would be plotted through the points in the order: p1, p3, p2.
We are finding that in highcharts 3, the line gets plotted through the points in the order p1, p2, p3 - which implies that it "turns back on itself".
I have prepared the following jsFiddle examples, which add 50 points to an existing series with randomized x and y value.:
Highcharts 2.1.9: http://jsfiddle.net/HdNh2/4/
Highcharts 3.0.0: http://jsfiddle.net/HdNh2/5/
Is this something that could be fixed or do we need to try and circumvent the issue?
Thanks in advance...
H
So just to close this issue: Highcharts has confirmed that the logic changed since 2.2.x.
In our case it was simple enough to just re-render the entire chart, but I suspect series.setData() would also have been an option.
Here's a workaround. This will sort points on their x-values as they're added manually. This events object is in the chart object options block.
events: {
click: function(e) {
// find the clicked values and the series
var series = this.series[DIA.currentSeriesIndex],
x = parseFloat(e.xAxis[0].value),
y = parseFloat(e.yAxis[0].value);
// Add it
series.addPoint([x, y]);
if ( series.data.length > 1) {
// grab last point object in array
var point = series.data[series.data.length-1];
// sort the point objects on their x values
series.data.sort(function (a, b)
{
//Compare "a" and "b" and return -1, 0, or 1
return (a.x - b.x);
});
// force a redraw
point.update();
}
}
}

JQplot tooltip for multiple y axes

For a JQplot chart with 2 y axes, I am able to set the tooltip but when i hover over a datapoint i need to know to which y axis the tooltip belongs. I need this so that i can display the tooltip after multiplying with the appropriate scale factor. The code i tried is shown below. I thought y will be null when we hover over a data point belonging to y2 axis. But y is never null.
$("#"+sTargetId).bind('jqplotcustomDataMouseOver',
function (ev, seriesIndex, pointIndex, data) {
var chart_left = $("#"+sTargetId).offset().left,
chart_right = ($(window).width() - ($("#"+sTargetId).offset().left + $("#"+sTargetId).outerWidth())),
chart_top = $("#"+sTargetId).offset().top,
x = oPlot.axes.xaxis.u2p(data[0]),
y = oPlot.axes.yaxis.u2p(data[1]),
y2 = oPlot.axes.y2axis.u2p(data[1]);;
if(y===null|| y===undefined){ //this condition doesnt work
var tooltipDataYaxis = data[1]*scaleYaxis1;
var sYDisplay = this.sYAxis1MeasureName;
$('#tooltip').css({left:chart_left+x, top:chart_top+y, marginRight:chart_right});
}
else{
tooltipDataYaxis = data[1]*scaleYaxis2;
sYDisplay = this.sYAxis2MeasureName;
$('#tooltip').css({left:chart_left+x, top:chart_top+y2, marginRight:chart_right});
}
$('#tooltip').html(
'<span style="font-family: Arial;font-size:'+sTooltip+';font:bold;color:#000000;">'+ sYDisplay+': ' + tooltipDataYaxis +'</span>');
$('#tooltip').show();
});
$("#"+sTargetId).bind('jqplotcustomDataUnhighlight',
function (ev, seriesIndex, pointIndex, data) {
$('#tooltip').empty();
$('#tooltip').hide();
});
}
The variable seriesIndex will help to identify which series the tooltip belongs to. :)
I was just playing with jqplot for the first time. quite fun.
In the highlighter plugin jqplot.highlighter.js
I extended it on line 336
elem.html(str + " component:"+neighbor.data[2]);
You might use Chrome developer tools to get the data model at this point and look at the contents of the neighbor object.
(scope variables > Local > neighbor > data )
That's how I did it anywho. Hope it helps.

Resources