X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;f=dygraph-canvas.js;h=49dddd48429f5f92c50e258b21b02d2d74a2d464;hb=02ecfa7a72bdf04b0648cb4daef5dc1bca66db67;hp=0813691c26a7200cd381c69ed9d3dd062f49e5f3;hpb=fbe31dc8001c5122d8fe980b4eede83fd71a835c;p=dygraphs.git diff --git a/dygraph-canvas.js b/dygraph-canvas.js index 0813691..49dddd4 100644 --- a/dygraph-canvas.js +++ b/dygraph-canvas.js @@ -2,24 +2,22 @@ // All Rights Reserved. /** - * @fileoverview Subclasses various parts of PlotKit to meet the additional - * needs of Dygraph: grid overlays and error bars + * @fileoverview Based on PlotKit, but modified to meet the needs of dygraphs. + * In particular, support for: + * - grid overlays + * - error bars + * - dygraphs attribute system */ -// Subclass PlotKit.Layout to add: -// 1. Sigma/errorBars properties -// 2. Copy error terms for PlotKit.CanvasRenderer._renderLineChart - /** - * Creates a new DygraphLayout object. Options are the same as those allowed - * by the PlotKit.Layout constructor. + * Creates a new DygraphLayout object. * @param {Object} options Options for PlotKit.Layout * @return {Object} The DygraphLayout object */ DygraphLayout = function(dygraph, options) { this.dygraph_ = dygraph; this.options = {}; // TODO(danvk): remove, use attr_ instead. - MochiKit.Base.update(this.options, options ? options : {}); + Dygraph.update(this.options, options ? options : {}); this.datasets = new Array(); }; @@ -40,6 +38,7 @@ DygraphLayout.prototype.evaluate = function() { DygraphLayout.prototype._evaluateLimits = function() { this.minxval = this.maxxval = null; for (var name in this.datasets) { + if (!this.datasets.hasOwnProperty(name)) continue; var series = this.datasets[name]; var x1 = series[0][0]; if (!this.minxval || x1 < this.minxval) this.minxval = x1; @@ -60,6 +59,8 @@ DygraphLayout.prototype._evaluateLineCharts = function() { // add all the rects this.points = new Array(); for (var setName in this.datasets) { + if (!this.datasets.hasOwnProperty(setName)) continue; + var dataset = this.datasets[setName]; for (var j = 0; j < dataset.length; j++) { var item = dataset[j]; @@ -119,9 +120,9 @@ DygraphLayout.prototype.evaluateWithError = function() { // Copy over the error terms var i = 0; // index in this.points for (var setName in this.datasets) { + if (!this.datasets.hasOwnProperty(setName)) continue; var j = 0; var dataset = this.datasets[setName]; - if (PlotKit.Base.isFuncLike(dataset)) continue; for (var j = 0; j < dataset.length; j++, i++) { var item = dataset[j]; var xv = parseFloat(item[0]); @@ -149,7 +150,7 @@ DygraphLayout.prototype.removeAllDatasets = function() { * @param {Object} new_options an associative array of new properties */ DygraphLayout.prototype.updateOptions = function(new_options) { - MochiKit.Base.update(this.options, new_options ? new_options : {}); + Dygraph.update(this.options, new_options ? new_options : {}); }; // Subclass PlotKit.CanvasRenderer to add: @@ -168,37 +169,26 @@ DygraphCanvasRenderer = function(dygraph, element, layout, options) { // default options this.options = { - "strokeWidth": 0.5, - "drawXAxis": true, - "drawYAxis": true, - "axisLineColor": Color.blackColor(), - "axisLineWidth": 0.5, - "axisTickSize": 3, - "axisLabelColor": Color.blackColor(), - "axisLabelFont": "Arial", - "axisLabelFontSize": 9, - "axisLabelWidth": 50, - "drawYGrid": true, - "drawXGrid": true, - "gridLineColor": MochiKit.Color.Color.grayColor() + "strokeWidth": 0.5, + "drawXAxis": true, + "drawYAxis": true, + "axisLineColor": "black", + "axisLineWidth": 0.5, + "axisTickSize": 3, + "axisLabelColor": "black", + "axisLabelFont": "Arial", + "axisLabelFontSize": 9, + "axisLabelWidth": 50, + "drawYGrid": true, + "drawXGrid": true, + "gridLineColor": "rgb(128,128,128)" }; - MochiKit.Base.update(this.options, options); + Dygraph.update(this.options, options); this.layout = layout; - this.element = MochiKit.DOM.getElement(element); + this.element = element; this.container = this.element.parentNode; - // Stuff relating to Canvas on IE support - this.isIE = PlotKit.Base.excanvasSupported(); - - if (this.isIE && !isNil(G_vmlCanvasManager)) { - this.IEDelay = 0.5; - this.maxTries = 5; - this.renderDelay = null; - this.clearDelay = null; - this.element = G_vmlCanvasManager.initElement(this.element); - } - this.height = this.element.height; this.width = this.element.width; @@ -218,8 +208,8 @@ DygraphCanvasRenderer = function(dygraph, element, layout, options) { this.area.h = this.height - this.options.axisLabelFontSize - 2 * this.options.axisTickSize; - MochiKit.DOM.updateNodeAttributes(this.container, - {"style":{ "position": "relative", "width": this.width + "px"}}); + this.container.style.position = "relative"; + this.container.style.width = this.width + "px"; }; DygraphCanvasRenderer.prototype.clear = function() { @@ -233,6 +223,7 @@ DygraphCanvasRenderer.prototype.clear = function() { var context = this.element.getContext("2d"); } 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; @@ -242,8 +233,14 @@ DygraphCanvasRenderer.prototype.clear = function() { var context = this.element.getContext("2d"); context.clearRect(0, 0, this.width, this.height); - MochiKit.Iter.forEach(this.xlabels, MochiKit.DOM.removeElement); - MochiKit.Iter.forEach(this.ylabels, MochiKit.DOM.removeElement); + for (var i = 0; i < this.xlabels.length; i++) { + var el = this.xlabels[i]; + el.parentNode.removeChild(el); + } + for (var i = 0; i < this.ylabels.length; i++) { + var el = this.ylabels[i]; + el.parentNode.removeChild(el); + } this.xlabels = new Array(); this.ylabels = new Array(); }; @@ -252,10 +249,10 @@ DygraphCanvasRenderer.prototype.clear = function() { DygraphCanvasRenderer.isSupported = function(canvasName) { var canvas = null; try { - if (MochiKit.Base.isUndefinedOrNull(canvasName)) - canvas = MochiKit.DOM.CANVAS({}); + if (typeof(canvasName) == 'undefined' || canvasName == null) + canvas = document.createElement("canvas"); else - canvas = MochiKit.DOM.getElement(canvasName); + canvas = canvasName; var context = canvas.getContext("2d"); } catch (e) { @@ -277,7 +274,7 @@ DygraphCanvasRenderer.prototype.render = function() { if (this.options.drawYGrid) { var ticks = this.layout.yticks; ctx.save(); - ctx.strokeStyle = this.options.gridLineColor.toRGBString(); + ctx.strokeStyle = this.options.gridLineColor; ctx.lineWidth = this.options.axisLineWidth; for (var i = 0; i < ticks.length; i++) { var x = this.area.x; @@ -293,7 +290,7 @@ DygraphCanvasRenderer.prototype.render = function() { if (this.options.drawXGrid) { var ticks = this.layout.xticks; ctx.save(); - ctx.strokeStyle = this.options.gridLineColor.toRGBString(); + ctx.strokeStyle = this.options.gridLineColor; ctx.lineWidth = this.options.axisLineWidth; for (var i=0; i= 0) { - ctx_.moveTo(prevX, prevYs[0]); - ctx_.lineTo(point.canvasx, newYs[0]); - ctx_.lineTo(point.canvasx, newYs[1]); - ctx_.lineTo(prevX, prevYs[1]); - ctx_.closePath(); + ctx.moveTo(prevX, prevYs[0]); + ctx.lineTo(point.canvasx, newYs[0]); + ctx.lineTo(point.canvasx, newYs[1]); + ctx.lineTo(prevX, prevYs[1]); + ctx.closePath(); } prevYs[0] = newYs[0]; prevYs[1] = newYs[1]; prevX = point.canvasx; } - }; - // should be same color as the lines - var err_color = color.colorWithAlpha(0.15); - ctx.fillStyle = err_color.toRGBString(); - ctx.beginPath(); - MochiKit.Iter.forEach(this.layout.points, partial(errorTrapezoid, ctx), this); + } ctx.fill(); } - }; + } + + for (var i = 0; i < setCount; i++) { + var setName = setNames[i]; + var color = colorScheme[i%colorCount]; + + // setup graphics context + context.save(); + var point = this.layout.points[0]; + var pointSize = this.dygraph_.attr_("pointSize"); + var prevX = null, prevY = null; + var drawPoints = this.dygraph_.attr_("drawPoints"); + var points = this.layout.points; + for (var j = 0; j < points.length; j++) { + var point = points[j]; + if (point.name == setName) { + if (!isOK(point.canvasy)) { + // this will make us move to the next point, not draw a line to it. + prevX = prevY = null; + } else { + // A point is "isolated" if it is non-null but both the previous + // and next points are null. + var isIsolated = (!prevX && (j == points.length - 1 || + !isOK(points[j+1].canvasy))); + + if (!prevX) { + prevX = point.canvasx; + prevY = point.canvasy; + } else { + ctx.beginPath(); + ctx.strokeStyle = color; + ctx.lineWidth = this.options.strokeWidth; + ctx.moveTo(prevX, prevY); + prevX = point.canvasx; + prevY = point.canvasy; + ctx.lineTo(prevX, prevY); + ctx.stroke(); + } + + if (drawPoints || isIsolated) { + ctx.beginPath(); + ctx.fillStyle = color; + ctx.arc(point.canvasx, point.canvasy, pointSize, + 0, 2 * Math.PI, false); + ctx.fill(); + } + } + } + } + } - if (errorBars) - bind(makeErrorBars, this)(context); - bind(makePath, this)(context); context.restore(); };