base.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import { __assign, __extends } from "tslib";
  2. import { AbstractShape } from '@antv/g-base';
  3. import { setShadow, setTransform, setClip } from '../util/svg';
  4. import { createDom } from '../util/dom';
  5. import { refreshElement } from '../util/draw';
  6. import { SVG_ATTR_MAP } from '../constant';
  7. import * as Shape from './index';
  8. import Group from '../group';
  9. import { getBBoxMethod } from '@antv/g-base';
  10. var ShapeBase = /** @class */ (function (_super) {
  11. __extends(ShapeBase, _super);
  12. function ShapeBase() {
  13. var _this = _super !== null && _super.apply(this, arguments) || this;
  14. _this.type = 'svg';
  15. _this.canFill = false;
  16. _this.canStroke = false;
  17. return _this;
  18. }
  19. ShapeBase.prototype.getDefaultAttrs = function () {
  20. var attrs = _super.prototype.getDefaultAttrs.call(this);
  21. // 设置默认值
  22. return __assign(__assign({}, attrs), { lineWidth: 1, lineAppendWidth: 0, strokeOpacity: 1, fillOpacity: 1 });
  23. };
  24. // 覆盖基类的 afterAttrsChange 方法
  25. ShapeBase.prototype.afterAttrsChange = function (targetAttrs) {
  26. _super.prototype.afterAttrsChange.call(this, targetAttrs);
  27. var canvas = this.get('canvas');
  28. // 只有挂载到画布下,才对元素进行实际渲染
  29. if (canvas && canvas.get('autoDraw')) {
  30. var context = canvas.get('context');
  31. this.draw(context, targetAttrs);
  32. }
  33. };
  34. ShapeBase.prototype.getShapeBase = function () {
  35. return Shape;
  36. };
  37. ShapeBase.prototype.getGroupBase = function () {
  38. return Group;
  39. };
  40. /**
  41. * 一些方法调用会引起画布变化
  42. * @param {ChangeType} changeType 改变的类型
  43. */
  44. ShapeBase.prototype.onCanvasChange = function (changeType) {
  45. refreshElement(this, changeType);
  46. };
  47. ShapeBase.prototype.calculateBBox = function () {
  48. var el = this.get('el');
  49. var bbox = null;
  50. // 包围盒计算依赖于绘制,如果还没有生成对应的 Dom 元素,则包围盒的长宽均为 0
  51. if (el) {
  52. bbox = el.getBBox();
  53. }
  54. else {
  55. var bboxMethod = getBBoxMethod(this.get('type'));
  56. if (bboxMethod) {
  57. bbox = bboxMethod(this);
  58. }
  59. }
  60. if (bbox) {
  61. var x = bbox.x, y = bbox.y, width = bbox.width, height = bbox.height;
  62. var lineWidth = this.getHitLineWidth();
  63. var halfWidth = lineWidth / 2;
  64. var minX = x - halfWidth;
  65. var minY = y - halfWidth;
  66. var maxX = x + width + halfWidth;
  67. var maxY = y + height + halfWidth;
  68. return {
  69. x: minX,
  70. y: minY,
  71. minX: minX,
  72. minY: minY,
  73. maxX: maxX,
  74. maxY: maxY,
  75. width: width + lineWidth,
  76. height: height + lineWidth,
  77. };
  78. }
  79. return {
  80. x: 0,
  81. y: 0,
  82. minX: 0,
  83. minY: 0,
  84. maxX: 0,
  85. maxY: 0,
  86. width: 0,
  87. height: 0,
  88. };
  89. };
  90. ShapeBase.prototype.isFill = function () {
  91. var _a = this.attr(), fill = _a.fill, fillStyle = _a.fillStyle;
  92. return (fill || fillStyle || this.isClipShape()) && this.canFill;
  93. };
  94. ShapeBase.prototype.isStroke = function () {
  95. var _a = this.attr(), stroke = _a.stroke, strokeStyle = _a.strokeStyle;
  96. return (stroke || strokeStyle) && this.canStroke;
  97. };
  98. ShapeBase.prototype.draw = function (context, targetAttrs) {
  99. var el = this.get('el');
  100. if (this.get('destroyed')) {
  101. if (el) {
  102. el.parentNode.removeChild(el);
  103. }
  104. }
  105. else {
  106. if (!el) {
  107. createDom(this);
  108. }
  109. setClip(this, context);
  110. this.createPath(context, targetAttrs);
  111. this.shadow(context, targetAttrs);
  112. this.strokeAndFill(context, targetAttrs);
  113. this.transform(targetAttrs);
  114. }
  115. };
  116. /**
  117. * @protected
  118. * 绘制图形的路径
  119. * @param {Defs} context 上下文
  120. * @param {ShapeAttrs} targetAttrs 渲染的目标属性
  121. */
  122. ShapeBase.prototype.createPath = function (context, targetAttrs) { };
  123. // stroke and fill
  124. ShapeBase.prototype.strokeAndFill = function (context, targetAttrs) {
  125. var attrs = targetAttrs || this.attr();
  126. var fill = attrs.fill, fillStyle = attrs.fillStyle, stroke = attrs.stroke, strokeStyle = attrs.strokeStyle, fillOpacity = attrs.fillOpacity, strokeOpacity = attrs.strokeOpacity, lineWidth = attrs.lineWidth;
  127. var el = this.get('el');
  128. if (this.canFill) {
  129. // 初次渲染和更新渲染的逻辑有所不同: 初次渲染值为空时,需要设置为 none,否则就会是黑色,而更新渲染则不需要
  130. if (!targetAttrs) {
  131. this._setColor(context, 'fill', fill || fillStyle);
  132. }
  133. else if ('fill' in attrs) {
  134. this._setColor(context, 'fill', fill);
  135. }
  136. else if ('fillStyle' in attrs) {
  137. // compatible with fillStyle
  138. this._setColor(context, 'fill', fillStyle);
  139. }
  140. if (fillOpacity) {
  141. el.setAttribute(SVG_ATTR_MAP['fillOpacity'], fillOpacity);
  142. }
  143. }
  144. if (this.canStroke && lineWidth > 0) {
  145. if (!targetAttrs) {
  146. this._setColor(context, 'stroke', stroke || strokeStyle);
  147. }
  148. else if ('stroke' in attrs) {
  149. this._setColor(context, 'stroke', stroke);
  150. }
  151. else if ('strokeStyle' in attrs) {
  152. // compatible with strokeStyle
  153. this._setColor(context, 'stroke', strokeStyle);
  154. }
  155. if (strokeOpacity) {
  156. el.setAttribute(SVG_ATTR_MAP['strokeOpacity'], strokeOpacity);
  157. }
  158. if (lineWidth) {
  159. el.setAttribute(SVG_ATTR_MAP['lineWidth'], lineWidth);
  160. }
  161. }
  162. };
  163. ShapeBase.prototype._setColor = function (context, attr, value) {
  164. var el = this.get('el');
  165. if (!value) {
  166. // need to set `none` to avoid default value
  167. el.setAttribute(SVG_ATTR_MAP[attr], 'none');
  168. return;
  169. }
  170. value = value.trim();
  171. if (/^[r,R,L,l]{1}[\s]*\(/.test(value)) {
  172. var id = context.find('gradient', value);
  173. if (!id) {
  174. id = context.addGradient(value);
  175. }
  176. el.setAttribute(SVG_ATTR_MAP[attr], "url(#" + id + ")");
  177. }
  178. else if (/^[p,P]{1}[\s]*\(/.test(value)) {
  179. var id = context.find('pattern', value);
  180. if (!id) {
  181. id = context.addPattern(value);
  182. }
  183. el.setAttribute(SVG_ATTR_MAP[attr], "url(#" + id + ")");
  184. }
  185. else {
  186. el.setAttribute(SVG_ATTR_MAP[attr], value);
  187. }
  188. };
  189. ShapeBase.prototype.shadow = function (context, targetAttrs) {
  190. var attrs = this.attr();
  191. var _a = targetAttrs || attrs, shadowOffsetX = _a.shadowOffsetX, shadowOffsetY = _a.shadowOffsetY, shadowBlur = _a.shadowBlur, shadowColor = _a.shadowColor;
  192. if (shadowOffsetX || shadowOffsetY || shadowBlur || shadowColor) {
  193. setShadow(this, context);
  194. }
  195. };
  196. ShapeBase.prototype.transform = function (targetAttrs) {
  197. var attrs = this.attr();
  198. var matrix = (targetAttrs || attrs).matrix;
  199. if (matrix) {
  200. setTransform(this);
  201. }
  202. };
  203. ShapeBase.prototype.isInShape = function (refX, refY) {
  204. return this.isPointInPath(refX, refY);
  205. };
  206. ShapeBase.prototype.isPointInPath = function (refX, refY) {
  207. var el = this.get('el');
  208. var canvas = this.get('canvas');
  209. var bbox = canvas.get('el').getBoundingClientRect();
  210. var clientX = refX + bbox.left;
  211. var clientY = refY + bbox.top;
  212. var element = document.elementFromPoint(clientX, clientY);
  213. if (element && element.isEqualNode(el)) {
  214. return true;
  215. }
  216. return false;
  217. };
  218. /**
  219. * 获取线拾取的宽度
  220. * @returns {number} 线的拾取宽度
  221. */
  222. ShapeBase.prototype.getHitLineWidth = function () {
  223. var _a = this.attrs, lineWidth = _a.lineWidth, lineAppendWidth = _a.lineAppendWidth;
  224. if (this.isStroke()) {
  225. return lineWidth + lineAppendWidth;
  226. }
  227. return 0;
  228. };
  229. return ShapeBase;
  230. }(AbstractShape));
  231. export default ShapeBase;
  232. //# sourceMappingURL=base.js.map