123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- 'use strict';
- module.exports = function(Chart) {
- var helpers = Chart.helpers;
- var globalDefaults = Chart.defaults.global;
- Chart.defaults.global.elements.line = {
- tension: 0.4,
- backgroundColor: globalDefaults.defaultColor,
- borderWidth: 3,
- borderColor: globalDefaults.defaultColor,
- borderCapStyle: 'butt',
- borderDash: [],
- borderDashOffset: 0.0,
- borderJoinStyle: 'miter',
- capBezierPoints: true,
- fill: true, // do we fill in the area between the line and its base axis
- };
- Chart.elements.Line = Chart.Element.extend({
- draw: function() {
- var me = this;
- var vm = me._view;
- var spanGaps = vm.spanGaps;
- var fillPoint = vm.scaleZero;
- var loop = me._loop;
- // Handle different fill modes for cartesian lines
- if (!loop) {
- if (vm.fill === 'top') {
- fillPoint = vm.scaleTop;
- } else if (vm.fill === 'bottom') {
- fillPoint = vm.scaleBottom;
- }
- }
- var ctx = me._chart.ctx;
- ctx.save();
- // Helper function to draw a line to a point
- function lineToPoint(previousPoint, point) {
- var pointVM = point._view;
- if (point._view.steppedLine === true) {
- ctx.lineTo(pointVM.x, previousPoint._view.y);
- ctx.lineTo(pointVM.x, pointVM.y);
- } else if (point._view.tension === 0) {
- ctx.lineTo(pointVM.x, pointVM.y);
- } else {
- ctx.bezierCurveTo(
- previousPoint._view.controlPointNextX,
- previousPoint._view.controlPointNextY,
- pointVM.controlPointPreviousX,
- pointVM.controlPointPreviousY,
- pointVM.x,
- pointVM.y
- );
- }
- }
- var points = me._children.slice(); // clone array
- var lastDrawnIndex = -1;
- // If we are looping, adding the first point again
- if (loop && points.length) {
- points.push(points[0]);
- }
- var index, current, previous, currentVM;
- // Fill Line
- if (points.length && vm.fill) {
- ctx.beginPath();
- for (index = 0; index < points.length; ++index) {
- current = points[index];
- previous = helpers.previousItem(points, index);
- currentVM = current._view;
- // First point moves to it's starting position no matter what
- if (index === 0) {
- if (loop) {
- ctx.moveTo(fillPoint.x, fillPoint.y);
- } else {
- ctx.moveTo(currentVM.x, fillPoint);
- }
- if (!currentVM.skip) {
- lastDrawnIndex = index;
- ctx.lineTo(currentVM.x, currentVM.y);
- }
- } else {
- previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
- if (currentVM.skip) {
- // Only do this if this is the first point that is skipped
- if (!spanGaps && lastDrawnIndex === (index - 1)) {
- if (loop) {
- ctx.lineTo(fillPoint.x, fillPoint.y);
- } else {
- ctx.lineTo(previous._view.x, fillPoint);
- }
- }
- } else {
- if (lastDrawnIndex !== (index - 1)) {
- // There was a gap and this is the first point after the gap. If we've never drawn a point, this is a special case.
- // If the first data point is NaN, then there is no real gap to skip
- if (spanGaps && lastDrawnIndex !== -1) {
- // We are spanning the gap, so simple draw a line to this point
- lineToPoint(previous, current);
- } else if (loop) {
- ctx.lineTo(currentVM.x, currentVM.y);
- } else {
- ctx.lineTo(currentVM.x, fillPoint);
- ctx.lineTo(currentVM.x, currentVM.y);
- }
- } else {
- // Line to next point
- lineToPoint(previous, current);
- }
- lastDrawnIndex = index;
- }
- }
- }
- if (!loop && lastDrawnIndex !== -1) {
- ctx.lineTo(points[lastDrawnIndex]._view.x, fillPoint);
- }
- ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
- ctx.closePath();
- ctx.fill();
- }
- // Stroke Line Options
- var globalOptionLineElements = globalDefaults.elements.line;
- ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
- // IE 9 and 10 do not support line dash
- if (ctx.setLineDash) {
- ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
- }
- ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
- ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
- ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
- ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
- // Stroke Line
- ctx.beginPath();
- lastDrawnIndex = -1;
- for (index = 0; index < points.length; ++index) {
- current = points[index];
- previous = helpers.previousItem(points, index);
- currentVM = current._view;
- // First point moves to it's starting position no matter what
- if (index === 0) {
- if (!currentVM.skip) {
- ctx.moveTo(currentVM.x, currentVM.y);
- lastDrawnIndex = index;
- }
- } else {
- previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
- if (!currentVM.skip) {
- if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) {
- // There was a gap and this is the first point after the gap
- ctx.moveTo(currentVM.x, currentVM.y);
- } else {
- // Line to next point
- lineToPoint(previous, current);
- }
- lastDrawnIndex = index;
- }
- }
- }
- ctx.stroke();
- ctx.restore();
- }
- });
- };
|