element.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. import { __extends } from "tslib";
  2. import { each, isEqual, isFunction, isNumber, isObject, isArray, noop, mix, upperFirst, uniqueId } from '@antv/util';
  3. import { ext } from '@antv/matrix-util';
  4. import { removeFromArray, isParent } from '../util/util';
  5. import { multiplyMatrix, multiplyVec2, invert } from '../util/matrix';
  6. import Base from './base';
  7. var transform = ext.transform;
  8. var MATRIX = 'matrix';
  9. var CLONE_CFGS = ['zIndex', 'capture', 'visible', 'type'];
  10. // 可以在 toAttrs 中设置,但不属于绘图属性的字段
  11. var RESERVED_PORPS = ['repeat'];
  12. var DELEGATION_SPLIT = ':';
  13. var WILDCARD = '*';
  14. // 需要考虑数组嵌套数组的场景
  15. // 数组嵌套对象的场景不考虑
  16. function _cloneArrayAttr(arr) {
  17. var result = [];
  18. for (var i = 0; i < arr.length; i++) {
  19. if (isArray(arr[i])) {
  20. result.push([].concat(arr[i]));
  21. }
  22. else {
  23. result.push(arr[i]);
  24. }
  25. }
  26. return result;
  27. }
  28. function getFormatFromAttrs(toAttrs, shape) {
  29. var fromAttrs = {};
  30. var attrs = shape.attrs;
  31. for (var k in toAttrs) {
  32. fromAttrs[k] = attrs[k];
  33. }
  34. return fromAttrs;
  35. }
  36. function getFormatToAttrs(props, shape) {
  37. var toAttrs = {};
  38. var attrs = shape.attr();
  39. each(props, function (v, k) {
  40. if (RESERVED_PORPS.indexOf(k) === -1 && !isEqual(attrs[k], v)) {
  41. toAttrs[k] = v;
  42. }
  43. });
  44. return toAttrs;
  45. }
  46. function checkExistedAttrs(animations, animation) {
  47. if (animation.onFrame) {
  48. return animations;
  49. }
  50. var startTime = animation.startTime, delay = animation.delay, duration = animation.duration;
  51. var hasOwnProperty = Object.prototype.hasOwnProperty;
  52. each(animations, function (item) {
  53. // 后一个动画开始执行的时间 < 前一个动画的结束时间 && 后一个动画的执行时间 > 前一个动画的延迟
  54. if (startTime + delay < item.startTime + item.delay + item.duration && duration > item.delay) {
  55. each(animation.toAttrs, function (v, k) {
  56. if (hasOwnProperty.call(item.toAttrs, k)) {
  57. delete item.toAttrs[k];
  58. delete item.fromAttrs[k];
  59. }
  60. });
  61. }
  62. });
  63. return animations;
  64. }
  65. var Element = /** @class */ (function (_super) {
  66. __extends(Element, _super);
  67. function Element(cfg) {
  68. var _this = _super.call(this, cfg) || this;
  69. /**
  70. * @protected
  71. * 图形属性
  72. * @type {ShapeAttrs}
  73. */
  74. _this.attrs = {};
  75. var attrs = _this.getDefaultAttrs();
  76. mix(attrs, cfg.attrs);
  77. _this.attrs = attrs;
  78. _this.initAttrs(attrs);
  79. _this.initAnimate(); // 初始化动画
  80. return _this;
  81. }
  82. // override
  83. Element.prototype.getDefaultCfg = function () {
  84. return {
  85. visible: true,
  86. capture: true,
  87. zIndex: 0,
  88. };
  89. };
  90. /**
  91. * @protected
  92. * 获取默认的属相
  93. */
  94. Element.prototype.getDefaultAttrs = function () {
  95. return {
  96. matrix: this.getDefaultMatrix(),
  97. opacity: 1,
  98. };
  99. };
  100. /**
  101. * @protected
  102. * 一些方法调用会引起画布变化
  103. * @param {ChangeType} changeType 改变的类型
  104. */
  105. Element.prototype.onCanvasChange = function (changeType) { };
  106. /**
  107. * @protected
  108. * 初始化属性,有些属性需要加工
  109. * @param {object} attrs 属性值
  110. */
  111. Element.prototype.initAttrs = function (attrs) { };
  112. /**
  113. * @protected
  114. * 初始化动画
  115. */
  116. Element.prototype.initAnimate = function () {
  117. this.set('animable', true);
  118. this.set('animating', false);
  119. };
  120. Element.prototype.isGroup = function () {
  121. return false;
  122. };
  123. Element.prototype.getParent = function () {
  124. return this.get('parent');
  125. };
  126. Element.prototype.getCanvas = function () {
  127. return this.get('canvas');
  128. };
  129. Element.prototype.attr = function () {
  130. var _a;
  131. var args = [];
  132. for (var _i = 0; _i < arguments.length; _i++) {
  133. args[_i] = arguments[_i];
  134. }
  135. var name = args[0], value = args[1];
  136. if (!name)
  137. return this.attrs;
  138. if (isObject(name)) {
  139. for (var k in name) {
  140. this.setAttr(k, name[k]);
  141. }
  142. this.afterAttrsChange(name);
  143. return this;
  144. }
  145. if (args.length === 2) {
  146. this.setAttr(name, value);
  147. this.afterAttrsChange((_a = {},
  148. _a[name] = value,
  149. _a));
  150. return this;
  151. }
  152. return this.attrs[name];
  153. };
  154. // 是否被裁剪,被裁剪则不显示,不参与拾取
  155. Element.prototype.isClipped = function (refX, refY) {
  156. var clip = this.getClip();
  157. return clip && !clip.isHit(refX, refY);
  158. };
  159. /**
  160. * 内部设置属性值的接口
  161. * @param {string} name 属性名
  162. * @param {any} value 属性值
  163. */
  164. Element.prototype.setAttr = function (name, value) {
  165. var originValue = this.attrs[name];
  166. if (originValue !== value) {
  167. this.attrs[name] = value;
  168. this.onAttrChange(name, value, originValue);
  169. }
  170. };
  171. /**
  172. * @protected
  173. * 属性值发生改变
  174. * @param {string} name 属性名
  175. * @param {any} value 属性值
  176. * @param {any} originValue 属性值
  177. */
  178. Element.prototype.onAttrChange = function (name, value, originValue) {
  179. if (name === 'matrix') {
  180. this.set('totalMatrix', null);
  181. }
  182. };
  183. /**
  184. * 属性更改后需要做的事情
  185. * @protected
  186. */
  187. Element.prototype.afterAttrsChange = function (targetAttrs) {
  188. if (this.cfg.isClipShape) {
  189. var applyTo = this.cfg.applyTo;
  190. if (applyTo) {
  191. applyTo.onCanvasChange('clip');
  192. }
  193. }
  194. else {
  195. this.onCanvasChange('attr');
  196. }
  197. };
  198. Element.prototype.show = function () {
  199. // 不是高频操作直接使用 set
  200. this.set('visible', true);
  201. this.onCanvasChange('show');
  202. return this;
  203. };
  204. Element.prototype.hide = function () {
  205. // 不是高频操作直接使用 set
  206. this.set('visible', false);
  207. this.onCanvasChange('hide');
  208. return this;
  209. };
  210. Element.prototype.setZIndex = function (zIndex) {
  211. this.set('zIndex', zIndex);
  212. var parent = this.getParent();
  213. if (parent) {
  214. // 改变 zIndex 不应该立即触发渲染 (调用 onCanvasChange('zIndex')),需要经过 sort 再触发
  215. parent.sort();
  216. }
  217. return this;
  218. };
  219. Element.prototype.toFront = function () {
  220. var parent = this.getParent();
  221. if (!parent) {
  222. return;
  223. }
  224. var children = parent.getChildren();
  225. var el = this.get('el');
  226. var index = children.indexOf(this);
  227. children.splice(index, 1);
  228. children.push(this);
  229. this.onCanvasChange('zIndex');
  230. };
  231. Element.prototype.toBack = function () {
  232. var parent = this.getParent();
  233. if (!parent) {
  234. return;
  235. }
  236. var children = parent.getChildren();
  237. var el = this.get('el');
  238. var index = children.indexOf(this);
  239. children.splice(index, 1);
  240. children.unshift(this);
  241. this.onCanvasChange('zIndex');
  242. };
  243. Element.prototype.remove = function (destroy) {
  244. if (destroy === void 0) { destroy = true; }
  245. var parent = this.getParent();
  246. if (parent) {
  247. removeFromArray(parent.getChildren(), this);
  248. if (!parent.get('clearing')) {
  249. // 如果父元素正在清理,当前元素不触发 remove
  250. this.onCanvasChange('remove');
  251. }
  252. }
  253. else {
  254. this.onCanvasChange('remove');
  255. }
  256. if (destroy) {
  257. this.destroy();
  258. }
  259. };
  260. Element.prototype.resetMatrix = function () {
  261. this.attr(MATRIX, this.getDefaultMatrix());
  262. this.onCanvasChange('matrix');
  263. };
  264. Element.prototype.getMatrix = function () {
  265. return this.attr(MATRIX);
  266. };
  267. Element.prototype.setMatrix = function (m) {
  268. this.attr(MATRIX, m);
  269. this.onCanvasChange('matrix');
  270. };
  271. // 获取总的 matrix
  272. Element.prototype.getTotalMatrix = function () {
  273. var totalMatrix = this.cfg.totalMatrix;
  274. if (!totalMatrix) {
  275. var currentMatrix = this.attr('matrix');
  276. var parentMatrix = this.cfg.parentMatrix;
  277. if (parentMatrix && currentMatrix) {
  278. totalMatrix = multiplyMatrix(parentMatrix, currentMatrix);
  279. }
  280. else {
  281. totalMatrix = currentMatrix || parentMatrix;
  282. }
  283. this.set('totalMatrix', totalMatrix);
  284. }
  285. return totalMatrix;
  286. };
  287. // 上层分组设置 matrix
  288. Element.prototype.applyMatrix = function (matrix) {
  289. var currentMatrix = this.attr('matrix');
  290. var totalMatrix = null;
  291. if (matrix && currentMatrix) {
  292. totalMatrix = multiplyMatrix(matrix, currentMatrix);
  293. }
  294. else {
  295. totalMatrix = currentMatrix || matrix;
  296. }
  297. this.set('totalMatrix', totalMatrix);
  298. this.set('parentMatrix', matrix);
  299. };
  300. /**
  301. * @protected
  302. * 获取默认的矩阵
  303. * @returns {number[]|null} 默认的矩阵
  304. */
  305. Element.prototype.getDefaultMatrix = function () {
  306. return null;
  307. };
  308. // 将向量应用设置的矩阵
  309. Element.prototype.applyToMatrix = function (v) {
  310. var matrix = this.attr('matrix');
  311. if (matrix) {
  312. return multiplyVec2(matrix, v);
  313. }
  314. return v;
  315. };
  316. // 根据设置的矩阵,将向量转换相对于图形/分组的位置
  317. Element.prototype.invertFromMatrix = function (v) {
  318. var matrix = this.attr('matrix');
  319. if (matrix) {
  320. var invertMatrix = invert(matrix);
  321. if (invertMatrix) {
  322. return multiplyVec2(invertMatrix, v);
  323. }
  324. }
  325. return v;
  326. };
  327. // 设置 clip
  328. Element.prototype.setClip = function (clipCfg) {
  329. var canvas = this.getCanvas();
  330. // 应该只设置当前元素的 clip,不应该去修改 clip 本身,方便 clip 被复用
  331. // TODO: setClip 的传参既 shape 配置,也支持 shape 对象
  332. // const preShape = this.get('clipShape');
  333. // if (preShape) {
  334. // // 将之前的 clipShape 销毁
  335. // preShape.destroy();
  336. // }
  337. var clipShape = null;
  338. // 如果配置项为 null,则不移除 clipShape
  339. if (clipCfg) {
  340. var ShapeBase = this.getShapeBase();
  341. var shapeType = upperFirst(clipCfg.type);
  342. var Cons = ShapeBase[shapeType];
  343. if (Cons) {
  344. clipShape = new Cons({
  345. type: clipCfg.type,
  346. isClipShape: true,
  347. applyTo: this,
  348. attrs: clipCfg.attrs,
  349. canvas: canvas,
  350. });
  351. }
  352. }
  353. this.set('clipShape', clipShape);
  354. this.onCanvasChange('clip');
  355. return clipShape;
  356. };
  357. Element.prototype.getClip = function () {
  358. // 高频率调用的地方直接使用 this.cfg.xxx
  359. var clipShape = this.cfg.clipShape;
  360. // 未设置时返回 Null,保证一致性
  361. if (!clipShape) {
  362. return null;
  363. }
  364. return clipShape;
  365. };
  366. Element.prototype.clone = function () {
  367. var _this = this;
  368. var originAttrs = this.attrs;
  369. var attrs = {};
  370. each(originAttrs, function (i, k) {
  371. if (isArray(originAttrs[k])) {
  372. attrs[k] = _cloneArrayAttr(originAttrs[k]);
  373. }
  374. else {
  375. attrs[k] = originAttrs[k];
  376. }
  377. });
  378. var cons = this.constructor;
  379. // @ts-ignore
  380. var clone = new cons({ attrs: attrs });
  381. each(CLONE_CFGS, function (cfgName) {
  382. clone.set(cfgName, _this.get(cfgName));
  383. });
  384. return clone;
  385. };
  386. Element.prototype.destroy = function () {
  387. var destroyed = this.destroyed;
  388. if (destroyed) {
  389. return;
  390. }
  391. this.attrs = {};
  392. _super.prototype.destroy.call(this);
  393. // this.onCanvasChange('destroy');
  394. };
  395. /**
  396. * 是否处于动画暂停状态
  397. * @return {boolean} 是否处于动画暂停状态
  398. */
  399. Element.prototype.isAnimatePaused = function () {
  400. return this.get('_pause').isPaused;
  401. };
  402. /**
  403. * 执行动画,支持多种函数签名
  404. * 1. animate(toAttrs: ElementAttrs, duration: number, easing?: string, callback?: () => void, delay?: number)
  405. * 2. animate(onFrame: OnFrame, duration: number, easing?: string, callback?: () => void, delay?: number)
  406. * 3. animate(toAttrs: ElementAttrs, cfg: AnimateCfg)
  407. * 4. animate(onFrame: OnFrame, cfg: AnimateCfg)
  408. * 各个参数的含义为:
  409. * toAttrs 动画最终状态
  410. * onFrame 自定义帧动画函数
  411. * duration 动画执行时间
  412. * easing 动画缓动效果
  413. * callback 动画执行后的回调
  414. * delay 动画延迟时间
  415. */
  416. Element.prototype.animate = function () {
  417. var args = [];
  418. for (var _i = 0; _i < arguments.length; _i++) {
  419. args[_i] = arguments[_i];
  420. }
  421. if (!this.get('timeline') && !this.get('canvas')) {
  422. return;
  423. }
  424. this.set('animating', true);
  425. var timeline = this.get('timeline');
  426. if (!timeline) {
  427. timeline = this.get('canvas').get('timeline');
  428. this.set('timeline', timeline);
  429. }
  430. var animations = this.get('animations') || [];
  431. // 初始化 tick
  432. if (!timeline.timer) {
  433. timeline.initTimer();
  434. }
  435. var toAttrs = args[0], duration = args[1], _a = args[2], easing = _a === void 0 ? 'easeLinear' : _a, _b = args[3], callback = _b === void 0 ? noop : _b, _c = args[4], delay = _c === void 0 ? 0 : _c;
  436. var onFrame;
  437. var repeat;
  438. var pauseCallback;
  439. var resumeCallback;
  440. var animateCfg;
  441. // 第二个参数,既可以是动画最终状态 toAttrs,也可以是自定义帧动画函数 onFrame
  442. if (isFunction(toAttrs)) {
  443. onFrame = toAttrs;
  444. toAttrs = {};
  445. }
  446. else if (isObject(toAttrs) && toAttrs.onFrame) {
  447. // 兼容 3.0 中的写法,onFrame 和 repeat 可在 toAttrs 中设置
  448. onFrame = toAttrs.onFrame;
  449. repeat = toAttrs.repeat;
  450. }
  451. // 第二个参数,既可以是执行时间 duration,也可以是动画参数 animateCfg
  452. if (isObject(duration)) {
  453. animateCfg = duration;
  454. duration = animateCfg.duration;
  455. easing = animateCfg.easing || 'easeLinear';
  456. delay = animateCfg.delay || 0;
  457. // animateCfg 中的设置优先级更高
  458. repeat = animateCfg.repeat || repeat || false;
  459. callback = animateCfg.callback || noop;
  460. pauseCallback = animateCfg.pauseCallback || noop;
  461. resumeCallback = animateCfg.resumeCallback || noop;
  462. }
  463. else {
  464. // 第四个参数,既可以是回调函数 callback,也可以是延迟时间 delay
  465. if (isNumber(callback)) {
  466. delay = callback;
  467. callback = null;
  468. }
  469. // 第三个参数,既可以是缓动参数 easing,也可以是回调函数 callback
  470. if (isFunction(easing)) {
  471. callback = easing;
  472. easing = 'easeLinear';
  473. }
  474. else {
  475. easing = easing || 'easeLinear';
  476. }
  477. }
  478. var formatToAttrs = getFormatToAttrs(toAttrs, this);
  479. var animation = {
  480. fromAttrs: getFormatFromAttrs(formatToAttrs, this),
  481. toAttrs: formatToAttrs,
  482. duration: duration,
  483. easing: easing,
  484. repeat: repeat,
  485. callback: callback,
  486. pauseCallback: pauseCallback,
  487. resumeCallback: resumeCallback,
  488. delay: delay,
  489. startTime: timeline.getTime(),
  490. id: uniqueId(),
  491. onFrame: onFrame,
  492. pathFormatted: false,
  493. };
  494. // 如果动画元素队列中已经有这个图形了
  495. if (animations.length > 0) {
  496. // 先检查是否需要合并属性。若有相同的动画,将该属性从前一个动画中删除,直接用后一个动画中
  497. animations = checkExistedAttrs(animations, animation);
  498. }
  499. else {
  500. // 否则将图形添加到动画元素队列
  501. timeline.addAnimator(this);
  502. }
  503. animations.push(animation);
  504. this.set('animations', animations);
  505. this.set('_pause', { isPaused: false });
  506. };
  507. /**
  508. * 停止动画
  509. * @param {boolean} toEnd 是否到动画的最终状态
  510. */
  511. Element.prototype.stopAnimate = function (toEnd) {
  512. var _this = this;
  513. if (toEnd === void 0) { toEnd = true; }
  514. var animations = this.get('animations');
  515. each(animations, function (animation) {
  516. // 将动画执行到最后一帧
  517. if (toEnd) {
  518. if (animation.onFrame) {
  519. _this.attr(animation.onFrame(1));
  520. }
  521. else {
  522. _this.attr(animation.toAttrs);
  523. }
  524. }
  525. if (animation.callback) {
  526. // 动画停止时的回调
  527. animation.callback();
  528. }
  529. });
  530. this.set('animating', false);
  531. this.set('animations', []);
  532. };
  533. /**
  534. * 暂停动画
  535. */
  536. Element.prototype.pauseAnimate = function () {
  537. var timeline = this.get('timeline');
  538. var animations = this.get('animations');
  539. var pauseTime = timeline.getTime();
  540. each(animations, function (animation) {
  541. animation._paused = true;
  542. animation._pauseTime = pauseTime;
  543. if (animation.pauseCallback) {
  544. // 动画暂停时的回调
  545. animation.pauseCallback();
  546. }
  547. });
  548. // 记录下是在什么时候暂停的
  549. this.set('_pause', {
  550. isPaused: true,
  551. pauseTime: pauseTime,
  552. });
  553. return this;
  554. };
  555. /**
  556. * 恢复动画
  557. */
  558. Element.prototype.resumeAnimate = function () {
  559. var timeline = this.get('timeline');
  560. var current = timeline.getTime();
  561. var animations = this.get('animations');
  562. var pauseTime = this.get('_pause').pauseTime;
  563. // 之后更新属性需要计算动画已经执行的时长,如果暂停了,就把初始时间调后
  564. each(animations, function (animation) {
  565. animation.startTime = animation.startTime + (current - pauseTime);
  566. animation._paused = false;
  567. animation._pauseTime = null;
  568. if (animation.resumeCallback) {
  569. animation.resumeCallback();
  570. }
  571. });
  572. this.set('_pause', {
  573. isPaused: false,
  574. });
  575. this.set('animations', animations);
  576. return this;
  577. };
  578. /**
  579. * 触发委托事件
  580. * @param {string} type 事件类型
  581. * @param {GraphEvent} eventObj 事件对象
  582. */
  583. Element.prototype.emitDelegation = function (type, eventObj) {
  584. var _this = this;
  585. var paths = eventObj.propagationPath;
  586. var events = this.getEvents();
  587. var relativeShape;
  588. if (type === 'mouseenter') {
  589. relativeShape = eventObj.fromShape;
  590. }
  591. else if (type === 'mouseleave') {
  592. relativeShape = eventObj.toShape;
  593. }
  594. var _loop_1 = function (i) {
  595. var element = paths[i];
  596. // 暂定跟 name 绑定
  597. var name_1 = element.get('name');
  598. if (name_1) {
  599. // 第一个 mouseenter 和 mouseleave 的停止即可,因为后面的都是前面的 Parent
  600. if (
  601. // 只有 element 是 Group 或者 Canvas 的时候,才需要判断 isParent
  602. (element.isGroup() || (element.isCanvas && element.isCanvas())) &&
  603. relativeShape &&
  604. isParent(element, relativeShape)) {
  605. return "break";
  606. }
  607. if (isArray(name_1)) {
  608. each(name_1, function (subName) {
  609. _this.emitDelegateEvent(element, subName, eventObj);
  610. });
  611. }
  612. else {
  613. this_1.emitDelegateEvent(element, name_1, eventObj);
  614. }
  615. }
  616. };
  617. var this_1 = this;
  618. // 至少有一个对象,且第一个对象为 shape
  619. for (var i = 0; i < paths.length; i++) {
  620. var state_1 = _loop_1(i);
  621. if (state_1 === "break")
  622. break;
  623. }
  624. };
  625. Element.prototype.emitDelegateEvent = function (element, name, eventObj) {
  626. var events = this.getEvents();
  627. // 事件委托的形式 name:type
  628. var eventName = name + DELEGATION_SPLIT + eventObj.type;
  629. if (events[eventName] || events[WILDCARD]) {
  630. // 对于通配符 *,事件名称 = 委托事件名称
  631. eventObj.name = eventName;
  632. eventObj.currentTarget = element;
  633. eventObj.delegateTarget = this;
  634. // 将委托事件的监听对象 delegateObject 挂载到事件对象上
  635. eventObj.delegateObject = element.get('delegateObject');
  636. this.emit(eventName, eventObj);
  637. }
  638. };
  639. /**
  640. * 移动元素
  641. * @param {number} translateX 水平移动距离
  642. * @param {number} translateY 垂直移动距离
  643. * @return {IElement} 元素
  644. */
  645. Element.prototype.translate = function (translateX, translateY) {
  646. if (translateX === void 0) { translateX = 0; }
  647. if (translateY === void 0) { translateY = 0; }
  648. var matrix = this.getMatrix();
  649. var newMatrix = transform(matrix, [['t', translateX, translateY]]);
  650. this.setMatrix(newMatrix);
  651. return this;
  652. };
  653. /**
  654. * 移动元素到目标位置
  655. * @param {number} targetX 目标位置的水平坐标
  656. * @param {number} targetX 目标位置的垂直坐标
  657. * @return {IElement} 元素
  658. */
  659. Element.prototype.move = function (targetX, targetY) {
  660. var x = this.attr('x') || 0;
  661. var y = this.attr('y') || 0;
  662. this.translate(targetX - x, targetY - y);
  663. return this;
  664. };
  665. /**
  666. * 移动元素到目标位置,等价于 move 方法。由于 moveTo 的语义性更强,因此在文档中推荐使用 moveTo 方法
  667. * @param {number} targetX 目标位置的 x 轴坐标
  668. * @param {number} targetY 目标位置的 y 轴坐标
  669. * @return {IElement} 元素
  670. */
  671. Element.prototype.moveTo = function (targetX, targetY) {
  672. return this.move(targetX, targetY);
  673. };
  674. /**
  675. * 缩放元素
  676. * @param {number} ratioX 水平缩放比例
  677. * @param {number} ratioY 垂直缩放比例
  678. * @return {IElement} 元素
  679. */
  680. Element.prototype.scale = function (ratioX, ratioY) {
  681. var matrix = this.getMatrix();
  682. var newMatrix = transform(matrix, [['s', ratioX, ratioY || ratioX]]);
  683. this.setMatrix(newMatrix);
  684. return this;
  685. };
  686. /**
  687. * 以画布左上角 (0, 0) 为中心旋转元素
  688. * @param {number} radian 旋转角度(弧度值)
  689. * @return {IElement} 元素
  690. */
  691. Element.prototype.rotate = function (radian) {
  692. var matrix = this.getMatrix();
  693. var newMatrix = transform(matrix, [['r', radian]]);
  694. this.setMatrix(newMatrix);
  695. return this;
  696. };
  697. /**
  698. * 以起始点为中心旋转元素
  699. * @param {number} radian 旋转角度(弧度值)
  700. * @return {IElement} 元素
  701. */
  702. Element.prototype.rotateAtStart = function (rotate) {
  703. var _a = this.attr(), x = _a.x, y = _a.y;
  704. var matrix = this.getMatrix();
  705. var newMatrix = transform(matrix, [
  706. ['t', -x, -y],
  707. ['r', rotate],
  708. ['t', x, y],
  709. ]);
  710. this.setMatrix(newMatrix);
  711. return this;
  712. };
  713. /**
  714. * 以任意点 (x, y) 为中心旋转元素
  715. * @param {number} radian 旋转角度(弧度值)
  716. * @return {IElement} 元素
  717. */
  718. Element.prototype.rotateAtPoint = function (x, y, rotate) {
  719. var matrix = this.getMatrix();
  720. var newMatrix = transform(matrix, [
  721. ['t', -x, -y],
  722. ['r', rotate],
  723. ['t', x, y],
  724. ]);
  725. this.setMatrix(newMatrix);
  726. return this;
  727. };
  728. return Element;
  729. }(Base));
  730. export default Element;
  731. //# sourceMappingURL=element.js.map