shape.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var tslib_1 = require("tslib");
  4. var element_1 = require("./element");
  5. var matrix_1 = require("../util/matrix");
  6. var AbstractShape = /** @class */ (function (_super) {
  7. tslib_1.__extends(AbstractShape, _super);
  8. function AbstractShape(cfg) {
  9. return _super.call(this, cfg) || this;
  10. }
  11. // 是否在包围盒内
  12. AbstractShape.prototype._isInBBox = function (refX, refY) {
  13. var bbox = this.getBBox();
  14. return bbox.minX <= refX && bbox.maxX >= refX && bbox.minY <= refY && bbox.maxY >= refY;
  15. };
  16. /**
  17. * 属性更改后需要做的事情
  18. * @protected
  19. * @param {ShapeAttrs} targetAttrs 渲染的图像属性
  20. */
  21. AbstractShape.prototype.afterAttrsChange = function (targetAttrs) {
  22. _super.prototype.afterAttrsChange.call(this, targetAttrs);
  23. this.clearCacheBBox();
  24. };
  25. // 计算包围盒时,需要缓存,这是一个高频的操作
  26. AbstractShape.prototype.getBBox = function () {
  27. var bbox = this.cfg.bbox;
  28. if (!bbox) {
  29. bbox = this.calculateBBox();
  30. this.set('bbox', bbox);
  31. }
  32. return bbox;
  33. };
  34. // 计算相对于画布的包围盒
  35. AbstractShape.prototype.getCanvasBBox = function () {
  36. var canvasBBox = this.cfg.canvasBBox;
  37. if (!canvasBBox) {
  38. canvasBBox = this.calculateCanvasBBox();
  39. this.set('canvasBBox', canvasBBox);
  40. }
  41. return canvasBBox;
  42. };
  43. AbstractShape.prototype.applyMatrix = function (matrix) {
  44. _super.prototype.applyMatrix.call(this, matrix);
  45. // 清理掉缓存的包围盒
  46. this.set('canvasBBox', null);
  47. };
  48. /**
  49. * 计算相对于画布的包围盒,默认等同于 bbox
  50. * @return {BBox} 包围盒
  51. */
  52. AbstractShape.prototype.calculateCanvasBBox = function () {
  53. var bbox = this.getBBox();
  54. var totalMatrix = this.getTotalMatrix();
  55. var minX = bbox.minX, minY = bbox.minY, maxX = bbox.maxX, maxY = bbox.maxY;
  56. if (totalMatrix) {
  57. var topLeft = matrix_1.multiplyVec2(totalMatrix, [bbox.minX, bbox.minY]);
  58. var topRight = matrix_1.multiplyVec2(totalMatrix, [bbox.maxX, bbox.minY]);
  59. var bottomLeft = matrix_1.multiplyVec2(totalMatrix, [bbox.minX, bbox.maxY]);
  60. var bottomRight = matrix_1.multiplyVec2(totalMatrix, [bbox.maxX, bbox.maxY]);
  61. minX = Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]);
  62. maxX = Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]);
  63. minY = Math.min(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]);
  64. maxY = Math.max(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]);
  65. }
  66. var attrs = this.attrs;
  67. // 如果存在 shadow 则计算 shadow
  68. if (attrs.shadowColor) {
  69. var _a = attrs.shadowBlur, shadowBlur = _a === void 0 ? 0 : _a, _b = attrs.shadowOffsetX, shadowOffsetX = _b === void 0 ? 0 : _b, _c = attrs.shadowOffsetY, shadowOffsetY = _c === void 0 ? 0 : _c;
  70. var shadowLeft = minX - shadowBlur + shadowOffsetX;
  71. var shadowRight = maxX + shadowBlur + shadowOffsetX;
  72. var shadowTop = minY - shadowBlur + shadowOffsetY;
  73. var shadowBottom = maxY + shadowBlur + shadowOffsetY;
  74. minX = Math.min(minX, shadowLeft);
  75. maxX = Math.max(maxX, shadowRight);
  76. minY = Math.min(minY, shadowTop);
  77. maxY = Math.max(maxY, shadowBottom);
  78. }
  79. return {
  80. x: minX,
  81. y: minY,
  82. minX: minX,
  83. minY: minY,
  84. maxX: maxX,
  85. maxY: maxY,
  86. width: maxX - minX,
  87. height: maxY - minY,
  88. };
  89. };
  90. /**
  91. * @protected
  92. * 清理缓存的 bbox
  93. */
  94. AbstractShape.prototype.clearCacheBBox = function () {
  95. this.set('bbox', null);
  96. this.set('canvasBBox', null);
  97. };
  98. // 实现接口
  99. AbstractShape.prototype.isClipShape = function () {
  100. return this.get('isClipShape');
  101. };
  102. /**
  103. * @protected
  104. * 不同的图形自己实现是否在图形内部的逻辑,要判断边和填充区域
  105. * @param {number} refX 相对于图形的坐标 x
  106. * @param {number} refY 相对于图形的坐标 Y
  107. * @return {boolean} 点是否在图形内部
  108. */
  109. AbstractShape.prototype.isInShape = function (refX, refY) {
  110. return false;
  111. };
  112. /**
  113. * 是否仅仅使用 BBox 检测就可以判定拾取到图形
  114. * 默认是 false,但是有些图形例如 image、marker 等都可直接使用 BBox 的检测而不需要使用图形拾取
  115. * @return {Boolean} 仅仅使用 BBox 进行拾取
  116. */
  117. AbstractShape.prototype.isOnlyHitBox = function () {
  118. return false;
  119. };
  120. // 不同的 Shape 各自实现
  121. AbstractShape.prototype.isHit = function (x, y) {
  122. var startArrowShape = this.get('startArrowShape');
  123. var endArrowShape = this.get('endArrowShape');
  124. var vec = [x, y, 1];
  125. vec = this.invertFromMatrix(vec);
  126. var refX = vec[0], refY = vec[1];
  127. var inBBox = this._isInBBox(refX, refY);
  128. // 跳过图形的拾取,在某些图形中可以省略一倍的检测成本
  129. if (this.isOnlyHitBox()) {
  130. return inBBox;
  131. }
  132. // 被裁减掉的和不在包围盒内的不进行计算
  133. if (inBBox && !this.isClipped(refX, refY)) {
  134. // 对图形进行拾取判断
  135. if (this.isInShape(refX, refY)) {
  136. return true;
  137. }
  138. // 对起始箭头进行拾取判断
  139. if (startArrowShape && startArrowShape.isHit(refX, refY)) {
  140. return true;
  141. }
  142. // 对结束箭头进行拾取判断
  143. if (endArrowShape && endArrowShape.isHit(refX, refY)) {
  144. return true;
  145. }
  146. }
  147. return false;
  148. };
  149. return AbstractShape;
  150. }(element_1.default));
  151. exports.default = AbstractShape;
  152. //# sourceMappingURL=shape.js.map