123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798 |
- /* Flot plugin for adding the ability to pan and zoom the plot.
- Copyright (c) 2007-2014 IOLA and Ole Laursen.
- Copyright (c) 2016 Ciprian Ceteras.
- Copyright (c) 2017 Raluca Portase.
- Licensed under the MIT license.
- */
- /**
- ## jquery.flot.navigate.js
- This flot plugin is used for adding the ability to pan and zoom the plot.
- A higher level overview is available at [interactions](interactions.md) documentation.
- The default behaviour is scrollwheel up/down to zoom in, drag
- to pan. The plugin defines plot.zoom({ center }), plot.zoomOut() and
- plot.pan( offset ) so you easily can add custom controls. It also fires
- "plotpan" and "plotzoom" events, useful for synchronizing plots.
- The plugin supports these options:
- ```js
- zoom: {
- interactive: false,
- active: false,
- amount: 1.5 // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
- }
- pan: {
- interactive: false,
- active: false,
- cursor: "move", // CSS mouse cursor value used when dragging, e.g. "pointer"
- frameRate: 60,
- mode: "smart" // enable smart pan mode
- }
- xaxis: {
- axisZoom: true, //zoom axis when mouse over it is allowed
- plotZoom: true, //zoom axis is allowed for plot zoom
- axisPan: true, //pan axis when mouse over it is allowed
- plotPan: true //pan axis is allowed for plot pan
- }
- yaxis: {
- axisZoom: true, //zoom axis when mouse over it is allowed
- plotZoom: true, //zoom axis is allowed for plot zoom
- axisPan: true, //pan axis when mouse over it is allowed
- plotPan: true //pan axis is allowed for plot pan
- }
- ```
- **interactive** enables the built-in drag/click behaviour. If you enable
- interactive for pan, then you'll have a basic plot that supports moving
- around; the same for zoom.
- **active** is true after a touch tap on plot. This enables plot navigation.
- Once activated, zoom and pan cannot be deactivated. When the plot becomes active,
- "plotactivated" event is triggered.
- **amount** specifies the default amount to zoom in (so 1.5 = 150%) relative to
- the current viewport.
- **cursor** is a standard CSS mouse cursor string used for visual feedback to the
- user when dragging.
- **frameRate** specifies the maximum number of times per second the plot will
- update itself while the user is panning around on it (set to null to disable
- intermediate pans, the plot will then not update until the mouse button is
- released).
- **mode** a string specifies the pan mode for mouse interaction. Accepted values:
- 'manual': no pan hint or direction snapping;
- 'smart': The graph shows pan hint bar and the pan movement will snap
- to one direction when the drag direction is close to it;
- 'smartLock'. The graph shows pan hint bar and the pan movement will always
- snap to a direction that the drag diorection started with.
- Example API usage:
- ```js
- plot = $.plot(...);
- // zoom default amount in on the pixel ( 10, 20 )
- plot.zoom({ center: { left: 10, top: 20 } });
- // zoom out again
- plot.zoomOut({ center: { left: 10, top: 20 } });
- // zoom 200% in on the pixel (10, 20)
- plot.zoom({ amount: 2, center: { left: 10, top: 20 } });
- // pan 100 pixels to the left (changing x-range in a positive way) and 20 down
- plot.pan({ left: -100, top: 20 })
- ```
- Here, "center" specifies where the center of the zooming should happen. Note
- that this is defined in pixel space, not the space of the data points (you can
- use the p2c helpers on the axes in Flot to help you convert between these).
- **amount** is the amount to zoom the viewport relative to the current range, so
- 1 is 100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out). You
- can set the default in the options.
- */
- /* eslint-enable */
- (function($) {
- 'use strict';
- var options = {
- zoom: {
- interactive: false,
- active: false,
- amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
- },
- pan: {
- interactive: false,
- active: false,
- cursor: "move",
- frameRate: 60,
- mode: 'smart'
- },
- recenter: {
- interactive: true
- },
- xaxis: {
- axisZoom: true, //zoom axis when mouse over it is allowed
- plotZoom: true, //zoom axis is allowed for plot zoom
- axisPan: true, //pan axis when mouse over it is allowed
- plotPan: true //pan axis is allowed for plot pan
- },
- yaxis: {
- axisZoom: true,
- plotZoom: true,
- axisPan: true,
- plotPan: true
- }
- };
- var saturated = $.plot.saturated;
- var browser = $.plot.browser;
- var SNAPPING_CONSTANT = $.plot.uiConstants.SNAPPING_CONSTANT;
- var PANHINT_LENGTH_CONSTANT = $.plot.uiConstants.PANHINT_LENGTH_CONSTANT;
- function init(plot) {
- plot.hooks.processOptions.push(initNevigation);
- }
- function initNevigation(plot, options) {
- var panAxes = null;
- var canDrag = false;
- var useManualPan = options.pan.mode === 'manual',
- smartPanLock = options.pan.mode === 'smartLock',
- useSmartPan = smartPanLock || options.pan.mode === 'smart';
- function onZoomClick(e, zoomOut, amount) {
- var page = browser.getPageXY(e);
- var c = plot.offset();
- c.left = page.X - c.left;
- c.top = page.Y - c.top;
- var ec = plot.getPlaceholder().offset();
- ec.left = page.X - ec.left;
- ec.top = page.Y - ec.top;
- var axes = plot.getXAxes().concat(plot.getYAxes()).filter(function (axis) {
- var box = axis.box;
- if (box !== undefined) {
- return (ec.left > box.left) && (ec.left < box.left + box.width) &&
- (ec.top > box.top) && (ec.top < box.top + box.height);
- }
- });
- if (axes.length === 0) {
- axes = undefined;
- }
- if (zoomOut) {
- plot.zoomOut({
- center: c,
- axes: axes,
- amount: amount
- });
- } else {
- plot.zoom({
- center: c,
- axes: axes,
- amount: amount
- });
- }
- }
- var prevCursor = 'default',
- panHint = null,
- panTimeout = null,
- plotState,
- prevDragPosition = { x: 0, y: 0 },
- isPanAction = false;
- function onMouseWheel(e, delta) {
- var maxAbsoluteDeltaOnMac = 1,
- isMacScroll = Math.abs(e.originalEvent.deltaY) <= maxAbsoluteDeltaOnMac,
- defaultNonMacScrollAmount = null,
- macMagicRatio = 50,
- amount = isMacScroll ? 1 + Math.abs(e.originalEvent.deltaY) / macMagicRatio : defaultNonMacScrollAmount;
- if (isPanAction) {
- onDragEnd(e);
- }
- if (plot.getOptions().zoom.active) {
- e.preventDefault();
- onZoomClick(e, delta < 0, amount);
- return false;
- }
- }
- plot.navigationState = function(startPageX, startPageY) {
- var axes = this.getAxes();
- var result = {};
- Object.keys(axes).forEach(function(axisName) {
- var axis = axes[axisName];
- result[axisName] = {
- navigationOffset: { below: axis.options.offset.below || 0,
- above: axis.options.offset.above || 0},
- axisMin: axis.min,
- axisMax: axis.max,
- diagMode: false
- }
- });
- result.startPageX = startPageX || 0;
- result.startPageY = startPageY || 0;
- return result;
- }
- function onMouseDown(e) {
- canDrag = true;
- }
- function onMouseUp(e) {
- canDrag = false;
- }
- function isLeftMouseButtonPressed(e) {
- return e.button === 0;
- }
- function onDragStart(e) {
- if (!canDrag || !isLeftMouseButtonPressed(e)) {
- return false;
- }
- isPanAction = true;
- var page = browser.getPageXY(e);
- var ec = plot.getPlaceholder().offset();
- ec.left = page.X - ec.left;
- ec.top = page.Y - ec.top;
- panAxes = plot.getXAxes().concat(plot.getYAxes()).filter(function (axis) {
- var box = axis.box;
- if (box !== undefined) {
- return (ec.left > box.left) && (ec.left < box.left + box.width) &&
- (ec.top > box.top) && (ec.top < box.top + box.height);
- }
- });
- if (panAxes.length === 0) {
- panAxes = undefined;
- }
- var c = plot.getPlaceholder().css('cursor');
- if (c) {
- prevCursor = c;
- }
- plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor);
- if (useSmartPan) {
- plotState = plot.navigationState(page.X, page.Y);
- } else if (useManualPan) {
- prevDragPosition.x = page.X;
- prevDragPosition.y = page.Y;
- }
- }
-
- function onDrag(e) {
- if (!isPanAction) {
- return;
- }
- var page = browser.getPageXY(e);
- var frameRate = plot.getOptions().pan.frameRate;
- if (frameRate === -1) {
- if (useSmartPan) {
- plot.smartPan({
- x: plotState.startPageX - page.X,
- y: plotState.startPageY - page.Y
- }, plotState, panAxes, false, smartPanLock);
- } else if (useManualPan) {
- plot.pan({
- left: prevDragPosition.x - page.X,
- top: prevDragPosition.y - page.Y,
- axes: panAxes
- });
- prevDragPosition.x = page.X;
- prevDragPosition.y = page.Y;
- }
- return;
- }
- if (panTimeout || !frameRate) return;
- panTimeout = setTimeout(function() {
- if (useSmartPan) {
- plot.smartPan({
- x: plotState.startPageX - page.X,
- y: plotState.startPageY - page.Y
- }, plotState, panAxes, false, smartPanLock);
- } else if (useManualPan) {
- plot.pan({
- left: prevDragPosition.x - page.X,
- top: prevDragPosition.y - page.Y,
- axes: panAxes
- });
- prevDragPosition.x = page.X;
- prevDragPosition.y = page.Y;
- }
- panTimeout = null;
- }, 1 / frameRate * 1000);
- }
- function onDragEnd(e) {
- if (!isPanAction) {
- return;
- }
- if (panTimeout) {
- clearTimeout(panTimeout);
- panTimeout = null;
- }
- isPanAction = false;
- var page = browser.getPageXY(e);
- plot.getPlaceholder().css('cursor', prevCursor);
- if (useSmartPan) {
- plot.smartPan({
- x: plotState.startPageX - page.X,
- y: plotState.startPageY - page.Y
- }, plotState, panAxes, false, smartPanLock);
- plot.smartPan.end();
- } else if (useManualPan) {
- plot.pan({
- left: prevDragPosition.x - page.X,
- top: prevDragPosition.y - page.Y,
- axes: panAxes
- });
- prevDragPosition.x = 0;
- prevDragPosition.y = 0;
- }
- }
- function onDblClick(e) {
- plot.activate();
- var o = plot.getOptions()
- if (!o.recenter.interactive) { return; }
- var axes = plot.getTouchedAxis(e.clientX, e.clientY),
- event;
- plot.recenter({ axes: axes[0] ? axes : null });
- if (axes[0]) {
- event = new $.Event('re-center', { detail: {
- axisTouched: axes[0]
- }});
- } else {
- event = new $.Event('re-center', { detail: e });
- }
- plot.getPlaceholder().trigger(event);
- }
- function onClick(e) {
- plot.activate();
- if (isPanAction) {
- onDragEnd(e);
- }
- return false;
- }
- plot.activate = function() {
- var o = plot.getOptions();
- if (!o.pan.active || !o.zoom.active) {
- o.pan.active = true;
- o.zoom.active = true;
- plot.getPlaceholder().trigger("plotactivated", [plot]);
- }
- }
- function bindEvents(plot, eventHolder) {
- var o = plot.getOptions();
- if (o.zoom.interactive) {
- eventHolder.mousewheel(onMouseWheel);
- }
- if (o.pan.interactive) {
- plot.addEventHandler("dragstart", onDragStart, eventHolder, 0);
- plot.addEventHandler("drag", onDrag, eventHolder, 0);
- plot.addEventHandler("dragend", onDragEnd, eventHolder, 0);
- eventHolder.bind("mousedown", onMouseDown);
- eventHolder.bind("mouseup", onMouseUp);
- }
- eventHolder.dblclick(onDblClick);
- eventHolder.click(onClick);
- }
- plot.zoomOut = function(args) {
- if (!args) {
- args = {};
- }
- if (!args.amount) {
- args.amount = plot.getOptions().zoom.amount;
- }
- args.amount = 1 / args.amount;
- plot.zoom(args);
- };
- plot.zoom = function(args) {
- if (!args) {
- args = {};
- }
- var c = args.center,
- amount = args.amount || plot.getOptions().zoom.amount,
- w = plot.width(),
- h = plot.height(),
- axes = args.axes || plot.getAxes();
- if (!c) {
- c = {
- left: w / 2,
- top: h / 2
- };
- }
- var xf = c.left / w,
- yf = c.top / h,
- minmax = {
- x: {
- min: c.left - xf * w / amount,
- max: c.left + (1 - xf) * w / amount
- },
- y: {
- min: c.top - yf * h / amount,
- max: c.top + (1 - yf) * h / amount
- }
- };
- for (var key in axes) {
- if (!axes.hasOwnProperty(key)) {
- continue;
- }
- var axis = axes[key],
- opts = axis.options,
- min = minmax[axis.direction].min,
- max = minmax[axis.direction].max,
- navigationOffset = axis.options.offset;
- //skip axis without axisZoom when zooming only on certain axis or axis without plotZoom for zoom on entire plot
- if ((!opts.axisZoom && args.axes) || (!args.axes && !opts.plotZoom)) {
- continue;
- }
- min = $.plot.saturated.saturate(axis.c2p(min));
- max = $.plot.saturated.saturate(axis.c2p(max));
- if (min > max) {
- // make sure min < max
- var tmp = min;
- min = max;
- max = tmp;
- }
- var offsetBelow = $.plot.saturated.saturate(navigationOffset.below - (axis.min - min));
- var offsetAbove = $.plot.saturated.saturate(navigationOffset.above - (axis.max - max));
- opts.offset = { below: offsetBelow, above: offsetAbove };
- };
- plot.setupGrid(true);
- plot.draw();
- if (!args.preventEvent) {
- plot.getPlaceholder().trigger("plotzoom", [plot, args]);
- }
- };
- plot.pan = function(args) {
- var delta = {
- x: +args.left,
- y: +args.top
- };
- if (isNaN(delta.x)) delta.x = 0;
- if (isNaN(delta.y)) delta.y = 0;
- $.each(args.axes || plot.getAxes(), function(_, axis) {
- var opts = axis.options,
- d = delta[axis.direction];
- //skip axis without axisPan when panning only on certain axis or axis without plotPan for pan the entire plot
- if ((!opts.axisPan && args.axes) || (!opts.plotPan && !args.axes)) {
- return;
- }
- if (d !== 0) {
- var navigationOffsetBelow = saturated.saturate(axis.c2p(axis.p2c(axis.min) + d) - axis.c2p(axis.p2c(axis.min))),
- navigationOffsetAbove = saturated.saturate(axis.c2p(axis.p2c(axis.max) + d) - axis.c2p(axis.p2c(axis.max)));
- if (!isFinite(navigationOffsetBelow)) {
- navigationOffsetBelow = 0;
- }
- if (!isFinite(navigationOffsetAbove)) {
- navigationOffsetAbove = 0;
- }
- opts.offset = {
- below: saturated.saturate(navigationOffsetBelow + (opts.offset.below || 0)),
- above: saturated.saturate(navigationOffsetAbove + (opts.offset.above || 0))
- };
- }
- });
- plot.setupGrid(true);
- plot.draw();
- if (!args.preventEvent) {
- plot.getPlaceholder().trigger("plotpan", [plot, args]);
- }
- };
- plot.recenter = function(args) {
- $.each(args.axes || plot.getAxes(), function(_, axis) {
- if (args.axes) {
- if (this.direction === 'x') {
- axis.options.offset = { below: 0 };
- } else if (this.direction === 'y') {
- axis.options.offset = { above: 0 };
- }
- } else {
- axis.options.offset = { below: 0, above: 0 };
- }
- });
- plot.setupGrid(true);
- plot.draw();
- };
- var shouldSnap = function(delta) {
- return (Math.abs(delta.y) < SNAPPING_CONSTANT && Math.abs(delta.x) >= SNAPPING_CONSTANT) ||
- (Math.abs(delta.x) < SNAPPING_CONSTANT && Math.abs(delta.y) >= SNAPPING_CONSTANT);
- }
- // adjust delta so the pan action is constrained on the vertical or horizontal direction
- // it the movements in the other direction are small
- var adjustDeltaToSnap = function(delta) {
- if (Math.abs(delta.x) < SNAPPING_CONSTANT && Math.abs(delta.y) >= SNAPPING_CONSTANT) {
- return {x: 0, y: delta.y};
- }
- if (Math.abs(delta.y) < SNAPPING_CONSTANT && Math.abs(delta.x) >= SNAPPING_CONSTANT) {
- return {x: delta.x, y: 0};
- }
- return delta;
- }
- var lockedDirection = null;
- var lockDeltaDirection = function(delta) {
- if (!lockedDirection && Math.max(Math.abs(delta.x), Math.abs(delta.y)) >= SNAPPING_CONSTANT) {
- lockedDirection = Math.abs(delta.x) < Math.abs(delta.y) ? 'y' : 'x';
- }
- switch (lockedDirection) {
- case 'x':
- return { x: delta.x, y: 0 };
- case 'y':
- return { x: 0, y: delta.y };
- default:
- return { x: 0, y: 0 };
- }
- }
- var isDiagonalMode = function(delta) {
- if (Math.abs(delta.x) > 0 && Math.abs(delta.y) > 0) {
- return true;
- }
- return false;
- }
- var restoreAxisOffset = function(axes, initialState, delta) {
- var axis;
- Object.keys(axes).forEach(function(axisName) {
- axis = axes[axisName];
- if (delta[axis.direction] === 0) {
- axis.options.offset.below = initialState[axisName].navigationOffset.below;
- axis.options.offset.above = initialState[axisName].navigationOffset.above;
- }
- });
- }
- var prevDelta = { x: 0, y: 0 };
- plot.smartPan = function(delta, initialState, panAxes, preventEvent, smartLock) {
- var snap = smartLock ? true : shouldSnap(delta),
- axes = plot.getAxes(),
- opts;
- delta = smartLock ? lockDeltaDirection(delta) : adjustDeltaToSnap(delta);
- if (isDiagonalMode(delta)) {
- initialState.diagMode = true;
- }
- if (snap && initialState.diagMode === true) {
- initialState.diagMode = false;
- restoreAxisOffset(axes, initialState, delta);
- }
- if (snap) {
- panHint = {
- start: {
- x: initialState.startPageX - plot.offset().left + plot.getPlotOffset().left,
- y: initialState.startPageY - plot.offset().top + plot.getPlotOffset().top
- },
- end: {
- x: initialState.startPageX - delta.x - plot.offset().left + plot.getPlotOffset().left,
- y: initialState.startPageY - delta.y - plot.offset().top + plot.getPlotOffset().top
- }
- }
- } else {
- panHint = {
- start: {
- x: initialState.startPageX - plot.offset().left + plot.getPlotOffset().left,
- y: initialState.startPageY - plot.offset().top + plot.getPlotOffset().top
- },
- end: false
- }
- }
- if (isNaN(delta.x)) delta.x = 0;
- if (isNaN(delta.y)) delta.y = 0;
- if (panAxes) {
- axes = panAxes;
- }
- var axis, axisMin, axisMax, p, d;
- Object.keys(axes).forEach(function(axisName) {
- axis = axes[axisName];
- axisMin = axis.min;
- axisMax = axis.max;
- opts = axis.options;
- d = delta[axis.direction];
- p = prevDelta[axis.direction];
- //skip axis without axisPan when panning only on certain axis or axis without plotPan for pan the entire plot
- if ((!opts.axisPan && panAxes) || (!panAxes && !opts.plotPan)) {
- return;
- }
- if (d !== 0) {
- var navigationOffsetBelow = saturated.saturate(axis.c2p(axis.p2c(axisMin) - (p - d)) - axis.c2p(axis.p2c(axisMin))),
- navigationOffsetAbove = saturated.saturate(axis.c2p(axis.p2c(axisMax) - (p - d)) - axis.c2p(axis.p2c(axisMax)));
- if (!isFinite(navigationOffsetBelow)) {
- navigationOffsetBelow = 0;
- }
- if (!isFinite(navigationOffsetAbove)) {
- navigationOffsetAbove = 0;
- }
- axis.options.offset.below = saturated.saturate(navigationOffsetBelow + (axis.options.offset.below || 0));
- axis.options.offset.above = saturated.saturate(navigationOffsetAbove + (axis.options.offset.above || 0));
- }
- });
- prevDelta = delta;
- plot.setupGrid(true);
- plot.draw();
- if (!preventEvent) {
- plot.getPlaceholder().trigger("plotpan", [plot, delta, panAxes, initialState]);
- }
- };
- plot.smartPan.end = function() {
- panHint = null;
- lockedDirection = null;
- prevDelta = { x: 0, y: 0 };
- plot.triggerRedrawOverlay();
- }
- function shutdown(plot, eventHolder) {
- eventHolder.unbind("mousewheel", onMouseWheel);
- eventHolder.unbind("mousedown", onMouseDown);
- eventHolder.unbind("mouseup", onMouseUp);
- eventHolder.unbind("dragstart", onDragStart);
- eventHolder.unbind("drag", onDrag);
- eventHolder.unbind("dragend", onDragEnd);
- eventHolder.unbind("dblclick", onDblClick);
- eventHolder.unbind("click", onClick);
- if (panTimeout) clearTimeout(panTimeout);
- }
- function drawOverlay(plot, ctx) {
- if (panHint) {
- ctx.strokeStyle = 'rgba(96, 160, 208, 0.7)';
- ctx.lineWidth = 2;
- ctx.lineJoin = "round";
- var startx = Math.round(panHint.start.x),
- starty = Math.round(panHint.start.y),
- endx, endy;
- if (panAxes) {
- if (panAxes[0].direction === 'x') {
- endy = Math.round(panHint.start.y);
- endx = Math.round(panHint.end.x);
- } else if (panAxes[0].direction === 'y') {
- endx = Math.round(panHint.start.x);
- endy = Math.round(panHint.end.y);
- }
- } else {
- endx = Math.round(panHint.end.x);
- endy = Math.round(panHint.end.y);
- }
- ctx.beginPath();
- if (panHint.end === false) {
- ctx.moveTo(startx, starty - PANHINT_LENGTH_CONSTANT);
- ctx.lineTo(startx, starty + PANHINT_LENGTH_CONSTANT);
- ctx.moveTo(startx + PANHINT_LENGTH_CONSTANT, starty);
- ctx.lineTo(startx - PANHINT_LENGTH_CONSTANT, starty);
- } else {
- var dirX = starty === endy;
- ctx.moveTo(startx - (dirX ? 0 : PANHINT_LENGTH_CONSTANT), starty - (dirX ? PANHINT_LENGTH_CONSTANT : 0));
- ctx.lineTo(startx + (dirX ? 0 : PANHINT_LENGTH_CONSTANT), starty + (dirX ? PANHINT_LENGTH_CONSTANT : 0));
- ctx.moveTo(startx, starty);
- ctx.lineTo(endx, endy);
- ctx.moveTo(endx - (dirX ? 0 : PANHINT_LENGTH_CONSTANT), endy - (dirX ? PANHINT_LENGTH_CONSTANT : 0));
- ctx.lineTo(endx + (dirX ? 0 : PANHINT_LENGTH_CONSTANT), endy + (dirX ? PANHINT_LENGTH_CONSTANT : 0));
- }
- ctx.stroke();
- }
- }
- plot.getTouchedAxis = function(touchPointX, touchPointY) {
- var ec = plot.getPlaceholder().offset();
- ec.left = touchPointX - ec.left;
- ec.top = touchPointY - ec.top;
- var axis = plot.getXAxes().concat(plot.getYAxes()).filter(function (axis) {
- var box = axis.box;
- if (box !== undefined) {
- return (ec.left > box.left) && (ec.left < box.left + box.width) &&
- (ec.top > box.top) && (ec.top < box.top + box.height);
- }
- });
- return axis;
- }
- plot.hooks.drawOverlay.push(drawOverlay);
- plot.hooks.bindEvents.push(bindEvents);
- plot.hooks.shutdown.push(shutdown);
- }
- $.plot.plugins.push({
- init: init,
- options: options,
- name: 'navigate',
- version: '1.3'
- });
- })(jQuery);
|