* `helpers.aliasPixel`
* `helpers.configMerge`
* `helpers.indexOf`
+* `helpers.lineTo`
* `helpers.min`
* `helpers.max`
* `helpers.nextItem`
* `_model.datasetLabel`
* `_model.label`
+* `Point._model.tension`
+* `Point._model.steppedLine`
* `TimeScale.getLabelWidth`
### Renamed
var meta = me.getMeta();
var xScale = me._xScale;
var yScale = me._yScale;
- var lineModel = meta.dataset._model;
var stacked = meta._stacked;
var parsed = me._getParsed(index);
var options = me._resolveDataElementOptions(index);
backgroundColor: options.backgroundColor,
borderColor: options.borderColor,
borderWidth: options.borderWidth,
- tension: lineModel ? lineModel.tension : 0,
- steppedLine: lineModel ? lineModel.steppedLine : false,
// Tooltip
hitRadius: options.hitRadius
};
var meta = me.getMeta();
var line = meta.dataset;
var points = meta.data || [];
- var config = me._config;
var animationsDisabled = me.chart._animationsDisabled;
var i, ilen;
- // Compatibility: If the properties are defined with only the old name, use those values
- if (config.tension !== undefined && config.lineTension === undefined) {
- config.lineTension = config.tension;
- }
-
// Data
line._children = points;
line._loop = true;
var scale = me.chart.scale;
var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
var options = me._resolveDataElementOptions(index);
- var lineModel = me.getMeta().dataset._model;
var x = reset ? scale.xCenter : pointPosition.x;
var y = reset ? scale.yCenter : pointPosition.y;
backgroundColor: options.backgroundColor,
borderColor: options.borderColor,
borderWidth: options.borderWidth,
- tension: lineModel ? lineModel.tension : 0,
// Tooltip
hitRadius: options.hitRadius
updateBezierControlPoints: function() {
var me = this;
var meta = me.getMeta();
+ var lineModel = meta.dataset._model;
var area = me.chart.chartArea;
var points = meta.data || [];
var i, ilen, model, controlPoints;
previousItem(points, i)._model,
model,
nextItem(points, i)._model,
- model.tension
+ lineModel.tension
);
// Prevent the bezier going outside of the bounds of the graph
ctx.strokeStyle = vm.borderColor;
}
-function normalPath(ctx, points, spanGaps) {
+function normalPath(ctx, points, spanGaps, vm) {
+ const steppedLine = vm.steppedLine;
+ const lineMethod = steppedLine ? helpers.canvas._steppedLineTo : helpers.canvas._bezierCurveTo;
let move = true;
let index, currentVM, previousVM;
if (move) {
ctx.moveTo(currentVM.x, currentVM.y);
move = false;
+ } else if (vm.tension || steppedLine) {
+ lineMethod(ctx, previousVM, currentVM, false, steppedLine);
} else {
- helpers.canvas.lineTo(ctx, previousVM, currentVM);
+ ctx.lineTo(currentVM.x, currentVM.y);
}
previousVM = currentVM;
}
if (useFastPath(vm)) {
fastPath(ctx, points, spanGaps);
} else {
- normalPath(ctx, points, spanGaps);
+ normalPath(ctx, points, spanGaps, vm);
}
if (closePath) {
ctx.restore();
},
- lineTo: function(ctx, previous, target, flip) {
- var stepped = target.steppedLine;
- if (stepped) {
- if (stepped === 'middle') {
- var midpoint = (previous.x + target.x) / 2.0;
- ctx.lineTo(midpoint, flip ? target.y : previous.y);
- ctx.lineTo(midpoint, flip ? previous.y : target.y);
- } else if ((stepped === 'after' && !flip) || (stepped !== 'after' && flip)) {
- ctx.lineTo(previous.x, target.y);
- } else {
- ctx.lineTo(target.x, previous.y);
- }
- ctx.lineTo(target.x, target.y);
- return;
- }
-
- if (!target.tension) {
- ctx.lineTo(target.x, target.y);
- return;
+ /**
+ * @private
+ */
+ _steppedLineTo: function(ctx, previous, target, flip, mode) {
+ if (mode === 'middle') {
+ const midpoint = (previous.x + target.x) / 2.0;
+ ctx.lineTo(midpoint, flip ? target.y : previous.y);
+ ctx.lineTo(midpoint, flip ? previous.y : target.y);
+ } else if ((mode === 'after' && !flip) || (mode !== 'after' && flip)) {
+ ctx.lineTo(previous.x, target.y);
+ } else {
+ ctx.lineTo(target.x, previous.y);
}
+ ctx.lineTo(target.x, target.y);
+ },
+ /**
+ * @private
+ */
+ _bezierCurveTo: function(ctx, previous, target, flip) {
ctx.bezierCurveTo(
flip ? previous.controlPointPreviousX : previous.controlPointNextX,
flip ? previous.controlPointPreviousY : previous.controlPointNextY,
return {
x: x === null ? point.x : x,
y: y === null ? point.y : y,
+ boundary: true
};
};
}
horizontal = scale.isHorizontal();
return {
x: horizontal ? target : null,
- y: horizontal ? null : target
+ y: horizontal ? null : target,
+ boundary: true
};
}
}
point.cy = center.y;
point.angle = scale.getIndexAngle(i) - Math.PI / 2;
}
+ point.boundary = true;
target.push(point);
}
return target;
return point && !point.skip;
}
-function drawArea(ctx, curve0, curve1, len0, len1) {
- var i, cx, cy, r;
+function drawArea(ctx, curve0, curve1, len0, len1, stepped, tension) {
+ const lineTo = stepped ? helpers.canvas._steppedLineTo : helpers.canvas._bezierCurveTo;
+ let i, cx, cy, r, target;
if (!len0 || !len1) {
return;
// building first area curve (normal)
ctx.moveTo(curve0[0].x, curve0[0].y);
for (i = 1; i < len0; ++i) {
- helpers.canvas.lineTo(ctx, curve0[i - 1], curve0[i]);
+ target = curve0[i];
+ if (!target.boundary && (tension || stepped)) {
+ lineTo(ctx, curve0[i - 1], target, false, stepped);
+ } else {
+ ctx.lineTo(target.x, target.y);
+ }
}
if (curve1[0].angle !== undefined) {
// building opposite area curve (reverse)
for (i = len1 - 1; i > 0; --i) {
- helpers.canvas.lineTo(ctx, curve1[i], curve1[i - 1], true);
+ target = curve1[i - 1];
+ if (!target.boundary && (tension || stepped)) {
+ lineTo(ctx, curve1[i], target, true, stepped);
+ } else {
+ ctx.lineTo(target.x, target.y);
+ }
}
}
-function doFill(ctx, points, mapper, view, color, loop) {
- var count = points.length;
- var span = view.spanGaps;
- var curve0 = [];
- var curve1 = [];
- var len0 = 0;
- var len1 = 0;
- var i, ilen, index, p0, p1, d0, d1, loopOffset;
+function doFill(ctx, points, mapper, el) {
+ const count = points.length;
+ const view = el._view;
+ const loop = el._loop;
+ const span = view.spanGaps;
+ const stepped = view.steppedLine;
+ const tension = view.tension;
+ let curve0 = [];
+ let curve1 = [];
+ let len0 = 0;
+ let len1 = 0;
+ let i, ilen, index, p0, p1, d0, d1, loopOffset;
ctx.beginPath();
len1 = curve1.push(p1);
} else if (len0 && len1) {
if (!span) {
- drawArea(ctx, curve0, curve1, len0, len1);
+ drawArea(ctx, curve0, curve1, len0, len1, stepped, tension);
len0 = len1 = 0;
curve0 = [];
curve1 = [];
}
}
- drawArea(ctx, curve0, curve1, len0, len1);
+ drawArea(ctx, curve0, curve1, len0, len1, stepped, tension);
ctx.closePath();
- ctx.fillStyle = color;
+ ctx.fillStyle = view.backgroundColor;
ctx.fill();
}
beforeDatasetsDraw: function(chart) {
var metasets = chart._getSortedVisibleDatasetMetas();
var ctx = chart.ctx;
- var meta, i, el, view, points, mapper, color;
+ var meta, i, el, points, mapper;
for (i = metasets.length - 1; i >= 0; --i) {
meta = metasets[i].$filler;
}
el = meta.el;
- view = el._view;
points = el._children || [];
mapper = meta.mapper;
- color = view.backgroundColor || defaults.global.defaultColor;
- if (mapper && color && points.length) {
+ if (mapper && points.length) {
helpers.canvas.clipArea(ctx, chart.chartArea);
- doFill(ctx, points, mapper, view, color, el._loop);
+ doFill(ctx, points, mapper, el);
helpers.canvas.unclipArea(ctx);
}
}
borderJoinStyle: 'bevel',
borderWidth: 1.2,
fill: true,
+ tension: 0.1,
}));
[
radius: 3,
pointStyle: 'circle',
skip: false,
- tension: 0.1,
}));
});
radius: 3,
pointStyle: 'circle',
skip: false,
- tension: 0.1,
}));
});
borderJoinStyle: 'miter',
borderWidth: 0.55,
fill: false,
+ tension: 0,
}));
// Since tension is now 0, we don't care about the control points
radius: 22,
pointStyle: 'circle',
skip: false,
- tension: 0,
}));
});
});