Element.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  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.isSilent = function () {
  404. var isSilent = this.silent;
  405. var ancestor = this.parent;
  406. while (!isSilent && ancestor) {
  407. if (ancestor.silent) {
  408. isSilent = true;
  409. break;
  410. }
  411. ancestor = ancestor.parent;
  412. }
  413. return isSilent;
  414. };
  415. Element.prototype._updateAnimationTargets = function () {
  416. for (var i = 0; i < this.animators.length; i++) {
  417. var animator = this.animators[i];
  418. if (animator.targetName) {
  419. animator.changeTarget(this[animator.targetName]);
  420. }
  421. }
  422. };
  423. Element.prototype.removeState = function (state) {
  424. var idx = indexOf(this.currentStates, state);
  425. if (idx >= 0) {
  426. var currentStates = this.currentStates.slice();
  427. currentStates.splice(idx, 1);
  428. this.useStates(currentStates);
  429. }
  430. };
  431. Element.prototype.replaceState = function (oldState, newState, forceAdd) {
  432. var currentStates = this.currentStates.slice();
  433. var idx = indexOf(currentStates, oldState);
  434. var newStateExists = indexOf(currentStates, newState) >= 0;
  435. if (idx >= 0) {
  436. if (!newStateExists) {
  437. currentStates[idx] = newState;
  438. }
  439. else {
  440. currentStates.splice(idx, 1);
  441. }
  442. }
  443. else if (forceAdd && !newStateExists) {
  444. currentStates.push(newState);
  445. }
  446. this.useStates(currentStates);
  447. };
  448. Element.prototype.toggleState = function (state, enable) {
  449. if (enable) {
  450. this.useState(state, true);
  451. }
  452. else {
  453. this.removeState(state);
  454. }
  455. };
  456. Element.prototype._mergeStates = function (states) {
  457. var mergedState = {};
  458. var mergedTextConfig;
  459. for (var i = 0; i < states.length; i++) {
  460. var state = states[i];
  461. extend(mergedState, state);
  462. if (state.textConfig) {
  463. mergedTextConfig = mergedTextConfig || {};
  464. extend(mergedTextConfig, state.textConfig);
  465. }
  466. }
  467. if (mergedTextConfig) {
  468. mergedState.textConfig = mergedTextConfig;
  469. }
  470. return mergedState;
  471. };
  472. Element.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
  473. var needsRestoreToNormal = !(state && keepCurrentStates);
  474. if (state && state.textConfig) {
  475. this.textConfig = extend({}, keepCurrentStates ? this.textConfig : normalState.textConfig);
  476. extend(this.textConfig, state.textConfig);
  477. }
  478. else if (needsRestoreToNormal) {
  479. if (normalState.textConfig) {
  480. this.textConfig = normalState.textConfig;
  481. }
  482. }
  483. var transitionTarget = {};
  484. var hasTransition = false;
  485. for (var i = 0; i < PRIMARY_STATES_KEYS.length; i++) {
  486. var key = PRIMARY_STATES_KEYS[i];
  487. var propNeedsTransition = transition && DEFAULT_ANIMATABLE_MAP[key];
  488. if (state && state[key] != null) {
  489. if (propNeedsTransition) {
  490. hasTransition = true;
  491. transitionTarget[key] = state[key];
  492. }
  493. else {
  494. this[key] = state[key];
  495. }
  496. }
  497. else if (needsRestoreToNormal) {
  498. if (normalState[key] != null) {
  499. if (propNeedsTransition) {
  500. hasTransition = true;
  501. transitionTarget[key] = normalState[key];
  502. }
  503. else {
  504. this[key] = normalState[key];
  505. }
  506. }
  507. }
  508. }
  509. if (!transition) {
  510. for (var i = 0; i < this.animators.length; i++) {
  511. var animator = this.animators[i];
  512. var targetName = animator.targetName;
  513. if (!animator.getLoop()) {
  514. animator.__changeFinalValue(targetName
  515. ? (state || normalState)[targetName]
  516. : (state || normalState));
  517. }
  518. }
  519. }
  520. if (hasTransition) {
  521. this._transitionState(stateName, transitionTarget, animationCfg);
  522. }
  523. };
  524. Element.prototype._attachComponent = function (componentEl) {
  525. if (componentEl.__zr && !componentEl.__hostTarget) {
  526. if (process.env.NODE_ENV !== 'production') {
  527. throw new Error('Text element has been added to zrender.');
  528. }
  529. return;
  530. }
  531. if (componentEl === this) {
  532. if (process.env.NODE_ENV !== 'production') {
  533. throw new Error('Recursive component attachment.');
  534. }
  535. return;
  536. }
  537. var zr = this.__zr;
  538. if (zr) {
  539. componentEl.addSelfToZr(zr);
  540. }
  541. componentEl.__zr = zr;
  542. componentEl.__hostTarget = this;
  543. };
  544. Element.prototype._detachComponent = function (componentEl) {
  545. if (componentEl.__zr) {
  546. componentEl.removeSelfFromZr(componentEl.__zr);
  547. }
  548. componentEl.__zr = null;
  549. componentEl.__hostTarget = null;
  550. };
  551. Element.prototype.getClipPath = function () {
  552. return this._clipPath;
  553. };
  554. Element.prototype.setClipPath = function (clipPath) {
  555. if (this._clipPath && this._clipPath !== clipPath) {
  556. this.removeClipPath();
  557. }
  558. this._attachComponent(clipPath);
  559. this._clipPath = clipPath;
  560. this.markRedraw();
  561. };
  562. Element.prototype.removeClipPath = function () {
  563. var clipPath = this._clipPath;
  564. if (clipPath) {
  565. this._detachComponent(clipPath);
  566. this._clipPath = null;
  567. this.markRedraw();
  568. }
  569. };
  570. Element.prototype.getTextContent = function () {
  571. return this._textContent;
  572. };
  573. Element.prototype.setTextContent = function (textEl) {
  574. var previousTextContent = this._textContent;
  575. if (previousTextContent === textEl) {
  576. return;
  577. }
  578. if (previousTextContent && previousTextContent !== textEl) {
  579. this.removeTextContent();
  580. }
  581. if (process.env.NODE_ENV !== 'production') {
  582. if (textEl.__zr && !textEl.__hostTarget) {
  583. throw new Error('Text element has been added to zrender.');
  584. }
  585. }
  586. textEl.innerTransformable = new Transformable();
  587. this._attachComponent(textEl);
  588. this._textContent = textEl;
  589. this.markRedraw();
  590. };
  591. Element.prototype.setTextConfig = function (cfg) {
  592. if (!this.textConfig) {
  593. this.textConfig = {};
  594. }
  595. extend(this.textConfig, cfg);
  596. this.markRedraw();
  597. };
  598. Element.prototype.removeTextConfig = function () {
  599. this.textConfig = null;
  600. this.markRedraw();
  601. };
  602. Element.prototype.removeTextContent = function () {
  603. var textEl = this._textContent;
  604. if (textEl) {
  605. textEl.innerTransformable = null;
  606. this._detachComponent(textEl);
  607. this._textContent = null;
  608. this._innerTextDefaultStyle = null;
  609. this.markRedraw();
  610. }
  611. };
  612. Element.prototype.getTextGuideLine = function () {
  613. return this._textGuide;
  614. };
  615. Element.prototype.setTextGuideLine = function (guideLine) {
  616. if (this._textGuide && this._textGuide !== guideLine) {
  617. this.removeTextGuideLine();
  618. }
  619. this._attachComponent(guideLine);
  620. this._textGuide = guideLine;
  621. this.markRedraw();
  622. };
  623. Element.prototype.removeTextGuideLine = function () {
  624. var textGuide = this._textGuide;
  625. if (textGuide) {
  626. this._detachComponent(textGuide);
  627. this._textGuide = null;
  628. this.markRedraw();
  629. }
  630. };
  631. Element.prototype.markRedraw = function () {
  632. this.__dirty |= REDRAW_BIT;
  633. var zr = this.__zr;
  634. if (zr) {
  635. if (this.__inHover) {
  636. zr.refreshHover();
  637. }
  638. else {
  639. zr.refresh();
  640. }
  641. }
  642. if (this.__hostTarget) {
  643. this.__hostTarget.markRedraw();
  644. }
  645. };
  646. Element.prototype.dirty = function () {
  647. this.markRedraw();
  648. };
  649. Element.prototype._toggleHoverLayerFlag = function (inHover) {
  650. this.__inHover = inHover;
  651. var textContent = this._textContent;
  652. var textGuide = this._textGuide;
  653. if (textContent) {
  654. textContent.__inHover = inHover;
  655. }
  656. if (textGuide) {
  657. textGuide.__inHover = inHover;
  658. }
  659. };
  660. Element.prototype.addSelfToZr = function (zr) {
  661. if (this.__zr === zr) {
  662. return;
  663. }
  664. this.__zr = zr;
  665. var animators = this.animators;
  666. if (animators) {
  667. for (var i = 0; i < animators.length; i++) {
  668. zr.animation.addAnimator(animators[i]);
  669. }
  670. }
  671. if (this._clipPath) {
  672. this._clipPath.addSelfToZr(zr);
  673. }
  674. if (this._textContent) {
  675. this._textContent.addSelfToZr(zr);
  676. }
  677. if (this._textGuide) {
  678. this._textGuide.addSelfToZr(zr);
  679. }
  680. };
  681. Element.prototype.removeSelfFromZr = function (zr) {
  682. if (!this.__zr) {
  683. return;
  684. }
  685. this.__zr = null;
  686. var animators = this.animators;
  687. if (animators) {
  688. for (var i = 0; i < animators.length; i++) {
  689. zr.animation.removeAnimator(animators[i]);
  690. }
  691. }
  692. if (this._clipPath) {
  693. this._clipPath.removeSelfFromZr(zr);
  694. }
  695. if (this._textContent) {
  696. this._textContent.removeSelfFromZr(zr);
  697. }
  698. if (this._textGuide) {
  699. this._textGuide.removeSelfFromZr(zr);
  700. }
  701. };
  702. Element.prototype.animate = function (key, loop, allowDiscreteAnimation) {
  703. var target = key ? this[key] : this;
  704. if (process.env.NODE_ENV !== 'production') {
  705. if (!target) {
  706. logError('Property "'
  707. + key
  708. + '" is not existed in element '
  709. + this.id);
  710. return;
  711. }
  712. }
  713. var animator = new Animator(target, loop, allowDiscreteAnimation);
  714. key && (animator.targetName = key);
  715. this.addAnimator(animator, key);
  716. return animator;
  717. };
  718. Element.prototype.addAnimator = function (animator, key) {
  719. var zr = this.__zr;
  720. var el = this;
  721. animator.during(function () {
  722. el.updateDuringAnimation(key);
  723. }).done(function () {
  724. var animators = el.animators;
  725. var idx = indexOf(animators, animator);
  726. if (idx >= 0) {
  727. animators.splice(idx, 1);
  728. }
  729. });
  730. this.animators.push(animator);
  731. if (zr) {
  732. zr.animation.addAnimator(animator);
  733. }
  734. zr && zr.wakeUp();
  735. };
  736. Element.prototype.updateDuringAnimation = function (key) {
  737. this.markRedraw();
  738. };
  739. Element.prototype.stopAnimation = function (scope, forwardToLast) {
  740. var animators = this.animators;
  741. var len = animators.length;
  742. var leftAnimators = [];
  743. for (var i = 0; i < len; i++) {
  744. var animator = animators[i];
  745. if (!scope || scope === animator.scope) {
  746. animator.stop(forwardToLast);
  747. }
  748. else {
  749. leftAnimators.push(animator);
  750. }
  751. }
  752. this.animators = leftAnimators;
  753. return this;
  754. };
  755. Element.prototype.animateTo = function (target, cfg, animationProps) {
  756. animateTo(this, target, cfg, animationProps);
  757. };
  758. Element.prototype.animateFrom = function (target, cfg, animationProps) {
  759. animateTo(this, target, cfg, animationProps, true);
  760. };
  761. Element.prototype._transitionState = function (stateName, target, cfg, animationProps) {
  762. var animators = animateTo(this, target, cfg, animationProps);
  763. for (var i = 0; i < animators.length; i++) {
  764. animators[i].__fromStateTransition = stateName;
  765. }
  766. };
  767. Element.prototype.getBoundingRect = function () {
  768. return null;
  769. };
  770. Element.prototype.getPaintRect = function () {
  771. return null;
  772. };
  773. Element.initDefaultProps = (function () {
  774. var elProto = Element.prototype;
  775. elProto.type = 'element';
  776. elProto.name = '';
  777. elProto.ignore =
  778. elProto.silent =
  779. elProto.isGroup =
  780. elProto.draggable =
  781. elProto.dragging =
  782. elProto.ignoreClip =
  783. elProto.__inHover = false;
  784. elProto.__dirty = REDRAW_BIT;
  785. var logs = {};
  786. function logDeprecatedError(key, xKey, yKey) {
  787. if (!logs[key + xKey + yKey]) {
  788. console.warn("DEPRECATED: '" + key + "' has been deprecated. use '" + xKey + "', '" + yKey + "' instead");
  789. logs[key + xKey + yKey] = true;
  790. }
  791. }
  792. function createLegacyProperty(key, privateKey, xKey, yKey) {
  793. Object.defineProperty(elProto, key, {
  794. get: function () {
  795. if (process.env.NODE_ENV !== 'production') {
  796. logDeprecatedError(key, xKey, yKey);
  797. }
  798. if (!this[privateKey]) {
  799. var pos = this[privateKey] = [];
  800. enhanceArray(this, pos);
  801. }
  802. return this[privateKey];
  803. },
  804. set: function (pos) {
  805. if (process.env.NODE_ENV !== 'production') {
  806. logDeprecatedError(key, xKey, yKey);
  807. }
  808. this[xKey] = pos[0];
  809. this[yKey] = pos[1];
  810. this[privateKey] = pos;
  811. enhanceArray(this, pos);
  812. }
  813. });
  814. function enhanceArray(self, pos) {
  815. Object.defineProperty(pos, 0, {
  816. get: function () {
  817. return self[xKey];
  818. },
  819. set: function (val) {
  820. self[xKey] = val;
  821. }
  822. });
  823. Object.defineProperty(pos, 1, {
  824. get: function () {
  825. return self[yKey];
  826. },
  827. set: function (val) {
  828. self[yKey] = val;
  829. }
  830. });
  831. }
  832. }
  833. if (Object.defineProperty) {
  834. createLegacyProperty('position', '_legacyPos', 'x', 'y');
  835. createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY');
  836. createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY');
  837. }
  838. })();
  839. return Element;
  840. }());
  841. mixin(Element, Eventful);
  842. mixin(Element, Transformable);
  843. function animateTo(animatable, target, cfg, animationProps, reverse) {
  844. cfg = cfg || {};
  845. var animators = [];
  846. animateToShallow(animatable, '', animatable, target, cfg, animationProps, animators, reverse);
  847. var finishCount = animators.length;
  848. var doneHappened = false;
  849. var cfgDone = cfg.done;
  850. var cfgAborted = cfg.aborted;
  851. var doneCb = function () {
  852. doneHappened = true;
  853. finishCount--;
  854. if (finishCount <= 0) {
  855. doneHappened
  856. ? (cfgDone && cfgDone())
  857. : (cfgAborted && cfgAborted());
  858. }
  859. };
  860. var abortedCb = function () {
  861. finishCount--;
  862. if (finishCount <= 0) {
  863. doneHappened
  864. ? (cfgDone && cfgDone())
  865. : (cfgAborted && cfgAborted());
  866. }
  867. };
  868. if (!finishCount) {
  869. cfgDone && cfgDone();
  870. }
  871. if (animators.length > 0 && cfg.during) {
  872. animators[0].during(function (target, percent) {
  873. cfg.during(percent);
  874. });
  875. }
  876. for (var i = 0; i < animators.length; i++) {
  877. var animator = animators[i];
  878. if (doneCb) {
  879. animator.done(doneCb);
  880. }
  881. if (abortedCb) {
  882. animator.aborted(abortedCb);
  883. }
  884. if (cfg.force) {
  885. animator.duration(cfg.duration);
  886. }
  887. animator.start(cfg.easing);
  888. }
  889. return animators;
  890. }
  891. function copyArrShallow(source, target, len) {
  892. for (var i = 0; i < len; i++) {
  893. source[i] = target[i];
  894. }
  895. }
  896. function is2DArray(value) {
  897. return isArrayLike(value[0]);
  898. }
  899. function copyValue(target, source, key) {
  900. if (isArrayLike(source[key])) {
  901. if (!isArrayLike(target[key])) {
  902. target[key] = [];
  903. }
  904. if (isTypedArray(source[key])) {
  905. var len = source[key].length;
  906. if (target[key].length !== len) {
  907. target[key] = new (source[key].constructor)(len);
  908. copyArrShallow(target[key], source[key], len);
  909. }
  910. }
  911. else {
  912. var sourceArr = source[key];
  913. var targetArr = target[key];
  914. var len0 = sourceArr.length;
  915. if (is2DArray(sourceArr)) {
  916. var len1 = sourceArr[0].length;
  917. for (var i = 0; i < len0; i++) {
  918. if (!targetArr[i]) {
  919. targetArr[i] = Array.prototype.slice.call(sourceArr[i]);
  920. }
  921. else {
  922. copyArrShallow(targetArr[i], sourceArr[i], len1);
  923. }
  924. }
  925. }
  926. else {
  927. copyArrShallow(targetArr, sourceArr, len0);
  928. }
  929. targetArr.length = sourceArr.length;
  930. }
  931. }
  932. else {
  933. target[key] = source[key];
  934. }
  935. }
  936. function isValueSame(val1, val2) {
  937. return val1 === val2
  938. || isArrayLike(val1) && isArrayLike(val2) && is1DArraySame(val1, val2);
  939. }
  940. function is1DArraySame(arr0, arr1) {
  941. var len = arr0.length;
  942. if (len !== arr1.length) {
  943. return false;
  944. }
  945. for (var i = 0; i < len; i++) {
  946. if (arr0[i] !== arr1[i]) {
  947. return false;
  948. }
  949. }
  950. return true;
  951. }
  952. function animateToShallow(animatable, topKey, animateObj, target, cfg, animationProps, animators, reverse) {
  953. var targetKeys = keys(target);
  954. var duration = cfg.duration;
  955. var delay = cfg.delay;
  956. var additive = cfg.additive;
  957. var setToFinal = cfg.setToFinal;
  958. var animateAll = !isObject(animationProps);
  959. var existsAnimators = animatable.animators;
  960. var animationKeys = [];
  961. for (var k = 0; k < targetKeys.length; k++) {
  962. var innerKey = targetKeys[k];
  963. var targetVal = target[innerKey];
  964. if (targetVal != null && animateObj[innerKey] != null
  965. && (animateAll || animationProps[innerKey])) {
  966. if (isObject(targetVal)
  967. && !isArrayLike(targetVal)
  968. && !isGradientObject(targetVal)) {
  969. if (topKey) {
  970. if (!reverse) {
  971. animateObj[innerKey] = targetVal;
  972. animatable.updateDuringAnimation(topKey);
  973. }
  974. continue;
  975. }
  976. animateToShallow(animatable, innerKey, animateObj[innerKey], targetVal, cfg, animationProps && animationProps[innerKey], animators, reverse);
  977. }
  978. else {
  979. animationKeys.push(innerKey);
  980. }
  981. }
  982. else if (!reverse) {
  983. animateObj[innerKey] = targetVal;
  984. animatable.updateDuringAnimation(topKey);
  985. animationKeys.push(innerKey);
  986. }
  987. }
  988. var keyLen = animationKeys.length;
  989. if (!additive && keyLen) {
  990. for (var i = 0; i < existsAnimators.length; i++) {
  991. var animator = existsAnimators[i];
  992. if (animator.targetName === topKey) {
  993. var allAborted = animator.stopTracks(animationKeys);
  994. if (allAborted) {
  995. var idx = indexOf(existsAnimators, animator);
  996. existsAnimators.splice(idx, 1);
  997. }
  998. }
  999. }
  1000. }
  1001. if (!cfg.force) {
  1002. animationKeys = filter(animationKeys, function (key) { return !isValueSame(target[key], animateObj[key]); });
  1003. keyLen = animationKeys.length;
  1004. }
  1005. if (keyLen > 0
  1006. || (cfg.force && !animators.length)) {
  1007. var revertedSource = void 0;
  1008. var reversedTarget = void 0;
  1009. var sourceClone = void 0;
  1010. if (reverse) {
  1011. reversedTarget = {};
  1012. if (setToFinal) {
  1013. revertedSource = {};
  1014. }
  1015. for (var i = 0; i < keyLen; i++) {
  1016. var innerKey = animationKeys[i];
  1017. reversedTarget[innerKey] = animateObj[innerKey];
  1018. if (setToFinal) {
  1019. revertedSource[innerKey] = target[innerKey];
  1020. }
  1021. else {
  1022. animateObj[innerKey] = target[innerKey];
  1023. }
  1024. }
  1025. }
  1026. else if (setToFinal) {
  1027. sourceClone = {};
  1028. for (var i = 0; i < keyLen; i++) {
  1029. var innerKey = animationKeys[i];
  1030. sourceClone[innerKey] = cloneValue(animateObj[innerKey]);
  1031. copyValue(animateObj, target, innerKey);
  1032. }
  1033. }
  1034. var animator = new Animator(animateObj, false, false, additive ? filter(existsAnimators, function (animator) { return animator.targetName === topKey; }) : null);
  1035. animator.targetName = topKey;
  1036. if (cfg.scope) {
  1037. animator.scope = cfg.scope;
  1038. }
  1039. if (setToFinal && revertedSource) {
  1040. animator.whenWithKeys(0, revertedSource, animationKeys);
  1041. }
  1042. if (sourceClone) {
  1043. animator.whenWithKeys(0, sourceClone, animationKeys);
  1044. }
  1045. animator.whenWithKeys(duration == null ? 500 : duration, reverse ? reversedTarget : target, animationKeys).delay(delay || 0);
  1046. animatable.addAnimator(animator, topKey);
  1047. animators.push(animator);
  1048. }
  1049. }
  1050. export default Element;