Displayable.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. import { __extends } from "tslib";
  2. import Element, { IN_HOVER_LAYER_KIND_ONLY_STYLE_CHANGE, } from '../Element.js';
  3. import BoundingRect from '../core/BoundingRect.js';
  4. import { keys, extend, createObject } from '../core/util.js';
  5. import { REDRAW_BIT, STYLE_CHANGED_BIT } from './constants.js';
  6. var STYLE_MAGIC_KEY = '__zr_style_' + Math.round((Math.random() * 10));
  7. export var DEFAULT_COMMON_STYLE = {
  8. shadowBlur: 0,
  9. shadowOffsetX: 0,
  10. shadowOffsetY: 0,
  11. shadowColor: '#000',
  12. opacity: 1,
  13. blend: 'source-over'
  14. };
  15. export var DEFAULT_COMMON_ANIMATION_PROPS = {
  16. style: {
  17. shadowBlur: true,
  18. shadowOffsetX: true,
  19. shadowOffsetY: true,
  20. shadowColor: true,
  21. opacity: true
  22. }
  23. };
  24. DEFAULT_COMMON_STYLE[STYLE_MAGIC_KEY] = true;
  25. var PRIMARY_STATES_KEYS = ['z', 'z2', 'invisible'];
  26. var PRIMARY_STATES_KEYS_IN_HOVER_LAYER = ['invisible'];
  27. var Displayable = (function (_super) {
  28. __extends(Displayable, _super);
  29. function Displayable(props) {
  30. return _super.call(this, props) || this;
  31. }
  32. Displayable.prototype._init = function (props) {
  33. var keysArr = keys(props);
  34. for (var i = 0; i < keysArr.length; i++) {
  35. var key = keysArr[i];
  36. if (key === 'style') {
  37. this.useStyle(props[key]);
  38. }
  39. else {
  40. _super.prototype.attrKV.call(this, key, props[key]);
  41. }
  42. }
  43. if (!this.style) {
  44. this.useStyle({});
  45. }
  46. };
  47. Displayable.prototype.beforeBrush = function (param) { };
  48. Displayable.prototype.afterBrush = function () { };
  49. Displayable.prototype.innerBeforeBrush = function () { };
  50. Displayable.prototype.innerAfterBrush = function () { };
  51. Displayable.prototype.shouldBePainted = function (viewWidth, viewHeight, considerClipPath, considerAncestors) {
  52. var m = this.transform;
  53. if (this.ignore
  54. || this.invisible
  55. || this.style.opacity === 0
  56. || (this.culling
  57. && isDisplayableCulled(this, viewWidth, viewHeight))
  58. || (m && !m[0] && !m[3])) {
  59. return false;
  60. }
  61. if (considerClipPath && this.__clipPaths && this.__clipPaths.length) {
  62. for (var i = 0; i < this.__clipPaths.length; ++i) {
  63. if (this.__clipPaths[i].isZeroArea()) {
  64. return false;
  65. }
  66. }
  67. }
  68. if (considerAncestors && this.parent) {
  69. var parent_1 = this.parent;
  70. while (parent_1) {
  71. if (parent_1.ignore) {
  72. return false;
  73. }
  74. parent_1 = parent_1.parent;
  75. }
  76. }
  77. return true;
  78. };
  79. Displayable.prototype.contain = function (x, y) {
  80. return this.rectContain(x, y);
  81. };
  82. Displayable.prototype.traverse = function (cb, context) {
  83. cb.call(context, this);
  84. };
  85. Displayable.prototype.rectContain = function (x, y) {
  86. var coord = this.transformCoordToLocal(x, y);
  87. var rect = this.getBoundingRect();
  88. return rect.contain(coord[0], coord[1]);
  89. };
  90. Displayable.prototype.getPaintRect = function () {
  91. var rect = this._paintRect;
  92. if (!this._paintRect || this.__dirty) {
  93. var transform = this.transform;
  94. var elRect = this.getBoundingRect();
  95. var style = this.style;
  96. var shadowSize = style.shadowBlur || 0;
  97. var shadowOffsetX = style.shadowOffsetX || 0;
  98. var shadowOffsetY = style.shadowOffsetY || 0;
  99. rect = this._paintRect || (this._paintRect = new BoundingRect(0, 0, 0, 0));
  100. if (transform) {
  101. BoundingRect.applyTransform(rect, elRect, transform);
  102. }
  103. else {
  104. rect.copy(elRect);
  105. }
  106. if (shadowSize || shadowOffsetX || shadowOffsetY) {
  107. rect.width += shadowSize * 2 + Math.abs(shadowOffsetX);
  108. rect.height += shadowSize * 2 + Math.abs(shadowOffsetY);
  109. rect.x = Math.min(rect.x, rect.x + shadowOffsetX - shadowSize);
  110. rect.y = Math.min(rect.y, rect.y + shadowOffsetY - shadowSize);
  111. }
  112. var tolerance = this.dirtyRectTolerance;
  113. if (!rect.isZero()) {
  114. rect.x = Math.floor(rect.x - tolerance);
  115. rect.y = Math.floor(rect.y - tolerance);
  116. rect.width = Math.ceil(rect.width + 1 + tolerance * 2);
  117. rect.height = Math.ceil(rect.height + 1 + tolerance * 2);
  118. }
  119. }
  120. return rect;
  121. };
  122. Displayable.prototype.setPrevPaintRect = function (paintRect) {
  123. if (paintRect) {
  124. this._prevPaintRect = this._prevPaintRect || new BoundingRect(0, 0, 0, 0);
  125. this._prevPaintRect.copy(paintRect);
  126. }
  127. else {
  128. this._prevPaintRect = null;
  129. }
  130. };
  131. Displayable.prototype.getPrevPaintRect = function () {
  132. return this._prevPaintRect;
  133. };
  134. Displayable.prototype.animateStyle = function (loop) {
  135. return this.animate('style', loop);
  136. };
  137. Displayable.prototype.updateDuringAnimation = function (targetKey) {
  138. if (targetKey === 'style') {
  139. this.dirtyStyle();
  140. }
  141. else {
  142. this.markRedraw();
  143. }
  144. };
  145. Displayable.prototype.attrKV = function (key, value) {
  146. if (key !== 'style') {
  147. _super.prototype.attrKV.call(this, key, value);
  148. }
  149. else {
  150. if (!this.style) {
  151. this.useStyle(value);
  152. }
  153. else {
  154. this.setStyle(value);
  155. }
  156. }
  157. };
  158. Displayable.prototype.setStyle = function (keyOrObj, value) {
  159. if (typeof keyOrObj === 'string') {
  160. this.style[keyOrObj] = value;
  161. }
  162. else {
  163. extend(this.style, keyOrObj);
  164. }
  165. this.dirtyStyle();
  166. return this;
  167. };
  168. Displayable.prototype.dirtyStyle = function (notRedraw) {
  169. if (!notRedraw) {
  170. this.markRedraw();
  171. }
  172. this.__dirty |= STYLE_CHANGED_BIT;
  173. if (this._rect) {
  174. this._rect = null;
  175. }
  176. };
  177. Displayable.prototype.dirty = function () {
  178. this.dirtyStyle();
  179. };
  180. Displayable.prototype.styleChanged = function () {
  181. return !!(this.__dirty & STYLE_CHANGED_BIT);
  182. };
  183. Displayable.prototype.styleUpdated = function () {
  184. this.__dirty &= ~STYLE_CHANGED_BIT;
  185. };
  186. Displayable.prototype.createStyle = function (obj) {
  187. return createObject(DEFAULT_COMMON_STYLE, obj);
  188. };
  189. Displayable.prototype.useStyle = function (obj) {
  190. if (!obj[STYLE_MAGIC_KEY]) {
  191. obj = this.createStyle(obj);
  192. }
  193. this.style = obj;
  194. this.dirtyStyle();
  195. };
  196. Displayable.prototype._useHoverStyle = function (obj) {
  197. this.__hoverStyle = obj;
  198. };
  199. Displayable.prototype.isStyleObject = function (obj) {
  200. return obj[STYLE_MAGIC_KEY];
  201. };
  202. Displayable.prototype._innerSaveToNormal = function (toState) {
  203. _super.prototype._innerSaveToNormal.call(this, toState);
  204. var normalState = this._normalState;
  205. if (toState.style && !normalState.style) {
  206. normalState.style = this._mergeStyle(this.createStyle(), this.style);
  207. }
  208. this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS);
  209. };
  210. Displayable.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
  211. _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg);
  212. var needsRestoreToNormal = !(state && keepCurrentStates);
  213. var inHoverOnlyStyleChange = this.__inHover === IN_HOVER_LAYER_KIND_ONLY_STYLE_CHANGE;
  214. var targetStyle;
  215. if (state && state.style) {
  216. if (transition) {
  217. if (keepCurrentStates) {
  218. targetStyle = state.style;
  219. }
  220. else {
  221. targetStyle = this._mergeStyle(this.createStyle(), normalState.style);
  222. this._mergeStyle(targetStyle, state.style);
  223. }
  224. }
  225. else {
  226. targetStyle = this._mergeStyle(this.createStyle(), keepCurrentStates ? this.style : normalState.style);
  227. this._mergeStyle(targetStyle, state.style);
  228. }
  229. }
  230. else if (needsRestoreToNormal) {
  231. targetStyle = normalState.style;
  232. }
  233. if (targetStyle) {
  234. if (transition) {
  235. var sourceStyle = this.style;
  236. this.style = this.createStyle(needsRestoreToNormal ? {} : sourceStyle);
  237. if (needsRestoreToNormal) {
  238. var changedKeys = keys(sourceStyle);
  239. for (var i = 0; i < changedKeys.length; i++) {
  240. var key = changedKeys[i];
  241. if (key in targetStyle) {
  242. targetStyle[key] = targetStyle[key];
  243. this.style[key] = sourceStyle[key];
  244. }
  245. }
  246. }
  247. var targetKeys = keys(targetStyle);
  248. for (var i = 0; i < targetKeys.length; i++) {
  249. var key = targetKeys[i];
  250. this.style[key] = this.style[key];
  251. }
  252. this._transitionState(stateName, {
  253. style: targetStyle
  254. }, animationCfg, this.getAnimationStyleProps());
  255. }
  256. else {
  257. if (inHoverOnlyStyleChange) {
  258. this._useHoverStyle(targetStyle);
  259. }
  260. else {
  261. this.useStyle(targetStyle);
  262. }
  263. }
  264. }
  265. if (!inHoverOnlyStyleChange) {
  266. var statesKeys = this.__inHover ? PRIMARY_STATES_KEYS_IN_HOVER_LAYER : PRIMARY_STATES_KEYS;
  267. for (var i = 0; i < statesKeys.length; i++) {
  268. var key = statesKeys[i];
  269. if (state && state[key] != null) {
  270. this[key] = state[key];
  271. }
  272. else if (needsRestoreToNormal) {
  273. if (normalState[key] != null) {
  274. this[key] = normalState[key];
  275. }
  276. }
  277. }
  278. }
  279. };
  280. Displayable.prototype._mergeStates = function (states) {
  281. var mergedState = _super.prototype._mergeStates.call(this, states);
  282. var mergedStyle;
  283. for (var i = 0; i < states.length; i++) {
  284. var state = states[i];
  285. if (state.style) {
  286. mergedStyle = mergedStyle || {};
  287. this._mergeStyle(mergedStyle, state.style);
  288. }
  289. }
  290. if (mergedStyle) {
  291. mergedState.style = mergedStyle;
  292. }
  293. return mergedState;
  294. };
  295. Displayable.prototype._mergeStyle = function (targetStyle, sourceStyle) {
  296. extend(targetStyle, sourceStyle);
  297. return targetStyle;
  298. };
  299. Displayable.prototype.getAnimationStyleProps = function () {
  300. return DEFAULT_COMMON_ANIMATION_PROPS;
  301. };
  302. Displayable.initDefaultProps = (function () {
  303. var dispProto = Displayable.prototype;
  304. dispProto.type = 'displayable';
  305. dispProto.invisible = false;
  306. dispProto.z = 0;
  307. dispProto.z2 = 0;
  308. dispProto.zlevel = 0;
  309. dispProto.culling = false;
  310. dispProto.cursor = 'pointer';
  311. dispProto.rectHover = false;
  312. dispProto.incremental = 0;
  313. dispProto._rect = null;
  314. dispProto.dirtyRectTolerance = 0;
  315. dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT;
  316. })();
  317. return Displayable;
  318. }(Element));
  319. var tmpRect = new BoundingRect(0, 0, 0, 0);
  320. var viewRect = new BoundingRect(0, 0, 0, 0);
  321. function isDisplayableCulled(el, width, height) {
  322. tmpRect.copy(el.getBoundingRect());
  323. if (el.transform) {
  324. tmpRect.applyTransform(el.transform);
  325. }
  326. viewRect.width = width;
  327. viewRect.height = height;
  328. return !tmpRect.intersect(viewRect);
  329. }
  330. export default Displayable;