From 0b135a263343bb77ca4f5c3804fde3759b1be494 Mon Sep 17 00:00:00 2001 From: "olau@iola.dk" Date: Fri, 21 Nov 2008 18:34:10 +0000 Subject: [PATCH] First stab at crosshair support git-svn-id: https://flot.googlecode.com/svn/trunk@115 1e0a6537-2640-0410-bfb7-f154510ff394 --- jquery.flot.js | 95 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/jquery.flot.js b/jquery.flot.js index c1cf451..54a31cc 100644 --- a/jquery.flot.js +++ b/jquery.flot.js @@ -94,6 +94,11 @@ mode: null, // one of null, "x", "y" or "xy" color: "#e8cfac" }, + crosshair: { + mode: null, // one of null, "x", "y" or "xy", + extendBeyondGrid: null, + color: "#aa0000" + }, shadowSize: 4 }, canvas = null, // the canvas for the plot itself @@ -117,6 +122,8 @@ this.getPlotOffset = function() { return plotOffset; }; this.getData = function() { return series; }; this.getAxes = function() { return axes; }; + this.setCrosshair = setCrosshair; + this.clearCrosshair = function () { setCrosshair(null); }; this.highlight = highlight; this.unhighlight = unhighlight; @@ -367,6 +374,9 @@ eventHolder.mousedown(onMouseDown); } + if (options.crosshair.mode != null) + eventHolder.mouseout(onMouseOut); + if (options.grid.clickable) eventHolder.click(onClick); } @@ -780,7 +790,7 @@ axis.labelHeight = 0; if (labels.length > 0) { var dummyDiv = $('
' - + labels.join("") + '
').appendTo(target); + + labels.join("") + '
').prependTo(target); axis.labelHeight = dummyDiv.height(); dummyDiv.remove(); } @@ -799,7 +809,7 @@ if (labels.length > 0) { var dummyDiv = $('
' - + labels.join("") + '
').appendTo(target); + + labels.join("") + '').prependTo(target); if (axis.labelWidth == null) axis.labelWidth = dummyDiv.width(); if (axis.labelHeight == null) @@ -1048,7 +1058,7 @@ html += ''; - target.append(html); + target.prepend(html); } function drawSeries(series) { @@ -1574,6 +1584,7 @@ selection = { first: { x: -1, y: -1}, second: { x: -1, y: -1}, show: false, active: false }, + crosshair = { pos: { x: -1, y: -1 } }, highlights = [], clickIsMouseUp = false, redrawTimeout = null, @@ -1663,17 +1674,20 @@ lastMousePos.pageY = e.pageY; } - if (options.grid.hoverable && !hoverTimeout) - hoverTimeout = setTimeout(onHover, 100); + if (options.grid.hoverable) + triggerClickHoverEvent("plothover", lastMousePos, + function (s) { return s["hoverable"] != false; }); + + if (options.crosshair.mode != null) { + setPositionFromEvent(crosshair.pos, e); + triggerRedrawOverlay(); + } if (selection.active) { - var r = null; - if (selectionIsSane()) - r = getSelectionForEvent(); + target.trigger("plotselecting", [ selectionIsSane() ? getSelectionForEvent() : null ]); - target.trigger("plotselecting", [ r ]); - updateSelection(lastMousePos); + crosshair.pos.x = -1; // hide the crosshair while selecting } } @@ -1701,6 +1715,13 @@ $(document).one("mouseup", onSelectionMouseUp); } + function onMouseOut(ev) { + if (options.crosshair.mode != null && crosshair.pos.x != -1) { + crosshair.pos.x = -1; + triggerRedrawOverlay(); + } + } + function onClick(e) { if (clickIsMouseUp) { clickIsMouseUp = false; @@ -1711,12 +1732,6 @@ function (s) { return s["clickable"] != false; }); } - function onHover() { - triggerClickHoverEvent("plothover", lastMousePos, - function (s) { return s["hoverable"] != false; }); - hoverTimeout = null; - } - // trigger click or hover event (they send the same parameters // so we share their code) function triggerClickHoverEvent(eventname, event, seriesFilter) { @@ -1782,7 +1797,6 @@ else drawPointHighlight(hi.series, hi.point); } - octx.restore(); // redraw selection if (selection.show && selectionIsSane()) { @@ -1796,9 +1810,23 @@ w = Math.abs(selection.second.x - selection.first.x), h = Math.abs(selection.second.y - selection.first.y); - octx.fillRect(x + plotOffset.left, y + plotOffset.top, w, h); - octx.strokeRect(x + plotOffset.left, y + plotOffset.top, w, h); + octx.fillRect(x, y, w, h); + octx.strokeRect(x, y, w, h); } + + // redraw crosshair + if (options.crosshair.mode != null && crosshair.pos.x != -1) { + octx.strokeStyle = parseColor(options.crosshair.color).scale(null, null, null, 0.8).toString(); + octx.lineWidth = 1; + ctx.lineJoin = "round"; + var pos = crosshair.pos; + octx.beginPath(); + octx.moveTo(pos.x, options.crosshair.extendBeyondGrid ? -plotOffset.top : 0); + octx.lineTo(pos.x, options.crosshair.extendBeyondGrid ? canvasHeight - plotOffset.top : plotHeight); + octx.stroke(); + + } + octx.restore(); } function highlight(s, point, auto) { @@ -1869,6 +1897,22 @@ 0, true, series.xaxis, series.yaxis, octx); } + function setPositionFromEvent(pos, e) { + var offset = eventHolder.offset(); + pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plotWidth); + pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plotHeight); + } + + function setCrosshair(pos) { + if (pos == null) + crosshair.pos.x = -1; + else { + crosshair.pos.x = clamp(0, pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plotWidth); + crosshair.pos.y = clamp(0, pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plotHeight); + } + triggerRedrawOverlay(); + } + function getSelectionForEvent() { var x1 = Math.min(selection.first.x, selection.second.x), x2 = Math.max(selection.first.x, selection.second.x), @@ -1920,17 +1964,14 @@ } function setSelectionPos(pos, e) { - var offset = eventHolder.offset(); + setPositionFromEvent(pos, e); + if (options.selection.mode == "y") { if (pos == selection.first) pos.x = 0; else pos.x = plotWidth; } - else { - pos.x = e.pageX - offset.left - plotOffset.left; - pos.x = Math.min(Math.max(0, pos.x), plotWidth); - } if (options.selection.mode == "x") { if (pos == selection.first) @@ -1938,10 +1979,6 @@ else pos.y = plotHeight; } - else { - pos.y = e.pageY - offset.top - plotOffset.top; - pos.y = Math.min(Math.max(0, pos.y), plotHeight); - } } function updateSelection(pos) { @@ -2021,7 +2058,7 @@ function clamp(min, value, max) { if (value < min) - return value; + return min; else if (value > max) return max; else