Group.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. var zrUtil = require("../core/util");
  2. var Element = require("../Element");
  3. var BoundingRect = require("../core/BoundingRect");
  4. /**
  5. * Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上
  6. * @module zrender/graphic/Group
  7. * @example
  8. * var Group = require('zrender/container/Group');
  9. * var Circle = require('zrender/graphic/shape/Circle');
  10. * var g = new Group();
  11. * g.position[0] = 100;
  12. * g.position[1] = 100;
  13. * g.add(new Circle({
  14. * style: {
  15. * x: 100,
  16. * y: 100,
  17. * r: 20,
  18. * }
  19. * }));
  20. * zr.add(g);
  21. */
  22. /**
  23. * @alias module:zrender/graphic/Group
  24. * @constructor
  25. * @extends module:zrender/mixin/Transformable
  26. * @extends module:zrender/mixin/Eventful
  27. */
  28. var Group = function (opts) {
  29. opts = opts || {};
  30. Element.call(this, opts);
  31. for (var key in opts) {
  32. if (opts.hasOwnProperty(key)) {
  33. this[key] = opts[key];
  34. }
  35. }
  36. this._children = [];
  37. this.__storage = null;
  38. this.__dirty = true;
  39. };
  40. Group.prototype = {
  41. constructor: Group,
  42. isGroup: true,
  43. /**
  44. * @type {string}
  45. */
  46. type: 'group',
  47. /**
  48. * 所有子孙元素是否响应鼠标事件
  49. * @name module:/zrender/container/Group#silent
  50. * @type {boolean}
  51. * @default false
  52. */
  53. silent: false,
  54. /**
  55. * @return {Array.<module:zrender/Element>}
  56. */
  57. children: function () {
  58. return this._children.slice();
  59. },
  60. /**
  61. * 获取指定 index 的儿子节点
  62. * @param {number} idx
  63. * @return {module:zrender/Element}
  64. */
  65. childAt: function (idx) {
  66. return this._children[idx];
  67. },
  68. /**
  69. * 获取指定名字的儿子节点
  70. * @param {string} name
  71. * @return {module:zrender/Element}
  72. */
  73. childOfName: function (name) {
  74. var children = this._children;
  75. for (var i = 0; i < children.length; i++) {
  76. if (children[i].name === name) {
  77. return children[i];
  78. }
  79. }
  80. },
  81. /**
  82. * @return {number}
  83. */
  84. childCount: function () {
  85. return this._children.length;
  86. },
  87. /**
  88. * 添加子节点到最后
  89. * @param {module:zrender/Element} child
  90. */
  91. add: function (child) {
  92. if (child && child !== this && child.parent !== this) {
  93. this._children.push(child);
  94. this._doAdd(child);
  95. }
  96. return this;
  97. },
  98. /**
  99. * 添加子节点在 nextSibling 之前
  100. * @param {module:zrender/Element} child
  101. * @param {module:zrender/Element} nextSibling
  102. */
  103. addBefore: function (child, nextSibling) {
  104. if (child && child !== this && child.parent !== this && nextSibling && nextSibling.parent === this) {
  105. var children = this._children;
  106. var idx = children.indexOf(nextSibling);
  107. if (idx >= 0) {
  108. children.splice(idx, 0, child);
  109. this._doAdd(child);
  110. }
  111. }
  112. return this;
  113. },
  114. _doAdd: function (child) {
  115. if (child.parent) {
  116. child.parent.remove(child);
  117. }
  118. child.parent = this;
  119. var storage = this.__storage;
  120. var zr = this.__zr;
  121. if (storage && storage !== child.__storage) {
  122. storage.addToStorage(child);
  123. if (child instanceof Group) {
  124. child.addChildrenToStorage(storage);
  125. }
  126. }
  127. zr && zr.refresh();
  128. },
  129. /**
  130. * 移除子节点
  131. * @param {module:zrender/Element} child
  132. */
  133. remove: function (child) {
  134. var zr = this.__zr;
  135. var storage = this.__storage;
  136. var children = this._children;
  137. var idx = zrUtil.indexOf(children, child);
  138. if (idx < 0) {
  139. return this;
  140. }
  141. children.splice(idx, 1);
  142. child.parent = null;
  143. if (storage) {
  144. storage.delFromStorage(child);
  145. if (child instanceof Group) {
  146. child.delChildrenFromStorage(storage);
  147. }
  148. }
  149. zr && zr.refresh();
  150. return this;
  151. },
  152. /**
  153. * 移除所有子节点
  154. */
  155. removeAll: function () {
  156. var children = this._children;
  157. var storage = this.__storage;
  158. var child;
  159. var i;
  160. for (i = 0; i < children.length; i++) {
  161. child = children[i];
  162. if (storage) {
  163. storage.delFromStorage(child);
  164. if (child instanceof Group) {
  165. child.delChildrenFromStorage(storage);
  166. }
  167. }
  168. child.parent = null;
  169. }
  170. children.length = 0;
  171. return this;
  172. },
  173. /**
  174. * 遍历所有子节点
  175. * @param {Function} cb
  176. * @param {} context
  177. */
  178. eachChild: function (cb, context) {
  179. var children = this._children;
  180. for (var i = 0; i < children.length; i++) {
  181. var child = children[i];
  182. cb.call(context, child, i);
  183. }
  184. return this;
  185. },
  186. /**
  187. * 深度优先遍历所有子孙节点
  188. * @param {Function} cb
  189. * @param {} context
  190. */
  191. traverse: function (cb, context) {
  192. for (var i = 0; i < this._children.length; i++) {
  193. var child = this._children[i];
  194. cb.call(context, child);
  195. if (child.type === 'group') {
  196. child.traverse(cb, context);
  197. }
  198. }
  199. return this;
  200. },
  201. addChildrenToStorage: function (storage) {
  202. for (var i = 0; i < this._children.length; i++) {
  203. var child = this._children[i];
  204. storage.addToStorage(child);
  205. if (child instanceof Group) {
  206. child.addChildrenToStorage(storage);
  207. }
  208. }
  209. },
  210. delChildrenFromStorage: function (storage) {
  211. for (var i = 0; i < this._children.length; i++) {
  212. var child = this._children[i];
  213. storage.delFromStorage(child);
  214. if (child instanceof Group) {
  215. child.delChildrenFromStorage(storage);
  216. }
  217. }
  218. },
  219. dirty: function () {
  220. this.__dirty = true;
  221. this.__zr && this.__zr.refresh();
  222. return this;
  223. },
  224. /**
  225. * @return {module:zrender/core/BoundingRect}
  226. */
  227. getBoundingRect: function (includeChildren) {
  228. // TODO Caching
  229. var rect = null;
  230. var tmpRect = new BoundingRect(0, 0, 0, 0);
  231. var children = includeChildren || this._children;
  232. var tmpMat = [];
  233. for (var i = 0; i < children.length; i++) {
  234. var child = children[i];
  235. if (child.ignore || child.invisible) {
  236. continue;
  237. }
  238. var childRect = child.getBoundingRect();
  239. var transform = child.getLocalTransform(tmpMat); // TODO
  240. // The boundingRect cacluated by transforming original
  241. // rect may be bigger than the actual bundingRect when rotation
  242. // is used. (Consider a circle rotated aginst its center, where
  243. // the actual boundingRect should be the same as that not be
  244. // rotated.) But we can not find better approach to calculate
  245. // actual boundingRect yet, considering performance.
  246. if (transform) {
  247. tmpRect.copy(childRect);
  248. tmpRect.applyTransform(transform);
  249. rect = rect || tmpRect.clone();
  250. rect.union(tmpRect);
  251. } else {
  252. rect = rect || childRect.clone();
  253. rect.union(childRect);
  254. }
  255. }
  256. return rect || tmpRect;
  257. }
  258. };
  259. zrUtil.inherits(Group, Element);
  260. var _default = Group;
  261. module.exports = _default;