Element.js 39 KB

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