Element.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. import Transformable, { TRANSFORMABLE_PROPS } from './core/Transformable.js';
  2. import Animator, { cloneValue } from './animation/Animator.js';
  3. import BoundingRect from './core/BoundingRect.js';
  4. import Eventful from './core/Eventful.js';
  5. import { calculateTextPosition, parsePercent } from './contain/text.js';
  6. import { guid, isObject, keys, extend, indexOf, logError, mixin, isArrayLike, isTypedArray, isGradientObject, filter, reduce } from './core/util.js';
  7. import { LIGHT_LABEL_COLOR, DARK_LABEL_COLOR } from './config.js';
  8. import { parse, stringify } from './tool/color.js';
  9. import { REDRAW_BIT } from './graphic/constants.js';
  10. export var PRESERVED_NORMAL_STATE = '__zr_normal__';
  11. var PRIMARY_STATES_KEYS = TRANSFORMABLE_PROPS.concat(['ignore']);
  12. var DEFAULT_ANIMATABLE_MAP = reduce(TRANSFORMABLE_PROPS, function (obj, key) {
  13. obj[key] = true;
  14. return obj;
  15. }, { ignore: false });
  16. var tmpTextPosCalcRes = {};
  17. var tmpBoundingRect = new BoundingRect(0, 0, 0, 0);
  18. var Element = (function () {
  19. function Element(props) {
  20. this.id = guid();
  21. this.animators = [];
  22. this.currentStates = [];
  23. this.states = {};
  24. this._init(props);
  25. }
  26. Element.prototype._init = function (props) {
  27. this.attr(props);
  28. };
  29. Element.prototype.drift = function (dx, dy, e) {
  30. switch (this.draggable) {
  31. case 'horizontal':
  32. dy = 0;
  33. break;
  34. case 'vertical':
  35. dx = 0;
  36. break;
  37. }
  38. var m = this.transform;
  39. if (!m) {
  40. m = this.transform = [1, 0, 0, 1, 0, 0];
  41. }
  42. m[4] += dx;
  43. m[5] += dy;
  44. this.decomposeTransform();
  45. this.markRedraw();
  46. };
  47. Element.prototype.beforeUpdate = function () { };
  48. Element.prototype.afterUpdate = function () { };
  49. Element.prototype.update = function () {
  50. this.updateTransform();
  51. if (this.__dirty) {
  52. this.updateInnerText();
  53. }
  54. };
  55. Element.prototype.updateInnerText = function (forceUpdate) {
  56. var textEl = this._textContent;
  57. if (textEl && (!textEl.ignore || forceUpdate)) {
  58. if (!this.textConfig) {
  59. this.textConfig = {};
  60. }
  61. var textConfig = this.textConfig;
  62. var isLocal = textConfig.local;
  63. var innerTransformable = textEl.innerTransformable;
  64. var textAlign = void 0;
  65. var textVerticalAlign = void 0;
  66. var textStyleChanged = false;
  67. innerTransformable.parent = isLocal ? this : null;
  68. var innerOrigin = false;
  69. innerTransformable.copyTransform(textEl);
  70. if (textConfig.position != null) {
  71. var layoutRect = tmpBoundingRect;
  72. if (textConfig.layoutRect) {
  73. layoutRect.copy(textConfig.layoutRect);
  74. }
  75. else {
  76. layoutRect.copy(this.getBoundingRect());
  77. }
  78. if (!isLocal) {
  79. layoutRect.applyTransform(this.transform);
  80. }
  81. if (this.calculateTextPosition) {
  82. this.calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect);
  83. }
  84. else {
  85. calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect);
  86. }
  87. innerTransformable.x = tmpTextPosCalcRes.x;
  88. innerTransformable.y = tmpTextPosCalcRes.y;
  89. textAlign = tmpTextPosCalcRes.align;
  90. textVerticalAlign = tmpTextPosCalcRes.verticalAlign;
  91. var textOrigin = textConfig.origin;
  92. if (textOrigin && textConfig.rotation != null) {
  93. var relOriginX = void 0;
  94. var relOriginY = void 0;
  95. if (textOrigin === 'center') {
  96. relOriginX = layoutRect.width * 0.5;
  97. relOriginY = layoutRect.height * 0.5;
  98. }
  99. else {
  100. relOriginX = parsePercent(textOrigin[0], layoutRect.width);
  101. relOriginY = parsePercent(textOrigin[1], layoutRect.height);
  102. }
  103. innerOrigin = true;
  104. innerTransformable.originX = -innerTransformable.x + relOriginX + (isLocal ? 0 : layoutRect.x);
  105. innerTransformable.originY = -innerTransformable.y + relOriginY + (isLocal ? 0 : layoutRect.y);
  106. }
  107. }
  108. if (textConfig.rotation != null) {
  109. innerTransformable.rotation = textConfig.rotation;
  110. }
  111. var textOffset = textConfig.offset;
  112. if (textOffset) {
  113. innerTransformable.x += textOffset[0];
  114. innerTransformable.y += textOffset[1];
  115. if (!innerOrigin) {
  116. innerTransformable.originX = -textOffset[0];
  117. innerTransformable.originY = -textOffset[1];
  118. }
  119. }
  120. var isInside = textConfig.inside == null
  121. ? (typeof textConfig.position === 'string' && textConfig.position.indexOf('inside') >= 0)
  122. : textConfig.inside;
  123. var innerTextDefaultStyle = this._innerTextDefaultStyle || (this._innerTextDefaultStyle = {});
  124. var textFill = void 0;
  125. var textStroke = void 0;
  126. var autoStroke = void 0;
  127. if (isInside && this.canBeInsideText()) {
  128. textFill = textConfig.insideFill;
  129. textStroke = textConfig.insideStroke;
  130. if (textFill == null || textFill === 'auto') {
  131. textFill = this.getInsideTextFill();
  132. }
  133. if (textStroke == null || textStroke === 'auto') {
  134. textStroke = this.getInsideTextStroke(textFill);
  135. autoStroke = true;
  136. }
  137. }
  138. else {
  139. textFill = textConfig.outsideFill;
  140. textStroke = textConfig.outsideStroke;
  141. if (textFill == null || textFill === 'auto') {
  142. textFill = this.getOutsideFill();
  143. }
  144. if (textStroke == null || textStroke === 'auto') {
  145. textStroke = this.getOutsideStroke(textFill);
  146. autoStroke = true;
  147. }
  148. }
  149. textFill = textFill || '#000';
  150. if (textFill !== innerTextDefaultStyle.fill
  151. || textStroke !== innerTextDefaultStyle.stroke
  152. || autoStroke !== innerTextDefaultStyle.autoStroke
  153. || textAlign !== innerTextDefaultStyle.align
  154. || textVerticalAlign !== innerTextDefaultStyle.verticalAlign) {
  155. textStyleChanged = true;
  156. innerTextDefaultStyle.fill = textFill;
  157. innerTextDefaultStyle.stroke = textStroke;
  158. innerTextDefaultStyle.autoStroke = autoStroke;
  159. innerTextDefaultStyle.align = textAlign;
  160. innerTextDefaultStyle.verticalAlign = textVerticalAlign;
  161. textEl.setDefaultTextStyle(innerTextDefaultStyle);
  162. }
  163. textEl.__dirty |= REDRAW_BIT;
  164. if (textStyleChanged) {
  165. textEl.dirtyStyle(true);
  166. }
  167. }
  168. };
  169. Element.prototype.canBeInsideText = function () {
  170. return true;
  171. };
  172. Element.prototype.getInsideTextFill = function () {
  173. return '#fff';
  174. };
  175. Element.prototype.getInsideTextStroke = function (textFill) {
  176. return '#000';
  177. };
  178. Element.prototype.getOutsideFill = function () {
  179. return this.__zr && this.__zr.isDarkMode() ? LIGHT_LABEL_COLOR : DARK_LABEL_COLOR;
  180. };
  181. Element.prototype.getOutsideStroke = function (textFill) {
  182. var backgroundColor = this.__zr && this.__zr.getBackgroundColor();
  183. var colorArr = typeof backgroundColor === 'string' && parse(backgroundColor);
  184. if (!colorArr) {
  185. colorArr = [255, 255, 255, 1];
  186. }
  187. var alpha = colorArr[3];
  188. var isDark = this.__zr.isDarkMode();
  189. for (var i = 0; i < 3; i++) {
  190. colorArr[i] = colorArr[i] * alpha + (isDark ? 0 : 255) * (1 - alpha);
  191. }
  192. colorArr[3] = 1;
  193. return stringify(colorArr, 'rgba');
  194. };
  195. Element.prototype.traverse = function (cb, context) { };
  196. Element.prototype.attrKV = function (key, value) {
  197. if (key === 'textConfig') {
  198. this.setTextConfig(value);
  199. }
  200. else if (key === 'textContent') {
  201. this.setTextContent(value);
  202. }
  203. else if (key === 'clipPath') {
  204. this.setClipPath(value);
  205. }
  206. else if (key === 'extra') {
  207. this.extra = this.extra || {};
  208. extend(this.extra, value);
  209. }
  210. else {
  211. this[key] = value;
  212. }
  213. };
  214. Element.prototype.hide = function () {
  215. this.ignore = true;
  216. this.markRedraw();
  217. };
  218. Element.prototype.show = function () {
  219. this.ignore = false;
  220. this.markRedraw();
  221. };
  222. Element.prototype.attr = function (keyOrObj, value) {
  223. if (typeof keyOrObj === 'string') {
  224. this.attrKV(keyOrObj, value);
  225. }
  226. else if (isObject(keyOrObj)) {
  227. var obj = keyOrObj;
  228. var keysArr = keys(obj);
  229. for (var i = 0; i < keysArr.length; i++) {
  230. var key = keysArr[i];
  231. this.attrKV(key, keyOrObj[key]);
  232. }
  233. }
  234. this.markRedraw();
  235. return this;
  236. };
  237. Element.prototype.saveCurrentToNormalState = function (toState) {
  238. this._innerSaveToNormal(toState);
  239. var normalState = this._normalState;
  240. for (var i = 0; i < this.animators.length; i++) {
  241. var animator = this.animators[i];
  242. var fromStateTransition = animator.__fromStateTransition;
  243. if (animator.getLoop() || fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) {
  244. continue;
  245. }
  246. var targetName = animator.targetName;
  247. var target = targetName
  248. ? normalState[targetName] : normalState;
  249. animator.saveTo(target);
  250. }
  251. };
  252. Element.prototype._innerSaveToNormal = function (toState) {
  253. var normalState = this._normalState;
  254. if (!normalState) {
  255. normalState = this._normalState = {};
  256. }
  257. if (toState.textConfig && !normalState.textConfig) {
  258. normalState.textConfig = this.textConfig;
  259. }
  260. this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS);
  261. };
  262. Element.prototype._savePrimaryToNormal = function (toState, normalState, primaryKeys) {
  263. for (var i = 0; i < primaryKeys.length; i++) {
  264. var key = primaryKeys[i];
  265. if (toState[key] != null && !(key in normalState)) {
  266. normalState[key] = this[key];
  267. }
  268. }
  269. };
  270. Element.prototype.hasState = function () {
  271. return this.currentStates.length > 0;
  272. };
  273. Element.prototype.getState = function (name) {
  274. return this.states[name];
  275. };
  276. Element.prototype.ensureState = function (name) {
  277. var states = this.states;
  278. if (!states[name]) {
  279. states[name] = {};
  280. }
  281. return states[name];
  282. };
  283. Element.prototype.clearStates = function (noAnimation) {
  284. this.useState(PRESERVED_NORMAL_STATE, false, noAnimation);
  285. };
  286. Element.prototype.useState = function (stateName, keepCurrentStates, noAnimation, forceUseHoverLayer) {
  287. var toNormalState = stateName === PRESERVED_NORMAL_STATE;
  288. var hasStates = this.hasState();
  289. if (!hasStates && toNormalState) {
  290. return;
  291. }
  292. var currentStates = this.currentStates;
  293. var animationCfg = this.stateTransition;
  294. if (indexOf(currentStates, stateName) >= 0 && (keepCurrentStates || currentStates.length === 1)) {
  295. return;
  296. }
  297. var state;
  298. if (this.stateProxy && !toNormalState) {
  299. state = this.stateProxy(stateName);
  300. }
  301. if (!state) {
  302. state = (this.states && this.states[stateName]);
  303. }
  304. if (!state && !toNormalState) {
  305. logError("State " + stateName + " not exists.");
  306. return;
  307. }
  308. if (!toNormalState) {
  309. this.saveCurrentToNormalState(state);
  310. }
  311. var useHoverLayer = !!((state && state.hoverLayer) || forceUseHoverLayer);
  312. if (useHoverLayer) {
  313. this._toggleHoverLayerFlag(true);
  314. }
  315. this._applyStateObj(stateName, state, this._normalState, keepCurrentStates, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg);
  316. var textContent = this._textContent;
  317. var textGuide = this._textGuide;
  318. if (textContent) {
  319. textContent.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer);
  320. }
  321. if (textGuide) {
  322. textGuide.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer);
  323. }
  324. if (toNormalState) {
  325. this.currentStates = [];
  326. this._normalState = {};
  327. }
  328. else {
  329. if (!keepCurrentStates) {
  330. this.currentStates = [stateName];
  331. }
  332. else {
  333. this.currentStates.push(stateName);
  334. }
  335. }
  336. this._updateAnimationTargets();
  337. this.markRedraw();
  338. if (!useHoverLayer && this.__inHover) {
  339. this._toggleHoverLayerFlag(false);
  340. this.__dirty &= ~REDRAW_BIT;
  341. }
  342. return state;
  343. };
  344. Element.prototype.useStates = function (states, noAnimation, forceUseHoverLayer) {
  345. if (!states.length) {
  346. this.clearStates();
  347. }
  348. else {
  349. var stateObjects = [];
  350. var currentStates = this.currentStates;
  351. var len = states.length;
  352. var notChange = len === currentStates.length;
  353. if (notChange) {
  354. for (var i = 0; i < len; i++) {
  355. if (states[i] !== currentStates[i]) {
  356. notChange = false;
  357. break;
  358. }
  359. }
  360. }
  361. if (notChange) {
  362. return;
  363. }
  364. for (var i = 0; i < len; i++) {
  365. var stateName = states[i];
  366. var stateObj = void 0;
  367. if (this.stateProxy) {
  368. stateObj = this.stateProxy(stateName, states);
  369. }
  370. if (!stateObj) {
  371. stateObj = this.states[stateName];
  372. }
  373. if (stateObj) {
  374. stateObjects.push(stateObj);
  375. }
  376. }
  377. var lastStateObj = stateObjects[len - 1];
  378. var useHoverLayer = !!((lastStateObj && lastStateObj.hoverLayer) || forceUseHoverLayer);
  379. if (useHoverLayer) {
  380. this._toggleHoverLayerFlag(true);
  381. }
  382. var mergedState = this._mergeStates(stateObjects);
  383. var animationCfg = this.stateTransition;
  384. this.saveCurrentToNormalState(mergedState);
  385. this._applyStateObj(states.join(','), mergedState, this._normalState, false, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg);
  386. var textContent = this._textContent;
  387. var textGuide = this._textGuide;
  388. if (textContent) {
  389. textContent.useStates(states, noAnimation, useHoverLayer);
  390. }
  391. if (textGuide) {
  392. textGuide.useStates(states, noAnimation, useHoverLayer);
  393. }
  394. this._updateAnimationTargets();
  395. this.currentStates = states.slice();
  396. this.markRedraw();
  397. if (!useHoverLayer && this.__inHover) {
  398. this._toggleHoverLayerFlag(false);
  399. this.__dirty &= ~REDRAW_BIT;
  400. }
  401. }
  402. };
  403. Element.prototype._updateAnimationTargets = function () {
  404. for (var i = 0; i < this.animators.length; i++) {
  405. var animator = this.animators[i];
  406. if (animator.targetName) {
  407. animator.changeTarget(this[animator.targetName]);
  408. }
  409. }
  410. };
  411. Element.prototype.removeState = function (state) {
  412. var idx = indexOf(this.currentStates, state);
  413. if (idx >= 0) {
  414. var currentStates = this.currentStates.slice();
  415. currentStates.splice(idx, 1);
  416. this.useStates(currentStates);
  417. }
  418. };
  419. Element.prototype.replaceState = function (oldState, newState, forceAdd) {
  420. var currentStates = this.currentStates.slice();
  421. var idx = indexOf(currentStates, oldState);
  422. var newStateExists = indexOf(currentStates, newState) >= 0;
  423. if (idx >= 0) {
  424. if (!newStateExists) {
  425. currentStates[idx] = newState;
  426. }
  427. else {
  428. currentStates.splice(idx, 1);
  429. }
  430. }
  431. else if (forceAdd && !newStateExists) {
  432. currentStates.push(newState);
  433. }
  434. this.useStates(currentStates);
  435. };
  436. Element.prototype.toggleState = function (state, enable) {
  437. if (enable) {
  438. this.useState(state, true);
  439. }
  440. else {
  441. this.removeState(state);
  442. }
  443. };
  444. Element.prototype._mergeStates = function (states) {
  445. var mergedState = {};
  446. var mergedTextConfig;
  447. for (var i = 0; i < states.length; i++) {
  448. var state = states[i];
  449. extend(mergedState, state);
  450. if (state.textConfig) {
  451. mergedTextConfig = mergedTextConfig || {};
  452. extend(mergedTextConfig, state.textConfig);
  453. }
  454. }
  455. if (mergedTextConfig) {
  456. mergedState.textConfig = mergedTextConfig;
  457. }
  458. return mergedState;
  459. };
  460. Element.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
  461. var needsRestoreToNormal = !(state && keepCurrentStates);
  462. if (state && state.textConfig) {
  463. this.textConfig = extend({}, keepCurrentStates ? this.textConfig : normalState.textConfig);
  464. extend(this.textConfig, state.textConfig);
  465. }
  466. else if (needsRestoreToNormal) {
  467. if (normalState.textConfig) {
  468. this.textConfig = normalState.textConfig;
  469. }
  470. }
  471. var transitionTarget = {};
  472. var hasTransition = false;
  473. for (var i = 0; i < PRIMARY_STATES_KEYS.length; i++) {
  474. var key = PRIMARY_STATES_KEYS[i];
  475. var propNeedsTransition = transition && DEFAULT_ANIMATABLE_MAP[key];
  476. if (state && state[key] != null) {
  477. if (propNeedsTransition) {
  478. hasTransition = true;
  479. transitionTarget[key] = state[key];
  480. }
  481. else {
  482. this[key] = state[key];
  483. }
  484. }
  485. else if (needsRestoreToNormal) {
  486. if (normalState[key] != null) {
  487. if (propNeedsTransition) {
  488. hasTransition = true;
  489. transitionTarget[key] = normalState[key];
  490. }
  491. else {
  492. this[key] = normalState[key];
  493. }
  494. }
  495. }
  496. }
  497. if (!transition) {
  498. for (var i = 0; i < this.animators.length; i++) {
  499. var animator = this.animators[i];
  500. var targetName = animator.targetName;
  501. if (!animator.getLoop()) {
  502. animator.__changeFinalValue(targetName
  503. ? (state || normalState)[targetName]
  504. : (state || normalState));
  505. }
  506. }
  507. }
  508. if (hasTransition) {
  509. this._transitionState(stateName, transitionTarget, animationCfg);
  510. }
  511. };
  512. Element.prototype._attachComponent = function (componentEl) {
  513. if (componentEl.__zr && !componentEl.__hostTarget) {
  514. if (process.env.NODE_ENV !== 'production') {
  515. throw new Error('Text element has been added to zrender.');
  516. }
  517. return;
  518. }
  519. if (componentEl === this) {
  520. if (process.env.NODE_ENV !== 'production') {
  521. throw new Error('Recursive component attachment.');
  522. }
  523. return;
  524. }
  525. var zr = this.__zr;
  526. if (zr) {
  527. componentEl.addSelfToZr(zr);
  528. }
  529. componentEl.__zr = zr;
  530. componentEl.__hostTarget = this;
  531. };
  532. Element.prototype._detachComponent = function (componentEl) {
  533. if (componentEl.__zr) {
  534. componentEl.removeSelfFromZr(componentEl.__zr);
  535. }
  536. componentEl.__zr = null;
  537. componentEl.__hostTarget = null;
  538. };
  539. Element.prototype.getClipPath = function () {
  540. return this._clipPath;
  541. };
  542. Element.prototype.setClipPath = function (clipPath) {
  543. if (this._clipPath && this._clipPath !== clipPath) {
  544. this.removeClipPath();
  545. }
  546. this._attachComponent(clipPath);
  547. this._clipPath = clipPath;
  548. this.markRedraw();
  549. };
  550. Element.prototype.removeClipPath = function () {
  551. var clipPath = this._clipPath;
  552. if (clipPath) {
  553. this._detachComponent(clipPath);
  554. this._clipPath = null;
  555. this.markRedraw();
  556. }
  557. };
  558. Element.prototype.getTextContent = function () {
  559. return this._textContent;
  560. };
  561. Element.prototype.setTextContent = function (textEl) {
  562. var previousTextContent = this._textContent;
  563. if (previousTextContent === textEl) {
  564. return;
  565. }
  566. if (previousTextContent && previousTextContent !== textEl) {
  567. this.removeTextContent();
  568. }
  569. if (process.env.NODE_ENV !== 'production') {
  570. if (textEl.__zr && !textEl.__hostTarget) {
  571. throw new Error('Text element has been added to zrender.');
  572. }
  573. }
  574. textEl.innerTransformable = new Transformable();
  575. this._attachComponent(textEl);
  576. this._textContent = textEl;
  577. this.markRedraw();
  578. };
  579. Element.prototype.setTextConfig = function (cfg) {
  580. if (!this.textConfig) {
  581. this.textConfig = {};
  582. }
  583. extend(this.textConfig, cfg);
  584. this.markRedraw();
  585. };
  586. Element.prototype.removeTextConfig = function () {
  587. this.textConfig = null;
  588. this.markRedraw();
  589. };
  590. Element.prototype.removeTextContent = function () {
  591. var textEl = this._textContent;
  592. if (textEl) {
  593. textEl.innerTransformable = null;
  594. this._detachComponent(textEl);
  595. this._textContent = null;
  596. this._innerTextDefaultStyle = null;
  597. this.markRedraw();
  598. }
  599. };
  600. Element.prototype.getTextGuideLine = function () {
  601. return this._textGuide;
  602. };
  603. Element.prototype.setTextGuideLine = function (guideLine) {
  604. if (this._textGuide && this._textGuide !== guideLine) {
  605. this.removeTextGuideLine();
  606. }
  607. this._attachComponent(guideLine);
  608. this._textGuide = guideLine;
  609. this.markRedraw();
  610. };
  611. Element.prototype.removeTextGuideLine = function () {
  612. var textGuide = this._textGuide;
  613. if (textGuide) {
  614. this._detachComponent(textGuide);
  615. this._textGuide = null;
  616. this.markRedraw();
  617. }
  618. };
  619. Element.prototype.markRedraw = function () {
  620. this.__dirty |= REDRAW_BIT;
  621. var zr = this.__zr;
  622. if (zr) {
  623. if (this.__inHover) {
  624. zr.refreshHover();
  625. }
  626. else {
  627. zr.refresh();
  628. }
  629. }
  630. if (this.__hostTarget) {
  631. this.__hostTarget.markRedraw();
  632. }
  633. };
  634. Element.prototype.dirty = function () {
  635. this.markRedraw();
  636. };
  637. Element.prototype._toggleHoverLayerFlag = function (inHover) {
  638. this.__inHover = inHover;
  639. var textContent = this._textContent;
  640. var textGuide = this._textGuide;
  641. if (textContent) {
  642. textContent.__inHover = inHover;
  643. }
  644. if (textGuide) {
  645. textGuide.__inHover = inHover;
  646. }
  647. };
  648. Element.prototype.addSelfToZr = function (zr) {
  649. if (this.__zr === zr) {
  650. return;
  651. }
  652. this.__zr = zr;
  653. var animators = this.animators;
  654. if (animators) {
  655. for (var i = 0; i < animators.length; i++) {
  656. zr.animation.addAnimator(animators[i]);
  657. }
  658. }
  659. if (this._clipPath) {
  660. this._clipPath.addSelfToZr(zr);
  661. }
  662. if (this._textContent) {
  663. this._textContent.addSelfToZr(zr);
  664. }
  665. if (this._textGuide) {
  666. this._textGuide.addSelfToZr(zr);
  667. }
  668. };
  669. Element.prototype.removeSelfFromZr = function (zr) {
  670. if (!this.__zr) {
  671. return;
  672. }
  673. this.__zr = null;
  674. var animators = this.animators;
  675. if (animators) {
  676. for (var i = 0; i < animators.length; i++) {
  677. zr.animation.removeAnimator(animators[i]);
  678. }
  679. }
  680. if (this._clipPath) {
  681. this._clipPath.removeSelfFromZr(zr);
  682. }
  683. if (this._textContent) {
  684. this._textContent.removeSelfFromZr(zr);
  685. }
  686. if (this._textGuide) {
  687. this._textGuide.removeSelfFromZr(zr);
  688. }
  689. };
  690. Element.prototype.animate = function (key, loop, allowDiscreteAnimation) {
  691. var target = key ? this[key] : this;
  692. if (process.env.NODE_ENV !== 'production') {
  693. if (!target) {
  694. logError('Property "'
  695. + key
  696. + '" is not existed in element '
  697. + this.id);
  698. return;
  699. }
  700. }
  701. var animator = new Animator(target, loop, allowDiscreteAnimation);
  702. key && (animator.targetName = key);
  703. this.addAnimator(animator, key);
  704. return animator;
  705. };
  706. Element.prototype.addAnimator = function (animator, key) {
  707. var zr = this.__zr;
  708. var el = this;
  709. animator.during(function () {
  710. el.updateDuringAnimation(key);
  711. }).done(function () {
  712. var animators = el.animators;
  713. var idx = indexOf(animators, animator);
  714. if (idx >= 0) {
  715. animators.splice(idx, 1);
  716. }
  717. });
  718. this.animators.push(animator);
  719. if (zr) {
  720. zr.animation.addAnimator(animator);
  721. }
  722. zr && zr.wakeUp();
  723. };
  724. Element.prototype.updateDuringAnimation = function (key) {
  725. this.markRedraw();
  726. };
  727. Element.prototype.stopAnimation = function (scope, forwardToLast) {
  728. var animators = this.animators;
  729. var len = animators.length;
  730. var leftAnimators = [];
  731. for (var i = 0; i < len; i++) {
  732. var animator = animators[i];
  733. if (!scope || scope === animator.scope) {
  734. animator.stop(forwardToLast);
  735. }
  736. else {
  737. leftAnimators.push(animator);
  738. }
  739. }
  740. this.animators = leftAnimators;
  741. return this;
  742. };
  743. Element.prototype.animateTo = function (target, cfg, animationProps) {
  744. animateTo(this, target, cfg, animationProps);
  745. };
  746. Element.prototype.animateFrom = function (target, cfg, animationProps) {
  747. animateTo(this, target, cfg, animationProps, true);
  748. };
  749. Element.prototype._transitionState = function (stateName, target, cfg, animationProps) {
  750. var animators = animateTo(this, target, cfg, animationProps);
  751. for (var i = 0; i < animators.length; i++) {
  752. animators[i].__fromStateTransition = stateName;
  753. }
  754. };
  755. Element.prototype.getBoundingRect = function () {
  756. return null;
  757. };
  758. Element.prototype.getPaintRect = function () {
  759. return null;
  760. };
  761. Element.initDefaultProps = (function () {
  762. var elProto = Element.prototype;
  763. elProto.type = 'element';
  764. elProto.name = '';
  765. elProto.ignore =
  766. elProto.silent =
  767. elProto.isGroup =
  768. elProto.draggable =
  769. elProto.dragging =
  770. elProto.ignoreClip =
  771. elProto.__inHover = false;
  772. elProto.__dirty = REDRAW_BIT;
  773. var logs = {};
  774. function logDeprecatedError(key, xKey, yKey) {
  775. if (!logs[key + xKey + yKey]) {
  776. console.warn("DEPRECATED: '" + key + "' has been deprecated. use '" + xKey + "', '" + yKey + "' instead");
  777. logs[key + xKey + yKey] = true;
  778. }
  779. }
  780. function createLegacyProperty(key, privateKey, xKey, yKey) {
  781. Object.defineProperty(elProto, key, {
  782. get: function () {
  783. if (process.env.NODE_ENV !== 'production') {
  784. logDeprecatedError(key, xKey, yKey);
  785. }
  786. if (!this[privateKey]) {
  787. var pos = this[privateKey] = [];
  788. enhanceArray(this, pos);
  789. }
  790. return this[privateKey];
  791. },
  792. set: function (pos) {
  793. if (process.env.NODE_ENV !== 'production') {
  794. logDeprecatedError(key, xKey, yKey);
  795. }
  796. this[xKey] = pos[0];
  797. this[yKey] = pos[1];
  798. this[privateKey] = pos;
  799. enhanceArray(this, pos);
  800. }
  801. });
  802. function enhanceArray(self, pos) {
  803. Object.defineProperty(pos, 0, {
  804. get: function () {
  805. return self[xKey];
  806. },
  807. set: function (val) {
  808. self[xKey] = val;
  809. }
  810. });
  811. Object.defineProperty(pos, 1, {
  812. get: function () {
  813. return self[yKey];
  814. },
  815. set: function (val) {
  816. self[yKey] = val;
  817. }
  818. });
  819. }
  820. }
  821. if (Object.defineProperty) {
  822. createLegacyProperty('position', '_legacyPos', 'x', 'y');
  823. createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY');
  824. createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY');
  825. }
  826. })();
  827. return Element;
  828. }());
  829. mixin(Element, Eventful);
  830. mixin(Element, Transformable);
  831. function animateTo(animatable, target, cfg, animationProps, reverse) {
  832. cfg = cfg || {};
  833. var animators = [];
  834. animateToShallow(animatable, '', animatable, target, cfg, animationProps, animators, reverse);
  835. var finishCount = animators.length;
  836. var doneHappened = false;
  837. var cfgDone = cfg.done;
  838. var cfgAborted = cfg.aborted;
  839. var doneCb = function () {
  840. doneHappened = true;
  841. finishCount--;
  842. if (finishCount <= 0) {
  843. doneHappened
  844. ? (cfgDone && cfgDone())
  845. : (cfgAborted && cfgAborted());
  846. }
  847. };
  848. var abortedCb = function () {
  849. finishCount--;
  850. if (finishCount <= 0) {
  851. doneHappened
  852. ? (cfgDone && cfgDone())
  853. : (cfgAborted && cfgAborted());
  854. }
  855. };
  856. if (!finishCount) {
  857. cfgDone && cfgDone();
  858. }
  859. if (animators.length > 0 && cfg.during) {
  860. animators[0].during(function (target, percent) {
  861. cfg.during(percent);
  862. });
  863. }
  864. for (var i = 0; i < animators.length; i++) {
  865. var animator = animators[i];
  866. if (doneCb) {
  867. animator.done(doneCb);
  868. }
  869. if (abortedCb) {
  870. animator.aborted(abortedCb);
  871. }
  872. if (cfg.force) {
  873. animator.duration(cfg.duration);
  874. }
  875. animator.start(cfg.easing);
  876. }
  877. return animators;
  878. }
  879. function copyArrShallow(source, target, len) {
  880. for (var i = 0; i < len; i++) {
  881. source[i] = target[i];
  882. }
  883. }
  884. function is2DArray(value) {
  885. return isArrayLike(value[0]);
  886. }
  887. function copyValue(target, source, key) {
  888. if (isArrayLike(source[key])) {
  889. if (!isArrayLike(target[key])) {
  890. target[key] = [];
  891. }
  892. if (isTypedArray(source[key])) {
  893. var len = source[key].length;
  894. if (target[key].length !== len) {
  895. target[key] = new (source[key].constructor)(len);
  896. copyArrShallow(target[key], source[key], len);
  897. }
  898. }
  899. else {
  900. var sourceArr = source[key];
  901. var targetArr = target[key];
  902. var len0 = sourceArr.length;
  903. if (is2DArray(sourceArr)) {
  904. var len1 = sourceArr[0].length;
  905. for (var i = 0; i < len0; i++) {
  906. if (!targetArr[i]) {
  907. targetArr[i] = Array.prototype.slice.call(sourceArr[i]);
  908. }
  909. else {
  910. copyArrShallow(targetArr[i], sourceArr[i], len1);
  911. }
  912. }
  913. }
  914. else {
  915. copyArrShallow(targetArr, sourceArr, len0);
  916. }
  917. targetArr.length = sourceArr.length;
  918. }
  919. }
  920. else {
  921. target[key] = source[key];
  922. }
  923. }
  924. function isValueSame(val1, val2) {
  925. return val1 === val2
  926. || isArrayLike(val1) && isArrayLike(val2) && is1DArraySame(val1, val2);
  927. }
  928. function is1DArraySame(arr0, arr1) {
  929. var len = arr0.length;
  930. if (len !== arr1.length) {
  931. return false;
  932. }
  933. for (var i = 0; i < len; i++) {
  934. if (arr0[i] !== arr1[i]) {
  935. return false;
  936. }
  937. }
  938. return true;
  939. }
  940. function animateToShallow(animatable, topKey, animateObj, target, cfg, animationProps, animators, reverse) {
  941. var targetKeys = keys(target);
  942. var duration = cfg.duration;
  943. var delay = cfg.delay;
  944. var additive = cfg.additive;
  945. var setToFinal = cfg.setToFinal;
  946. var animateAll = !isObject(animationProps);
  947. var existsAnimators = animatable.animators;
  948. var animationKeys = [];
  949. for (var k = 0; k < targetKeys.length; k++) {
  950. var innerKey = targetKeys[k];
  951. var targetVal = target[innerKey];
  952. if (targetVal != null && animateObj[innerKey] != null
  953. && (animateAll || animationProps[innerKey])) {
  954. if (isObject(targetVal)
  955. && !isArrayLike(targetVal)
  956. && !isGradientObject(targetVal)) {
  957. if (topKey) {
  958. if (!reverse) {
  959. animateObj[innerKey] = targetVal;
  960. animatable.updateDuringAnimation(topKey);
  961. }
  962. continue;
  963. }
  964. animateToShallow(animatable, innerKey, animateObj[innerKey], targetVal, cfg, animationProps && animationProps[innerKey], animators, reverse);
  965. }
  966. else {
  967. animationKeys.push(innerKey);
  968. }
  969. }
  970. else if (!reverse) {
  971. animateObj[innerKey] = targetVal;
  972. animatable.updateDuringAnimation(topKey);
  973. animationKeys.push(innerKey);
  974. }
  975. }
  976. var keyLen = animationKeys.length;
  977. if (!additive && keyLen) {
  978. for (var i = 0; i < existsAnimators.length; i++) {
  979. var animator = existsAnimators[i];
  980. if (animator.targetName === topKey) {
  981. var allAborted = animator.stopTracks(animationKeys);
  982. if (allAborted) {
  983. var idx = indexOf(existsAnimators, animator);
  984. existsAnimators.splice(idx, 1);
  985. }
  986. }
  987. }
  988. }
  989. if (!cfg.force) {
  990. animationKeys = filter(animationKeys, function (key) { return !isValueSame(target[key], animateObj[key]); });
  991. keyLen = animationKeys.length;
  992. }
  993. if (keyLen > 0
  994. || (cfg.force && !animators.length)) {
  995. var revertedSource = void 0;
  996. var reversedTarget = void 0;
  997. var sourceClone = void 0;
  998. if (reverse) {
  999. reversedTarget = {};
  1000. if (setToFinal) {
  1001. revertedSource = {};
  1002. }
  1003. for (var i = 0; i < keyLen; i++) {
  1004. var innerKey = animationKeys[i];
  1005. reversedTarget[innerKey] = animateObj[innerKey];
  1006. if (setToFinal) {
  1007. revertedSource[innerKey] = target[innerKey];
  1008. }
  1009. else {
  1010. animateObj[innerKey] = target[innerKey];
  1011. }
  1012. }
  1013. }
  1014. else if (setToFinal) {
  1015. sourceClone = {};
  1016. for (var i = 0; i < keyLen; i++) {
  1017. var innerKey = animationKeys[i];
  1018. sourceClone[innerKey] = cloneValue(animateObj[innerKey]);
  1019. copyValue(animateObj, target, innerKey);
  1020. }
  1021. }
  1022. var animator = new Animator(animateObj, false, false, additive ? filter(existsAnimators, function (animator) { return animator.targetName === topKey; }) : null);
  1023. animator.targetName = topKey;
  1024. if (cfg.scope) {
  1025. animator.scope = cfg.scope;
  1026. }
  1027. if (setToFinal && revertedSource) {
  1028. animator.whenWithKeys(0, revertedSource, animationKeys);
  1029. }
  1030. if (sourceClone) {
  1031. animator.whenWithKeys(0, sourceClone, animationKeys);
  1032. }
  1033. animator.whenWithKeys(duration == null ? 500 : duration, reverse ? reversedTarget : target, animationKeys).delay(delay || 0);
  1034. animatable.addAnimator(animator, topKey);
  1035. animators.push(animator);
  1036. }
  1037. }
  1038. export default Element;