X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph.js;h=40f1d11873c92ee3836e001fa169b98a9358a336;hb=87cf3e095ae7fd57b6208f8ee910a51d711542e1;hp=148da341387686f9b1a5b4cb315ffec6dd067202;hpb=240df72e34176516f2d3455e924d7e2d756db773;p=dygraphs.git diff --git a/dygraph.js b/dygraph.js index 148da34..40f1d11 100644 --- a/dygraph.js +++ b/dygraph.js @@ -187,8 +187,7 @@ Dygraph.dateAxisFormatter = function(date, granularity) { Dygraph.DEFAULT_ATTRS = { highlightCircleSize: 3, highlightSeriesOpts: null, - highlightSeriesBackgroundFade: 0, - highlightSeriesAnimated: false, + highlightSeriesBackgroundAlpha: 0.5, labelsDivWidth: 250, labelsDivStyles: { @@ -1022,7 +1021,11 @@ Dygraph.prototype.createStatusMessage_ = function() { div.className = "dygraph-legend"; for (var name in messagestyle) { if (messagestyle.hasOwnProperty(name)) { - div.style[name] = messagestyle[name]; + try { + div.style[name] = messagestyle[name]; + } catch (e) { + this.warn("You are using unsupported css properties for your browser in labelsDivStyles"); + } } } this.graphDiv.appendChild(div); @@ -1512,17 +1515,23 @@ Dygraph.prototype.findClosestRow = function(domX) { var l = points.length; for (var i = 0; i < l; i++) { var point = points[i]; - if (point === null) continue; + if (!Dygraph.isValidPoint(point)) continue; var dist = Math.abs(point.canvasx - domX); - if (minDistX !== null && dist >= minDistX) continue; - minDistX = dist; - idx = i; + if (minDistX === null || dist < minDistX) { + minDistX = dist; + idx = i; + } } return this.idxToRow_(idx); }; /** - * Given canvas X,Y coordinates, find the closest point + * Given canvas X,Y coordinates, find the closest point. + * + * This finds the individual data point across all visible series + * that's closest to the supplied DOM coordinates using the standard + * Euclidean X,Y distance. + * * @param {Number} domX graph-relative DOM X coordinate * @param {Number} domY graph-relative DOM Y coordinate * Returns: {row, seriesName, point} @@ -1538,15 +1547,16 @@ Dygraph.prototype.findClosestPoint = function(domX, domY) { var len = this.layout_.setPointsLengths[setIdx]; for (var i = 0; i < len; ++i) { var point = points[first + i]; - if (point === null) continue; + if (!Dygraph.isValidPoint(point)) continue; dx = point.canvasx - domX; dy = point.canvasy - domY; dist = dx * dx + dy * dy; - if (minDist !== null && dist >= minDist) continue; - minDist = dist; - closestPoint = point; - closestSeries = setIdx; - idx = i; + if (minDist === null || dist < minDist) { + minDist = dist; + closestPoint = point; + closestSeries = setIdx; + idx = i; + } } } var name = this.layout_.setNames[closestSeries]; @@ -1559,6 +1569,11 @@ Dygraph.prototype.findClosestPoint = function(domX, domY) { /** * Given canvas X,Y coordinates, find the touched area in a stacked graph. + * + * This first finds the X data point closest to the supplied DOM X coordinate, + * then finds the series which puts the Y coordinate on top of its filled area, + * using linear interpolation between adjacent point pairs. + * * @param {Number} domX graph-relative DOM X coordinate * @param {Number} domY graph-relative DOM Y coordinate * Returns: {row, seriesName, point} @@ -1573,28 +1588,34 @@ Dygraph.prototype.findStackedPoint = function(domX, domY) { var len = this.layout_.setPointsLengths[setIdx]; if (row >= len) continue; var p1 = points[first + row]; + if (!Dygraph.isValidPoint(p1)) continue; var py = p1.canvasy; if (domX > p1.canvasx && row + 1 < len) { // interpolate series Y value using next point var p2 = points[first + row + 1]; - var dx = p2.canvasx - p1.canvasx; - if (dx > 0) { - var r = (domX - p1.canvasx) / dx; - py += r * (p2.canvasy - p1.canvasy); + if (Dygraph.isValidPoint(p2)) { + var dx = p2.canvasx - p1.canvasx; + if (dx > 0) { + var r = (domX - p1.canvasx) / dx; + py += r * (p2.canvasy - p1.canvasy); + } } } else if (domX < p1.canvasx && row > 0) { // interpolate series Y value using previous point var p0 = points[first + row - 1]; - var dx = p1.canvasx - p0.canvasx; - if (dx > 0) { - var r = (p1.canvasx - domX) / dx; - py += r * (p0.canvasy - p1.canvasy); + if (Dygraph.isValidPoint(p0)) { + var dx = p1.canvasx - p0.canvasx; + if (dx > 0) { + var r = (p1.canvasx - domX) / dx; + py += r * (p0.canvasy - p1.canvasy); + } } } // Stop if the point (domX, py) is above this series' upper edge - if (setIdx > 0 && py >= domY) break; - closestPoint = p1; - closestSeries = setIdx; + if (setIdx == 0 || py < domY) { + closestPoint = p1; + closestSeries = setIdx; + } } var name = this.layout_.setNames[closestSeries]; return { @@ -1835,10 +1856,8 @@ Dygraph.prototype.setLegendHTML_ = function(x, sel_points) { Dygraph.prototype.animateSelection_ = function(direction) { var totalSteps = 10; var millis = 30; - if (this.fadeLevel === undefined) { - this.fadeLevel = 0; - this.animateId = 0; - } + if (this.fadeLevel === undefined) this.fadeLevel = 0; + if (this.animateId === undefined) this.animateId = 0; var start = this.fadeLevel; var steps = direction < 0 ? start : totalSteps - start; if (steps <= 0) { @@ -1876,9 +1895,13 @@ Dygraph.prototype.updateSelection_ = function(opt_animFraction) { var ctx = this.canvas_ctx_; if (this.attr_('highlightSeriesOpts')) { ctx.clearRect(0, 0, this.width_, this.height_); - var alpha = this.attr_('highlightSeriesBackgroundFade'); + var alpha = 1.0 - this.attr_('highlightSeriesBackgroundAlpha'); if (alpha) { - if (this.attr_('highlightSeriesAnimate')) { + // Activating background fade includes an animation effect for a gradual + // fade. TODO(klausw): make this independently configurable if it causes + // issues? Use a shared preference to control animations? + var animateBackgroundFade = true; + if (animateBackgroundFade) { if (opt_animFraction === undefined) { // start a new animation this.animateSelection_(1); @@ -1922,10 +1945,16 @@ Dygraph.prototype.updateSelection_ = function(opt_animFraction) { if (!Dygraph.isOK(pt.canvasy)) continue; var circleSize = this.attr_('highlightCircleSize', pt.name); - ctx.beginPath(); - ctx.fillStyle = this.plotter_.colors[pt.name]; - ctx.arc(canvasx, pt.canvasy, circleSize, 0, 2 * Math.PI, false); - ctx.fill(); + var callback = this.attr_("drawHighlightPointCallback", pt.name); + var color = this.plotter_.colors[pt.name]; + if (!callback) { + callback = Dygraph.Circles.DEFAULT; + } + ctx.lineWidth = this.attr_('strokeWidth', pt.name); + ctx.strokeStyle = color; + ctx.fillStyle = color; + callback(this.g, pt.name, ctx, canvasx, pt.canvasy, + color, circleSize); } ctx.restore();