From 56a1e0600a39ac896ec58bec1a638bccdf40d37a Mon Sep 17 00:00:00 2001 From: Petr Shevtsov <petr.shevtsov@gmail.com> Date: Tue, 21 Apr 2015 11:49:44 -0400 Subject: [PATCH] Crosshair plugin --- extras/crosshair.js | 87 ++++++++++++++++++++++++++++++++++++++++++ tests/crosshair.html | 105 +++++++++++++++++++++++++-------------------------- 2 files changed, 138 insertions(+), 54 deletions(-) create mode 100644 extras/crosshair.js diff --git a/extras/crosshair.js b/extras/crosshair.js new file mode 100644 index 0000000..0df61d4 --- /dev/null +++ b/extras/crosshair.js @@ -0,0 +1,87 @@ +/** + * @license + * Copyright 2015 Petr Shevtsov (petr.shevtsov@gmail.com) + * MIT-licensed (http://opensource.org/licenses/MIT) + */ + +/*global Dygraph:false */ +/*jshint globalstrict: true */ +Dygraph.Plugins.Crosshair = (function() { + "use strict"; + + /** + * Creates the crosshair + * + * @constructor + */ + + var crosshair = function(opt_options) { + this.canvas_ = document.createElement("canvas"); + opt_options = opt_options || {}; + this.direction_ = opt_options.direction || null; + }; + + crosshair.prototype.toString = function() { + return "Crosshair Plugin"; + }; + + /** + * @param {Dygraph} g Graph instance. + * @return {object.<string, function(ev)>} Mapping of event names to callbacks. + */ + crosshair.prototype.activate = function(g) { + g.graphDiv.appendChild(this.canvas_); + + return { + select: this.select, + deselect: this.deselect + }; + }; + + crosshair.prototype.select = function(e) { + if (this.direction_ === null) { + return; + } + + var width = e.dygraph.width_; + var height = e.dygraph.height_; + this.canvas_.width = width; + this.canvas_.height = height; + this.canvas_.style.width = width + "px"; // for IE + this.canvas_.style.height = height + "px"; // for IE + + var ctx = this.canvas_.getContext("2d"); + ctx.clearRect(0, 0, width, height); + ctx.strokeStyle = "rgba(0, 0, 0,0.3)"; + ctx.beginPath(); + + var canvasx = Math.floor(e.dygraph.selPoints_[0].canvasx) + 0.5; // crisper rendering + + if (this.direction_ === "vertical" || this.direction_ === "both") { + ctx.moveTo(canvasx, 0); + ctx.lineTo(canvasx, height); + } + + if (this.direction_ === "horizontal" || this.direction_ === "both") { + for (var i = 0; i < e.dygraph.selPoints_.length; i++) { + var canvasy = Math.floor(e.dygraph.selPoints_[i].canvasy) + 0.5; // crisper rendering + ctx.moveTo(0, canvasy); + ctx.lineTo(width, canvasy); + } + } + + ctx.stroke(); + ctx.closePath(); + }; + + crosshair.prototype.deselect = function(e) { + var ctx = this.canvas_.getContext("2d"); + ctx.clearRect(0, 0, this.canvas_.width, this.canvas_.height); + }; + + crosshair.prototype.destroy = function() { + this.canvas_ = null; + }; + + return crosshair; +})(); diff --git a/tests/crosshair.html b/tests/crosshair.html index 422e8e2..89aaf1d 100644 --- a/tests/crosshair.html +++ b/tests/crosshair.html @@ -8,69 +8,66 @@ --> <script type="text/javascript" src="../dygraph-dev.js"></script> + <script type="text/javascript" src="../extras/crosshair.js"></script> <script type="text/javascript" src="data.js"></script> - <style type="text/css"> - .line { - visibility: hidden; - background-color: black; - position: absolute; - pointer-events: none; /* let mouse events fall through to the chart */ - } - .yline { - width: 100%; - height: 1px; - } - .xline { - height: 100%; - width: 1px; - } - </style> </head> <body> - <p>Hover, click and zoom to test the callbacks:</p> - <div id="div_g" style="width:600px; height:300px; position:relative;"> + <p>Vertical crosshair:</p> + <div id="div_g_v" style="width:600px; height:300px; position:relative;"> </div> - <script type="text/javascript"> - var lines = []; - var xline; - g = new Dygraph( - document.getElementById("div_g"), - NoisyData, { - rollPeriod: 7, - showRoller: true, - errorBars: true, + <p>Horizontal crosshairs:</p> + <div id="div_g_h" style="width:600px; height:300px; position:relative;"> + </div> - highlightCallback: function(e, x, pts) { - for (var i = 0; i < pts.length; i++) { - var y = pts[i].canvasy; - lines[i].style.visibility = "visible"; - lines[i].style.top = y + "px"; - if (i == 0) xline.style.left = pts[i].canvasx + "px"; - } - xline.style.visibility = "visible"; - }, + <p>Both crosshairs:</p> + <div id="div_g_b" style="width:600px; height:300px; position:relative;"> + </div> + + <script type="text/javascript"> + gv = new Dygraph( + document.getElementById("div_g_v"), + NoisyData, + { + rollPeriod: 7, + showRoller: true, + errorBars: true, - unhighlightCallback: function(e) { - for (var i = 0; i < 2; i++) { - lines[i].style.visibility = "hidden"; - } - xline.style.visibility = "hidden"; - } - } - ); + plugins: [ + new Dygraph.Plugins.Crosshair({ + direction: "vertical" + }) + ] + } + ); + gh = new Dygraph( + document.getElementById("div_g_h"), + NoisyData, { + rollPeriod: 7, + showRoller: true, + errorBars: true, - for (var i = 0; i < 2; i++) { - var line = document.createElement("div"); - line.className = "line yline"; - document.getElementById("div_g").appendChild(line); - lines.push(line); - } + plugins: [ + new Dygraph.Plugins.Crosshair({ + direction: "horizontal" + }) + ] + } + ); + gb = new Dygraph( + document.getElementById("div_g_b"), + NoisyData, { + rollPeriod: 7, + showRoller: true, + errorBars: true, - xline = document.createElement("div"); - xline.className = "line xline"; - xline.style.top = "0px"; - document.getElementById("div_g").appendChild(xline); + plugins: [ + new Dygraph.Plugins.Crosshair({ + direction: "both" + }) + ] + } + ); </script> </body> </html> -- 2.7.4