* @constructor
*/
-var DygraphCanvasRenderer = (function() {
/*global Dygraph:false */
"use strict";
+import * as utils from './dygraph-utils';
+import Dygraph from './dygraph';
+
/**
* @constructor
this.width = dygraph.width_;
// --- check whether everything is ok before we return
- if (!Dygraph.isCanvasSupported(this.element)) {
+ if (!utils.isCanvasSupported(this.element)) {
throw "Canvas is not supported.";
}
// Set up a clipping area for the canvas (and the interaction canvas).
// This ensures that we don't overdraw.
- // 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();
+ 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();
- }
+ ctx = this.dygraph_.hidden_ctx_;
+ ctx.beginPath();
+ ctx.rect(this.area.x, this.area.y, this.area.w, this.area.h);
+ ctx.clip();
};
/**
// TODO(konigsberg): Compute attributes outside this method call.
var stepPlot = g.getBooleanOption("stepPlot", e.setName);
- if (!Dygraph.isArrayLike(strokePattern)) {
+ if (!utils.isArrayLike(strokePattern)) {
strokePattern = null;
}
var points = e.points;
var setName = e.setName;
- var iter = Dygraph.createIterator(points, 0, points.length,
+ var iter = utils.createIterator(points, 0, points.length,
DygraphCanvasRenderer._getIteratorPredicate(
g.getBooleanOption("connectSeparatedPoints", setName)));
var ctx = e.drawingContext;
ctx.save();
if (stroking) {
- ctx.installPattern(strokePattern);
+ if (ctx.setLineDash) ctx.setLineDash(strokePattern);
}
var pointsOnLine = DygraphCanvasRenderer._drawSeries(
e, pointsOnLine, drawPointCallback, color, pointSize);
if (stroking) {
- ctx.uninstallPattern();
+ if (ctx.setLineDash) ctx.setLineDash([]);
}
ctx.restore();
prevCanvasX = prevCanvasY = null;
} else {
isIsolated = false;
- if (drawGapPoints || !prevCanvasX) {
+ if (drawGapPoints || prevCanvasX === null) {
iter.nextIdx_ = i;
iter.next();
nextCanvasY = iter.hasNext ? iter.peek.canvasy : null;
var isNextCanvasYNullOrNaN = nextCanvasY === null ||
nextCanvasY != nextCanvasY;
- isIsolated = (!prevCanvasX && isNextCanvasYNullOrNaN);
+ isIsolated = (prevCanvasX === null && isNextCanvasYNullOrNaN);
if (drawGapPoints) {
// Also consider a point to be "isolated" if it's adjacent to a
// null point, excluding the graph edges.
- if ((!first && !prevCanvasX) ||
+ if ((!first && prevCanvasX === null) ||
(iter.hasNext && isNextCanvasYNullOrNaN)) {
isIsolated = true;
}
// Determine which series have specialized plotters.
var plotter_attr = this.dygraph_.getOption("plotter");
var plotters = plotter_attr;
- if (!Dygraph.isArrayLike(plotters)) {
+ if (!utils.isArrayLike(plotters)) {
plotters = [plotters];
}
// this code a bit nasty.
var borderWidth = g.getNumericOption("strokeBorderWidth", setName);
var drawPointCallback = g.getOption("drawPointCallback", setName) ||
- Dygraph.Circles.DEFAULT;
+ utils.Circles.DEFAULT;
var strokePattern = g.getOption("strokePattern", setName);
var drawPoints = g.getBooleanOption("drawPoints", setName);
var pointSize = g.getNumericOption("pointSize", setName);
var stepPlot = g.getBooleanOption("stepPlot", setName);
var points = e.points;
- var iter = Dygraph.createIterator(points, 0, points.length,
+ var iter = utils.createIterator(points, 0, points.length,
DygraphCanvasRenderer._getIteratorPredicate(
g.getBooleanOption("connectSeparatedPoints", setName)));
var prevY = NaN;
var prevYs = [-1, -1];
// should be same color as the lines but only 15% opaque.
- var rgb = Dygraph.toRGB_(color);
+ var rgb = utils.toRGB_(color);
var err_color =
'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + fillAlpha + ')';
ctx.fillStyle = err_color;
* Proxy for CanvasRenderingContext2D which drops moveTo/lineTo calls which are
* superfluous. It accumulates all movements which haven't changed the x-value
* and only applies the two with the most extreme y-values.
- *
+ *
* Calls to lineTo/moveTo must have non-decreasing x-values.
*/
DygraphCanvasRenderer._fastCanvasProxy = function(context) {
var pendingActions = []; // array of [type, x, y] tuples
var lastRoundedX = null;
+ var lastFlushedX = null;
var LINE_TO = 1,
MOVE_TO = 2;
context.moveTo(action[1], action[2]);
}
}
+ if (pendingActions.length) {
+ lastFlushedX = pendingActions[pendingActions.length - 1][1];
+ }
actionCount += pendingActions.length;
pendingActions = [];
};
var addAction = function(action, x, y) {
var rx = Math.round(x);
if (lastRoundedX === null || rx != lastRoundedX) {
- flushActions();
+ // if there are large gaps on the x-axis, it's essential to keep the
+ // first and last point as well.
+ var hasGapOnLeft = (lastRoundedX - lastFlushedX > 1),
+ hasGapOnRight = (rx - lastRoundedX > 1),
+ hasGap = hasGapOnLeft || hasGapOnRight;
+ flushActions(hasGap);
lastRoundedX = rx;
}
pendingActions.push([action, x, y]);
var sets = e.allSeriesPoints;
var setCount = sets.length;
- var fillAlpha = g.getNumericOption('fillAlpha');
var stackedGraph = g.getBooleanOption("stackedGraph");
var colors = g.getColors();
var setName = setNames[setIdx];
if (!g.getBooleanOption('fillGraph', setName)) continue;
+ var fillAlpha = g.getNumericOption('fillAlpha', setName);
var stepPlot = g.getBooleanOption('stepPlot', setName);
var color = colors[setIdx];
var axis = g.axisPropertiesForSeries(setName);
axisY = area.h * axisY + area.y;
var points = sets[setIdx];
- var iter = Dygraph.createIterator(points, 0, points.length,
+ var iter = utils.createIterator(points, 0, points.length,
DygraphCanvasRenderer._getIteratorPredicate(
g.getBooleanOption("connectSeparatedPoints", setName)));
var prevYs = [-1, -1];
var newYs;
// should be same color as the lines but only 15% opaque.
- var rgb = Dygraph.toRGB_(color);
+ var rgb = utils.toRGB_(color);
var err_color =
'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + fillAlpha + ')';
ctx.fillStyle = err_color;
// If the point density is high enough, dropping segments on their way to
// the canvas justifies the overhead of doing so.
- if (points.length > 2 * g.width_) {
+ if (points.length > 2 * g.width_ || Dygraph.FORCE_FAST_PROXY) {
ctx = DygraphCanvasRenderer._fastCanvasProxy(ctx);
}
var point;
while (iter.hasNext) {
point = iter.next();
- if (!Dygraph.isOK(point.y) && !stepPlot) {
+ if (!utils.isOK(point.y) && !stepPlot) {
traceBackPath(ctx, prevX, prevYs[1], pathBack);
pathBack = [];
prevX = NaN;
}
};
-return DygraphCanvasRenderer;
-
-})();
+export default DygraphCanvasRenderer;