element.rectangle.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. 'use strict';
  2. module.exports = function(Chart) {
  3. var globalOpts = Chart.defaults.global;
  4. globalOpts.elements.rectangle = {
  5. backgroundColor: globalOpts.defaultColor,
  6. borderWidth: 0,
  7. borderColor: globalOpts.defaultColor,
  8. borderSkipped: 'bottom'
  9. };
  10. function isVertical(bar) {
  11. return bar._view.width !== undefined;
  12. }
  13. /**
  14. * Helper function to get the bounds of the bar regardless of the orientation
  15. * @private
  16. * @param bar {Chart.Element.Rectangle} the bar
  17. * @return {Bounds} bounds of the bar
  18. */
  19. function getBarBounds(bar) {
  20. var vm = bar._view;
  21. var x1, x2, y1, y2;
  22. if (isVertical(bar)) {
  23. // vertical
  24. var halfWidth = vm.width / 2;
  25. x1 = vm.x - halfWidth;
  26. x2 = vm.x + halfWidth;
  27. y1 = Math.min(vm.y, vm.base);
  28. y2 = Math.max(vm.y, vm.base);
  29. } else {
  30. // horizontal bar
  31. var halfHeight = vm.height / 2;
  32. x1 = Math.min(vm.x, vm.base);
  33. x2 = Math.max(vm.x, vm.base);
  34. y1 = vm.y - halfHeight;
  35. y2 = vm.y + halfHeight;
  36. }
  37. return {
  38. left: x1,
  39. top: y1,
  40. right: x2,
  41. bottom: y2
  42. };
  43. }
  44. Chart.elements.Rectangle = Chart.Element.extend({
  45. draw: function() {
  46. var ctx = this._chart.ctx;
  47. var vm = this._view;
  48. var halfWidth = vm.width / 2,
  49. leftX = vm.x - halfWidth,
  50. rightX = vm.x + halfWidth,
  51. top = vm.base - (vm.base - vm.y),
  52. halfStroke = vm.borderWidth / 2;
  53. // Canvas doesn't allow us to stroke inside the width so we can
  54. // adjust the sizes to fit if we're setting a stroke on the line
  55. if (vm.borderWidth) {
  56. leftX += halfStroke;
  57. rightX -= halfStroke;
  58. top += halfStroke;
  59. }
  60. ctx.beginPath();
  61. ctx.fillStyle = vm.backgroundColor;
  62. ctx.strokeStyle = vm.borderColor;
  63. ctx.lineWidth = vm.borderWidth;
  64. // Corner points, from bottom-left to bottom-right clockwise
  65. // | 1 2 |
  66. // | 0 3 |
  67. var corners = [
  68. [leftX, vm.base],
  69. [leftX, top],
  70. [rightX, top],
  71. [rightX, vm.base]
  72. ];
  73. // Find first (starting) corner with fallback to 'bottom'
  74. var borders = ['bottom', 'left', 'top', 'right'];
  75. var startCorner = borders.indexOf(vm.borderSkipped, 0);
  76. if (startCorner === -1) {
  77. startCorner = 0;
  78. }
  79. function cornerAt(index) {
  80. return corners[(startCorner + index) % 4];
  81. }
  82. // Draw rectangle from 'startCorner'
  83. var corner = cornerAt(0);
  84. ctx.moveTo(corner[0], corner[1]);
  85. for (var i = 1; i < 4; i++) {
  86. corner = cornerAt(i);
  87. ctx.lineTo(corner[0], corner[1]);
  88. }
  89. ctx.fill();
  90. if (vm.borderWidth) {
  91. ctx.stroke();
  92. }
  93. },
  94. height: function() {
  95. var vm = this._view;
  96. return vm.base - vm.y;
  97. },
  98. inRange: function(mouseX, mouseY) {
  99. var inRange = false;
  100. if (this._view) {
  101. var bounds = getBarBounds(this);
  102. inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom;
  103. }
  104. return inRange;
  105. },
  106. inLabelRange: function(mouseX, mouseY) {
  107. var me = this;
  108. if (!me._view) {
  109. return false;
  110. }
  111. var inRange = false;
  112. var bounds = getBarBounds(me);
  113. if (isVertical(me)) {
  114. inRange = mouseX >= bounds.left && mouseX <= bounds.right;
  115. } else {
  116. inRange = mouseY >= bounds.top && mouseY <= bounds.bottom;
  117. }
  118. return inRange;
  119. },
  120. inXRange: function(mouseX) {
  121. var bounds = getBarBounds(this);
  122. return mouseX >= bounds.left && mouseX <= bounds.right;
  123. },
  124. inYRange: function(mouseY) {
  125. var bounds = getBarBounds(this);
  126. return mouseY >= bounds.top && mouseY <= bounds.bottom;
  127. },
  128. getCenterPoint: function() {
  129. var vm = this._view;
  130. var x, y;
  131. if (isVertical(this)) {
  132. x = vm.x;
  133. y = (vm.y + vm.base) / 2;
  134. } else {
  135. x = (vm.x + vm.base) / 2;
  136. y = vm.y;
  137. }
  138. return {x: x, y: y};
  139. },
  140. getArea: function() {
  141. var vm = this._view;
  142. return vm.width * Math.abs(vm.y - vm.base);
  143. },
  144. tooltipPosition: function() {
  145. var vm = this._view;
  146. return {
  147. x: vm.x,
  148. y: vm.y
  149. };
  150. }
  151. });
  152. };