You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

element.line.js 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. "use strict";
  2. module.exports = function(Chart) {
  3. var helpers = Chart.helpers;
  4. var globalDefaults = Chart.defaults.global;
  5. Chart.defaults.global.elements.line = {
  6. tension: 0.4,
  7. backgroundColor: globalDefaults.defaultColor,
  8. borderWidth: 3,
  9. borderColor: globalDefaults.defaultColor,
  10. borderCapStyle: 'butt',
  11. borderDash: [],
  12. borderDashOffset: 0.0,
  13. borderJoinStyle: 'miter',
  14. fill: true // do we fill in the area between the line and its base axis
  15. };
  16. Chart.elements.Line = Chart.Element.extend({
  17. lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {
  18. var me = this;
  19. var ctx = me._chart.ctx;
  20. var spanGaps = me._view ? me._view.spanGaps : false;
  21. if (point._view.skip && !spanGaps) {
  22. skipHandler.call(me, previousPoint, point, nextPoint);
  23. } else if (previousPoint._view.skip && !spanGaps) {
  24. previousSkipHandler.call(me, previousPoint, point, nextPoint);
  25. } else if (point._view.tension === 0) {
  26. ctx.lineTo(point._view.x, point._view.y);
  27. } else {
  28. // Line between points
  29. ctx.bezierCurveTo(
  30. previousPoint._view.controlPointNextX,
  31. previousPoint._view.controlPointNextY,
  32. point._view.controlPointPreviousX,
  33. point._view.controlPointPreviousY,
  34. point._view.x,
  35. point._view.y
  36. );
  37. }
  38. },
  39. draw: function() {
  40. var me = this;
  41. var vm = me._view;
  42. var ctx = me._chart.ctx;
  43. var first = me._children[0];
  44. var last = me._children[me._children.length - 1];
  45. function loopBackToStart(drawLineToCenter) {
  46. if (!first._view.skip && !last._view.skip) {
  47. // Draw a bezier line from last to first
  48. ctx.bezierCurveTo(
  49. last._view.controlPointNextX,
  50. last._view.controlPointNextY,
  51. first._view.controlPointPreviousX,
  52. first._view.controlPointPreviousY,
  53. first._view.x,
  54. first._view.y
  55. );
  56. } else if (drawLineToCenter) {
  57. // Go to center
  58. ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
  59. }
  60. }
  61. ctx.save();
  62. // If we had points and want to fill this line, do so.
  63. if (me._children.length > 0 && vm.fill) {
  64. // Draw the background first (so the border is always on top)
  65. ctx.beginPath();
  66. helpers.each(me._children, function(point, index) {
  67. var previous = helpers.previousItem(me._children, index);
  68. var next = helpers.nextItem(me._children, index);
  69. // First point moves to it's starting position no matter what
  70. if (index === 0) {
  71. if (me._loop) {
  72. ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);
  73. } else {
  74. ctx.moveTo(point._view.x, vm.scaleZero);
  75. }
  76. if (point._view.skip) {
  77. if (!me._loop) {
  78. ctx.moveTo(next._view.x, me._view.scaleZero);
  79. }
  80. } else {
  81. ctx.lineTo(point._view.x, point._view.y);
  82. }
  83. } else {
  84. me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
  85. if (me._loop) {
  86. // Go to center
  87. ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
  88. } else {
  89. ctx.lineTo(previousPoint._view.x, me._view.scaleZero);
  90. ctx.moveTo(nextPoint._view.x, me._view.scaleZero);
  91. }
  92. }, function(previousPoint, point) {
  93. // If we skipped the last point, draw a line to ourselves so that the fill is nice
  94. ctx.lineTo(point._view.x, point._view.y);
  95. });
  96. }
  97. }, me);
  98. // For radial scales, loop back around to the first point
  99. if (me._loop) {
  100. loopBackToStart(true);
  101. } else {
  102. //Round off the line by going to the base of the chart, back to the start, then fill.
  103. ctx.lineTo(me._children[me._children.length - 1]._view.x, vm.scaleZero);
  104. ctx.lineTo(me._children[0]._view.x, vm.scaleZero);
  105. }
  106. ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
  107. ctx.closePath();
  108. ctx.fill();
  109. }
  110. var globalOptionLineElements = globalDefaults.elements.line;
  111. // Now draw the line between all the points with any borders
  112. ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
  113. // IE 9 and 10 do not support line dash
  114. if (ctx.setLineDash) {
  115. ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
  116. }
  117. ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
  118. ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
  119. ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
  120. ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
  121. ctx.beginPath();
  122. helpers.each(me._children, function(point, index) {
  123. var previous = helpers.previousItem(me._children, index);
  124. var next = helpers.nextItem(me._children, index);
  125. if (index === 0) {
  126. ctx.moveTo(point._view.x, point._view.y);
  127. } else {
  128. me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
  129. ctx.moveTo(nextPoint._view.x, nextPoint._view.y);
  130. }, function(previousPoint, point) {
  131. // If we skipped the last point, move up to our point preventing a line from being drawn
  132. ctx.moveTo(point._view.x, point._view.y);
  133. });
  134. }
  135. }, me);
  136. if (me._loop && me._children.length > 0) {
  137. loopBackToStart();
  138. }
  139. ctx.stroke();
  140. ctx.restore();
  141. }
  142. });
  143. };