X-Git-Url: https://adrianiainlam.tk/git/?a=blobdiff_plain;ds=sidebyside;f=dygraph-canvas.js;h=5326673b1d466594a7e7bd35b4de2e8edb22e642;hb=beeabac2f71ae45c510b0355d0e76972083a6ca6;hp=f1e3c8c1763cfc9270c840dbae398532084bede4;hpb=8cfe592f75ebfe39460a51558488aa7b12ccc87c;p=dygraphs.git diff --git a/dygraph-canvas.js b/dygraph-canvas.js index f1e3c8c..5326673 100644 --- a/dygraph-canvas.js +++ b/dygraph-canvas.js @@ -62,11 +62,6 @@ var DygraphCanvasRenderer = function(dygraph, element, elementContext, layout) { throw "Canvas is not supported."; // internal state - this.xlabels = []; - this.ylabels = []; - this.annotations = []; - this.chartLabels = {}; - this.area = layout.getPlotArea(); this.container.style.position = "relative"; this.container.style.width = this.width + "px"; @@ -123,27 +118,6 @@ DygraphCanvasRenderer.prototype.clear = function() { context = this.elementContext; context.clearRect(0, 0, this.width, this.height); - - function removeArray(ary) { - for (var i = 0; i < ary.length; i++) { - var el = ary[i]; - if (el.parentNode) el.parentNode.removeChild(el); - } - } - - removeArray(this.xlabels); - removeArray(this.ylabels); - removeArray(this.annotations); - - for (var k in this.chartLabels) { - if (!this.chartLabels.hasOwnProperty(k)) continue; - var el = this.chartLabels[k]; - if (el.parentNode) el.parentNode.removeChild(el); - } - this.xlabels = []; - this.ylabels = []; - this.annotations = []; - this.chartLabels = {}; }; /** @@ -238,9 +212,6 @@ DygraphCanvasRenderer.prototype.render = function() { // Do the ordinary rendering, as before this._renderLineChart(); - this._renderAxis(); - this._renderChartLabels(); - this._renderAnnotations(); }; DygraphCanvasRenderer.prototype._createIEClipArea = function() { @@ -312,400 +283,6 @@ DygraphCanvasRenderer.prototype._createIEClipArea = function() { }); }; -DygraphCanvasRenderer.prototype._renderAxis = function() { - if (!this.attr_('drawXAxis') && !this.attr_('drawYAxis')) return; - - // Round pixels to half-integer boundaries for crisper drawing. - function halfUp(x) { return Math.round(x) + 0.5; } - function halfDown(y){ return Math.round(y) - 0.5; } - - var context = this.elementContext; - - var label, x, y, tick, i; - - var labelStyle = { - position: "absolute", - fontSize: this.attr_('axisLabelFontSize') + "px", - zIndex: 10, - color: this.attr_('axisLabelColor'), - width: this.attr_('axisLabelWidth') + "px", - // height: this.attr_('axisLabelFontSize') + 2 + "px", - lineHeight: "normal", // Something other than "normal" line-height screws up label positioning. - overflow: "hidden" - }; - var makeDiv = function(txt, axis, prec_axis) { - var div = document.createElement("div"); - for (var name in labelStyle) { - if (labelStyle.hasOwnProperty(name)) { - div.style[name] = labelStyle[name]; - } - } - var inner_div = document.createElement("div"); - inner_div.className = 'dygraph-axis-label' + - ' dygraph-axis-label-' + axis + - (prec_axis ? ' dygraph-axis-label-' + prec_axis : ''); - inner_div.innerHTML=txt; - div.appendChild(inner_div); - return div; - }; - - // axis lines - context.save(); - context.strokeStyle = this.attr_('axisLineColor'); - context.lineWidth = this.attr_('axisLineWidth'); - - if (this.attr_('drawYAxis')) { - if (this.layout.yticks && this.layout.yticks.length > 0) { - var num_axes = this.dygraph_.numAxes(); - for (i = 0; i < this.layout.yticks.length; i++) { - tick = this.layout.yticks[i]; - if (typeof(tick) == "function") return; - x = this.area.x; - var sgn = 1; - var prec_axis = 'y1'; - if (tick[0] == 1) { // right-side y-axis - x = this.area.x + this.area.w; - sgn = -1; - prec_axis = 'y2'; - } - y = this.area.y + tick[1] * this.area.h; - - /* Tick marks are currently clipped, so don't bother drawing them. - context.beginPath(); - context.moveTo(halfUp(x), halfDown(y)); - context.lineTo(halfUp(x - sgn * this.attr_('axisTickSize')), halfDown(y)); - context.closePath(); - context.stroke(); - */ - - label = makeDiv(tick[2], 'y', num_axes == 2 ? prec_axis : null); - var top = (y - this.attr_('axisLabelFontSize') / 2); - if (top < 0) top = 0; - - if (top + this.attr_('axisLabelFontSize') + 3 > this.height) { - label.style.bottom = "0px"; - } else { - label.style.top = top + "px"; - } - if (tick[0] === 0) { - label.style.left = (this.area.x - this.attr_('yAxisLabelWidth') - this.attr_('axisTickSize')) + "px"; - label.style.textAlign = "right"; - } else if (tick[0] == 1) { - label.style.left = (this.area.x + this.area.w + - this.attr_('axisTickSize')) + "px"; - label.style.textAlign = "left"; - } - label.style.width = this.attr_('yAxisLabelWidth') + "px"; - this.container.appendChild(label); - this.ylabels.push(label); - } - - // The lowest tick on the y-axis often overlaps with the leftmost - // tick on the x-axis. Shift the bottom tick up a little bit to - // compensate if necessary. - var bottomTick = this.ylabels[0]; - var fontSize = this.attr_('axisLabelFontSize'); - var bottom = parseInt(bottomTick.style.top, 10) + fontSize; - if (bottom > this.height - fontSize) { - bottomTick.style.top = (parseInt(bottomTick.style.top, 10) - - fontSize / 2) + "px"; - } - } - - // draw a vertical line on the left to separate the chart from the labels. - var axisX; - if (this.attr_('drawAxesAtZero')) { - var r = this.dygraph_.toPercentXCoord(0); - if (r > 1 || r < 0) r = 0; - axisX = halfUp(this.area.x + r * this.area.w); - } else { - axisX = halfUp(this.area.x); - } - context.beginPath(); - context.moveTo(axisX, halfDown(this.area.y)); - context.lineTo(axisX, halfDown(this.area.y + this.area.h)); - context.closePath(); - context.stroke(); - - // if there's a secondary y-axis, draw a vertical line for that, too. - if (this.dygraph_.numAxes() == 2) { - context.beginPath(); - context.moveTo(halfDown(this.area.x + this.area.w), halfDown(this.area.y)); - context.lineTo(halfDown(this.area.x + this.area.w), halfDown(this.area.y + this.area.h)); - context.closePath(); - context.stroke(); - } - } - - if (this.attr_('drawXAxis')) { - if (this.layout.xticks) { - for (i = 0; i < this.layout.xticks.length; i++) { - tick = this.layout.xticks[i]; - x = this.area.x + tick[0] * this.area.w; - y = this.area.y + this.area.h; - - /* Tick marks are currently clipped, so don't bother drawing them. - context.beginPath(); - context.moveTo(halfUp(x), halfDown(y)); - context.lineTo(halfUp(x), halfDown(y + this.attr_('axisTickSize'))); - context.closePath(); - context.stroke(); - */ - - label = makeDiv(tick[1], 'x'); - label.style.textAlign = "center"; - label.style.top = (y + this.attr_('axisTickSize')) + 'px'; - - var left = (x - this.attr_('axisLabelWidth')/2); - if (left + this.attr_('axisLabelWidth') > this.width) { - left = this.width - this.attr_('xAxisLabelWidth'); - label.style.textAlign = "right"; - } - if (left < 0) { - left = 0; - label.style.textAlign = "left"; - } - - label.style.left = left + "px"; - label.style.width = this.attr_('xAxisLabelWidth') + "px"; - this.container.appendChild(label); - this.xlabels.push(label); - } - } - - context.beginPath(); - var axisY; - if (this.attr_('drawAxesAtZero')) { - var r = this.dygraph_.toPercentYCoord(0, 0); - if (r > 1 || r < 0) r = 1; - axisY = halfDown(this.area.y + r * this.area.h); - } else { - axisY = halfDown(this.area.y + this.area.h); - } - context.moveTo(halfUp(this.area.x), axisY); - context.lineTo(halfUp(this.area.x + this.area.w), axisY); - context.closePath(); - context.stroke(); - } - - context.restore(); -}; - - -DygraphCanvasRenderer.prototype._renderChartLabels = function() { - var div, class_div; - - // Generate divs for the chart title, xlabel and ylabel. - // Space for these divs has already been taken away from the charting area in - // the DygraphCanvasRenderer constructor. - if (this.attr_('title')) { - div = document.createElement("div"); - div.style.position = 'absolute'; - div.style.top = '0px'; - div.style.left = this.area.x + 'px'; - div.style.width = this.area.w + 'px'; - div.style.height = this.attr_('titleHeight') + 'px'; - div.style.textAlign = 'center'; - div.style.fontSize = (this.attr_('titleHeight') - 8) + 'px'; - div.style.fontWeight = 'bold'; - class_div = document.createElement("div"); - class_div.className = 'dygraph-label dygraph-title'; - class_div.innerHTML = this.attr_('title'); - div.appendChild(class_div); - this.container.appendChild(div); - this.chartLabels.title = div; - } - - if (this.attr_('xlabel')) { - div = document.createElement("div"); - div.style.position = 'absolute'; - div.style.bottom = 0; // TODO(danvk): this is lazy. Calculate style.top. - div.style.left = this.area.x + 'px'; - div.style.width = this.area.w + 'px'; - div.style.height = this.attr_('xLabelHeight') + 'px'; - div.style.textAlign = 'center'; - div.style.fontSize = (this.attr_('xLabelHeight') - 2) + 'px'; - - class_div = document.createElement("div"); - class_div.className = 'dygraph-label dygraph-xlabel'; - class_div.innerHTML = this.attr_('xlabel'); - div.appendChild(class_div); - this.container.appendChild(div); - this.chartLabels.xlabel = div; - } - - var that = this; - function createRotatedDiv(axis, classes, html) { - var box = { - left: 0, - top: that.area.y, - width: that.attr_('yLabelWidth'), - height: that.area.h - }; - // TODO(danvk): is this outer div actually necessary? - div = document.createElement("div"); - div.style.position = 'absolute'; - if (axis == 1) { - div.style.left = box.left; - } else { - div.style.right = box.left; - } - div.style.top = box.top + 'px'; - div.style.width = box.width + 'px'; - div.style.height = box.height + 'px'; - div.style.fontSize = (that.attr_('yLabelWidth') - 2) + 'px'; - - var inner_div = document.createElement("div"); - inner_div.style.position = 'absolute'; - inner_div.style.width = box.height + 'px'; - inner_div.style.height = box.width + 'px'; - inner_div.style.top = (box.height / 2 - box.width / 2) + 'px'; - inner_div.style.left = (box.width / 2 - box.height / 2) + 'px'; - inner_div.style.textAlign = 'center'; - - // CSS rotation is an HTML5 feature which is not standardized. Hence every - // browser has its own name for the CSS style. - var val = 'rotate(' + (axis == 1 ? '-' : '') + '90deg)'; - inner_div.style.transform = val; // HTML5 - inner_div.style.WebkitTransform = val; // Safari/Chrome - inner_div.style.MozTransform = val; // Firefox - inner_div.style.OTransform = val; // Opera - inner_div.style.msTransform = val; // IE9 - - if (typeof(document.documentMode) !== 'undefined' && - document.documentMode < 9) { - // We're dealing w/ an old version of IE, so we have to rotate the text - // using a BasicImage transform. This uses a different origin of rotation - // than HTML5 rotation (top left of div vs. its center). - inner_div.style.filter = - 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + - (axis == 1 ? '3' : '1') + ')'; - inner_div.style.left = '0px'; - inner_div.style.top = '0px'; - } - - class_div = document.createElement("div"); - class_div.className = classes; - class_div.innerHTML = html; - - inner_div.appendChild(class_div); - div.appendChild(inner_div); - return div; - } - - var div; - if (this.attr_('ylabel')) { - div = createRotatedDiv(1, 'dygraph-label dygraph-ylabel', - this.attr_('ylabel')); - this.container.appendChild(div); - this.chartLabels.ylabel = div; - } - if (this.attr_('y2label') && this.dygraph_.numAxes() == 2) { - div = createRotatedDiv(2, 'dygraph-label dygraph-y2label', - this.attr_('y2label')); - this.container.appendChild(div); - this.chartLabels.y2label = div; - } -}; - - -DygraphCanvasRenderer.prototype._renderAnnotations = function() { - var annotationStyle = { - "position": "absolute", - "fontSize": this.attr_('axisLabelFontSize') + "px", - "zIndex": 10, - "overflow": "hidden" - }; - - var bindEvt = function(eventName, classEventName, p, self) { - return function(e) { - var a = p.annotation; - if (a.hasOwnProperty(eventName)) { - a[eventName](a, p, self.dygraph_, e); - } else if (self.dygraph_.attr_(classEventName)) { - self.dygraph_.attr_(classEventName)(a, p, self.dygraph_,e ); - } - }; - }; - - // Get a list of point with annotations. - var points = this.layout.annotated_points; - for (var i = 0; i < points.length; i++) { - var p = points[i]; - if (p.canvasx < this.area.x || p.canvasx > this.area.x + this.area.w || - p.canvasy < this.area.y || p.canvasy > this.area.y + this.area.h) { - continue; - } - - var a = p.annotation; - var tick_height = 6; - if (a.hasOwnProperty("tickHeight")) { - tick_height = a.tickHeight; - } - - var div = document.createElement("div"); - for (var name in annotationStyle) { - if (annotationStyle.hasOwnProperty(name)) { - div.style[name] = annotationStyle[name]; - } - } - if (!a.hasOwnProperty('icon')) { - div.className = "dygraphDefaultAnnotation"; - } - if (a.hasOwnProperty('cssClass')) { - div.className += " " + a.cssClass; - } - - var width = a.hasOwnProperty('width') ? a.width : 16; - var height = a.hasOwnProperty('height') ? a.height : 16; - if (a.hasOwnProperty('icon')) { - var img = document.createElement("img"); - img.src = a.icon; - img.width = width; - img.height = height; - div.appendChild(img); - } else if (p.annotation.hasOwnProperty('shortText')) { - div.appendChild(document.createTextNode(p.annotation.shortText)); - } - div.style.left = (p.canvasx - width / 2) + "px"; - if (a.attachAtBottom) { - div.style.top = (this.area.h - height - tick_height) + "px"; - } else { - div.style.top = (p.canvasy - height - tick_height) + "px"; - } - div.style.width = width + "px"; - div.style.height = height + "px"; - div.title = p.annotation.text; - div.style.color = this.colors[p.name]; - div.style.borderColor = this.colors[p.name]; - a.div = div; - - this.dygraph_.addEvent(div, 'click', - bindEvt('clickHandler', 'annotationClickHandler', p, this)); - this.dygraph_.addEvent(div, 'mouseover', - bindEvt('mouseOverHandler', 'annotationMouseOverHandler', p, this)); - this.dygraph_.addEvent(div, 'mouseout', - bindEvt('mouseOutHandler', 'annotationMouseOutHandler', p, this)); - this.dygraph_.addEvent(div, 'dblclick', - bindEvt('dblClickHandler', 'annotationDblClickHandler', p, this)); - - this.container.appendChild(div); - this.annotations.push(div); - - var ctx = this.elementContext; - ctx.strokeStyle = this.colors[p.name]; - ctx.beginPath(); - if (!a.attachAtBottom) { - ctx.moveTo(p.canvasx, p.canvasy); - ctx.lineTo(p.canvasx, p.canvasy - 2 - tick_height); - } else { - ctx.moveTo(p.canvasx, this.area.h); - ctx.lineTo(p.canvasx, this.area.h - 2 - tick_height); - } - ctx.closePath(); - ctx.stroke(); - } -}; /** * Returns a predicate to be used with an iterator, which will @@ -919,11 +496,7 @@ DygraphCanvasRenderer.prototype._renderLineChart = function() { var setNames = this.layout.setNames; var setCount = setNames.length; - // TODO(danvk): Move this mapping into Dygraph and get it out of here. - this.colors = {}; - for (i = 0; i < setCount; i++) { - this.colors[setNames[i]] = this.colorScheme_[i % this.colorScheme_.length]; - } + this.colors = this.dygraph_.colorsMap_; // Update Points // TODO(danvk): here