X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph-canvas.js;h=a688c43975958639e973715cdcbc5727b18712c9;hb=0a5aa490041ec62b5c7e4951d4d4e7a2fd345fc2;hp=4ebf5bc16b87d0d649715f606236098b318a9fdc;hpb=9f79cb9489fd18858e4f5b661cb4b03be988b3b3;p=dygraphs.git diff --git a/dygraph-canvas.js b/dygraph-canvas.js index 4ebf5bc..a688c43 100644 --- a/dygraph-canvas.js +++ b/dygraph-canvas.js @@ -24,7 +24,7 @@ * @constructor */ -/*jshint globalstrict: true */ +var DygraphCanvasRenderer = (function() { /*global Dygraph:false */ "use strict"; @@ -57,31 +57,27 @@ var DygraphCanvasRenderer = function(dygraph, element, elementContext, layout) { this.width = dygraph.width_; // --- check whether everything is ok before we return - // NOTE(konigsberg): isIE is never defined in this object. Bug of some sort. - if (!this.isIE && !(Dygraph.isCanvasSupported(this.element))) - throw "Canvas is not supported."; + if (!Dygraph.isCanvasSupported(this.element)) { + throw "Canvas is not supported."; + } // internal state this.area = layout.getPlotArea(); // Set up a clipping area for the canvas (and the interaction canvas). // This ensures that we don't overdraw. - if (this.dygraph_.isUsingExcanvas_) { - this._createIEClipArea(); - } else { - // on Android 3 and 4, setting a clipping area on a canvas prevents it from - // displaying anything. - if (!Dygraph.isAndroid()) { - var ctx = this.dygraph_.canvas_ctx_; - ctx.beginPath(); - ctx.rect(this.area.x, this.area.y, this.area.w, this.area.h); - ctx.clip(); - - ctx = this.dygraph_.hidden_ctx_; - ctx.beginPath(); - ctx.rect(this.area.x, this.area.y, this.area.w, this.area.h); - ctx.clip(); - } + // on Android 3 and 4, setting a clipping area on a canvas prevents it from + // displaying anything. + if (!Dygraph.isAndroid()) { + var ctx = this.dygraph_.canvas_ctx_; + ctx.beginPath(); + ctx.rect(this.area.x, this.area.y, this.area.w, this.area.h); + ctx.clip(); + + ctx = this.dygraph_.hidden_ctx_; + ctx.beginPath(); + ctx.rect(this.area.x, this.area.y, this.area.w, this.area.h); + ctx.clip(); } }; @@ -92,26 +88,7 @@ var DygraphCanvasRenderer = function(dygraph, element, elementContext, layout) { * @private */ DygraphCanvasRenderer.prototype.clear = function() { - var context; - if (this.isIE) { - // VML takes a while to start up, so we just poll every this.IEDelay - try { - if (this.clearDelay) { - this.clearDelay.cancel(); - this.clearDelay = null; - } - context = this.elementContext; - } - catch (e) { - // TODO(danvk): this is broken, since MochiKit.Async is gone. - // this.clearDelay = MochiKit.Async.wait(this.IEDelay); - // this.clearDelay.addCallback(bind(this.clear, this)); - return; - } - } - - context = this.elementContext; - context.clearRect(0, 0, this.width, this.height); + this.elementContext.clearRect(0, 0, this.width, this.height); }; /** @@ -129,76 +106,6 @@ DygraphCanvasRenderer.prototype.render = function() { this._renderLineChart(); }; -DygraphCanvasRenderer.prototype._createIEClipArea = function() { - var className = 'dygraph-clip-div'; - var graphDiv = this.dygraph_.graphDiv; - - // Remove old clip divs. - for (var i = graphDiv.childNodes.length-1; i >= 0; i--) { - if (graphDiv.childNodes[i].className == className) { - graphDiv.removeChild(graphDiv.childNodes[i]); - } - } - - // Determine background color to give clip divs. - var backgroundColor = document.bgColor; - var element = this.dygraph_.graphDiv; - while (element != document) { - var bgcolor = element.currentStyle.backgroundColor; - if (bgcolor && bgcolor != 'transparent') { - backgroundColor = bgcolor; - break; - } - element = element.parentNode; - } - - function createClipDiv(area) { - if (area.w === 0 || area.h === 0) { - return; - } - var elem = document.createElement('div'); - elem.className = className; - elem.style.backgroundColor = backgroundColor; - elem.style.position = 'absolute'; - elem.style.left = area.x + 'px'; - elem.style.top = area.y + 'px'; - elem.style.width = area.w + 'px'; - elem.style.height = area.h + 'px'; - graphDiv.appendChild(elem); - } - - var plotArea = this.area; - // Left side - createClipDiv({ - x:0, y:0, - w:plotArea.x, - h:this.height - }); - - // Top - createClipDiv({ - x: plotArea.x, y: 0, - w: this.width - plotArea.x, - h: plotArea.y - }); - - // Right side - createClipDiv({ - x: plotArea.x + plotArea.w, y: 0, - w: this.width - plotArea.x - plotArea.w, - h: this.height - }); - - // Bottom - createClipDiv({ - x: plotArea.x, - y: plotArea.y + plotArea.h, - w: this.width - plotArea.x, - h: this.height - plotArea.h - plotArea.y - }); -}; - - /** * Returns a predicate to be used with an iterator, which will * iterate over points appropriately, depending on whether @@ -599,12 +506,16 @@ DygraphCanvasRenderer._errorPlotter = function(e) { continue; } + newYs = [ point.y_bottom, point.y_top ]; if (stepPlot) { - newYs = [ point.y_bottom, point.y_top ]; prevY = point.y; - } else { - newYs = [ point.y_bottom, point.y_top ]; } + + // The documentation specifically disallows nulls inside the point arrays, + // but in case it happens we should do something sensible. + if (isNaN(newYs[0])) newYs[0] = point.y; + if (isNaN(newYs[1])) newYs[1] = point.y; + newYs[0] = e.plotArea.h * newYs[0] + e.plotArea.y; newYs[1] = e.plotArea.h * newYs[1] + e.plotArea.y; if (!isNaN(prevX)) { @@ -637,7 +548,6 @@ DygraphCanvasRenderer._errorPlotter = function(e) { DygraphCanvasRenderer._fastCanvasProxy = function(context) { var pendingActions = []; // array of [type, x, y] tuples var lastRoundedX = null; - var extremeYs = null; // [minY, maxY] for lastRoundedX var LINE_TO = 1, MOVE_TO = 2; @@ -746,7 +656,7 @@ DygraphCanvasRenderer._fastCanvasProxy = function(context) { _count: function() { return actionCount; } }; -} +}; /** * Draws the shaded regions when "fillGraph" is set. Not to be confused with @@ -803,6 +713,17 @@ DygraphCanvasRenderer._fillPlotter = function(e) { var currBaseline; var prevStepPlot; // for different line drawing modes (line/step) per series + // Helper function to trace a line back along the baseline. + var traceBackPath = function(ctx, baselineX, baselineY, pathBack) { + ctx.lineTo(baselineX, baselineY); + if (stackedGraph) { + for (var i = pathBack.length - 1; i >= 0; i--) { + var pt = pathBack[i]; + ctx.lineTo(pt[0], pt[1]); + } + } + }; + // process sets in reverse order (needed for stacked graphs) for (var setIdx = setCount - 1; setIdx >= 0; setIdx--) { var ctx = e.drawingContext; @@ -846,24 +767,15 @@ DygraphCanvasRenderer._fillPlotter = function(e) { // stores the [x, y] values needed to trace that shape. var pathBack = []; - var traceBackPath = function(baselineX, baselineY) { - ctx.lineTo(baselineX, baselineY); - if (stackedGraph) { - for (var i = pathBack.length - 1; i >= 0; i--) { - var pt = pathBack[i]; - ctx.lineTo(pt[0], pt[1]); - } - } - pathBack = []; - }; - // TODO(danvk): there are a lot of options at play in this loop. // The logic would be much clearer if some (e.g. stackGraph and // stepPlot) were split off into separate sub-plotters. + var point; while (iter.hasNext) { - var point = iter.next(); + point = iter.next(); if (!Dygraph.isOK(point.y) && !stepPlot) { - traceBackPath(prevX, prevYs[1]); + traceBackPath(ctx, prevX, prevYs[1], pathBack); + pathBack = []; prevX = NaN; if (point.y_stacked !== null && !isNaN(point.y_stacked)) { baseline[point.canvasx] = area.h * point.y_stacked + area.y; @@ -937,9 +849,14 @@ DygraphCanvasRenderer._fillPlotter = function(e) { prevX = point.canvasx; } prevStepPlot = stepPlot; - if (newYs) { - traceBackPath(point.canvasx, newYs[1]); + if (newYs && point) { + traceBackPath(ctx, point.canvasx, newYs[1], pathBack); + pathBack = []; } ctx.fill(); } }; + +return DygraphCanvasRenderer; + +})();