I have written a plugin for jQuery Flot charts which allows you to dynamically add data points by clicking on the line of a chart, remove them by right clicking and also it allows the dragging of these points around the canvas.
This works fine and I also have a tooltip displaying the Y value when you hover over or drag a point around.
What I would like to do is display a second tooltip when a user hovers over a line showing the message "Left-click to add a data point".
I can't seem to find a way to add a hover event to the line itself and there doesn't appear to be a native method.
Does anyone know how I might go about achieving this?
Thank you.
EDIT: here is a jsFiddle that includes the tooltip creation code that I am using:
jsFiddle
as you can see a tooltip renders when you hover over an actual datapoint, however I would like to find a way to fire have a seperate tooltip rendered when you hover over the line inbetween the datapoints. NOTE: this fiddle does NOT include my custom code to add and drag the datapoints dynamically as it would be too much code for the purposes of this question.
So basically we are looking to conditionally display a tooltip when the position of the cursor meets the requirement that it is over a line on the chart. Since lines are not an entity we can work with you need calculate the line between the nearest two points on either side of your cursor and then see if your current position lies on it. I simplified your example a bit:
Function to calculate distance between two points:
function lineDistance( p1x, p1y,p2x, p2y ) {
return Math.sqrt( (p2x - p1x)*(p2x - p1x) + (p2y-p1y)*(p2y-p1y) );
}
Assuming that your nearest two points are A and B to your cursor C then the distance AB
should equal AC + BC
.
So to determine if it is on the line: Math.abs(AB-(AC+BC)) < SomeThreshold
. Using the threshold essentially draws a box around the line which the cursor can fall inside of.
Then extending your code in the plothover
(jsFiddle)
$(placeholder).bind("plothover", function (event, pos, item) {
if (item) {
var tipText;
if (opts.xaxis.mode === "time" || opts.xaxes[0].mode === "time") {
tipText = stringFormat(to.content, item, timestampToDate);
} else {
tipText = stringFormat(to.content, item);
}
$tip.html(tipText).css({
left: tipPosition.x + to.shifts.x,
top: tipPosition.y + to.shifts.y
}).show();
} else {
// Extended for line hover
var series = plot.getData();
var xBeforeIndex = 0;
var xAfterIndex = -1;
var Threshold = 0.0000025;
var i = 1;
while (i <= series[0].data.length && xAfterIndex==-1) {
if (xAfterIndex == -1 && pos.x > series[0].data[i][0]) {
xBeforeIndex = i;
} else if (xAfterIndex == -1) {
xAfterIndex = i;
}
i++;
}
var onTheLine =
lineDistance(
series[0].data[xBeforeIndex][0]/10000,series[0].data[xBeforeIndex][1],
pos.x/10000, pos.y)
+lineDistance(pos.x/10000, pos.y,
series[0].data[xAfterIndex][0]/10000,series[0].data[xAfterIndex][1])
-lineDistance(
series[0].data[xBeforeIndex][0]/10000,series[0].data[xBeforeIndex][1],
series[0].data[xAfterIndex][0]/10000,series[0].data[xAfterIndex][1]);
if (Math.abs(onTheLine) < Threshold) {
tipText = "Found Line";
$tip.html(tipText).css({
left: tipPosition.x + to.shifts.x,
top: tipPosition.y + to.shifts.y
}).show();
} else {
$tip.hide().html('');
}
}
});
Things not done here:
Note, adding the second graph will require you to find the nearest points for both graphs and checking if it falls on either line. If your lines are close or intersecting you could just make one the priority line. If you struggle adding the second line back in I can help later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With