312 lines
6.7 KiB
JavaScript
312 lines
6.7 KiB
JavaScript
|
var zrUtil = require("../core/util");
|
|||
|
|
|||
|
var Element = require("../Element");
|
|||
|
|
|||
|
var BoundingRect = require("../core/BoundingRect");
|
|||
|
|
|||
|
/**
|
|||
|
* Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上
|
|||
|
* @module zrender/graphic/Group
|
|||
|
* @example
|
|||
|
* var Group = require('zrender/container/Group');
|
|||
|
* var Circle = require('zrender/graphic/shape/Circle');
|
|||
|
* var g = new Group();
|
|||
|
* g.position[0] = 100;
|
|||
|
* g.position[1] = 100;
|
|||
|
* g.add(new Circle({
|
|||
|
* style: {
|
|||
|
* x: 100,
|
|||
|
* y: 100,
|
|||
|
* r: 20,
|
|||
|
* }
|
|||
|
* }));
|
|||
|
* zr.add(g);
|
|||
|
*/
|
|||
|
|
|||
|
/**
|
|||
|
* @alias module:zrender/graphic/Group
|
|||
|
* @constructor
|
|||
|
* @extends module:zrender/mixin/Transformable
|
|||
|
* @extends module:zrender/mixin/Eventful
|
|||
|
*/
|
|||
|
var Group = function (opts) {
|
|||
|
opts = opts || {};
|
|||
|
Element.call(this, opts);
|
|||
|
|
|||
|
for (var key in opts) {
|
|||
|
if (opts.hasOwnProperty(key)) {
|
|||
|
this[key] = opts[key];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this._children = [];
|
|||
|
this.__storage = null;
|
|||
|
this.__dirty = true;
|
|||
|
};
|
|||
|
|
|||
|
Group.prototype = {
|
|||
|
constructor: Group,
|
|||
|
isGroup: true,
|
|||
|
|
|||
|
/**
|
|||
|
* @type {string}
|
|||
|
*/
|
|||
|
type: 'group',
|
|||
|
|
|||
|
/**
|
|||
|
* 所有子孙元素是否响应鼠标事件
|
|||
|
* @name module:/zrender/container/Group#silent
|
|||
|
* @type {boolean}
|
|||
|
* @default false
|
|||
|
*/
|
|||
|
silent: false,
|
|||
|
|
|||
|
/**
|
|||
|
* @return {Array.<module:zrender/Element>}
|
|||
|
*/
|
|||
|
children: function () {
|
|||
|
return this._children.slice();
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 获取指定 index 的儿子节点
|
|||
|
* @param {number} idx
|
|||
|
* @return {module:zrender/Element}
|
|||
|
*/
|
|||
|
childAt: function (idx) {
|
|||
|
return this._children[idx];
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 获取指定名字的儿子节点
|
|||
|
* @param {string} name
|
|||
|
* @return {module:zrender/Element}
|
|||
|
*/
|
|||
|
childOfName: function (name) {
|
|||
|
var children = this._children;
|
|||
|
|
|||
|
for (var i = 0; i < children.length; i++) {
|
|||
|
if (children[i].name === name) {
|
|||
|
return children[i];
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* @return {number}
|
|||
|
*/
|
|||
|
childCount: function () {
|
|||
|
return this._children.length;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 添加子节点到最后
|
|||
|
* @param {module:zrender/Element} child
|
|||
|
*/
|
|||
|
add: function (child) {
|
|||
|
if (child && child !== this && child.parent !== this) {
|
|||
|
this._children.push(child);
|
|||
|
|
|||
|
this._doAdd(child);
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 添加子节点在 nextSibling 之前
|
|||
|
* @param {module:zrender/Element} child
|
|||
|
* @param {module:zrender/Element} nextSibling
|
|||
|
*/
|
|||
|
addBefore: function (child, nextSibling) {
|
|||
|
if (child && child !== this && child.parent !== this && nextSibling && nextSibling.parent === this) {
|
|||
|
var children = this._children;
|
|||
|
var idx = children.indexOf(nextSibling);
|
|||
|
|
|||
|
if (idx >= 0) {
|
|||
|
children.splice(idx, 0, child);
|
|||
|
|
|||
|
this._doAdd(child);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
},
|
|||
|
_doAdd: function (child) {
|
|||
|
if (child.parent) {
|
|||
|
child.parent.remove(child);
|
|||
|
}
|
|||
|
|
|||
|
child.parent = this;
|
|||
|
var storage = this.__storage;
|
|||
|
var zr = this.__zr;
|
|||
|
|
|||
|
if (storage && storage !== child.__storage) {
|
|||
|
storage.addToStorage(child);
|
|||
|
|
|||
|
if (child instanceof Group) {
|
|||
|
child.addChildrenToStorage(storage);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
zr && zr.refresh();
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 移除子节点
|
|||
|
* @param {module:zrender/Element} child
|
|||
|
*/
|
|||
|
remove: function (child) {
|
|||
|
var zr = this.__zr;
|
|||
|
var storage = this.__storage;
|
|||
|
var children = this._children;
|
|||
|
var idx = zrUtil.indexOf(children, child);
|
|||
|
|
|||
|
if (idx < 0) {
|
|||
|
return this;
|
|||
|
}
|
|||
|
|
|||
|
children.splice(idx, 1);
|
|||
|
child.parent = null;
|
|||
|
|
|||
|
if (storage) {
|
|||
|
storage.delFromStorage(child);
|
|||
|
|
|||
|
if (child instanceof Group) {
|
|||
|
child.delChildrenFromStorage(storage);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
zr && zr.refresh();
|
|||
|
return this;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 移除所有子节点
|
|||
|
*/
|
|||
|
removeAll: function () {
|
|||
|
var children = this._children;
|
|||
|
var storage = this.__storage;
|
|||
|
var child;
|
|||
|
var i;
|
|||
|
|
|||
|
for (i = 0; i < children.length; i++) {
|
|||
|
child = children[i];
|
|||
|
|
|||
|
if (storage) {
|
|||
|
storage.delFromStorage(child);
|
|||
|
|
|||
|
if (child instanceof Group) {
|
|||
|
child.delChildrenFromStorage(storage);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
child.parent = null;
|
|||
|
}
|
|||
|
|
|||
|
children.length = 0;
|
|||
|
return this;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 遍历所有子节点
|
|||
|
* @param {Function} cb
|
|||
|
* @param {} context
|
|||
|
*/
|
|||
|
eachChild: function (cb, context) {
|
|||
|
var children = this._children;
|
|||
|
|
|||
|
for (var i = 0; i < children.length; i++) {
|
|||
|
var child = children[i];
|
|||
|
cb.call(context, child, i);
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 深度优先遍历所有子孙节点
|
|||
|
* @param {Function} cb
|
|||
|
* @param {} context
|
|||
|
*/
|
|||
|
traverse: function (cb, context) {
|
|||
|
for (var i = 0; i < this._children.length; i++) {
|
|||
|
var child = this._children[i];
|
|||
|
cb.call(context, child);
|
|||
|
|
|||
|
if (child.type === 'group') {
|
|||
|
child.traverse(cb, context);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return this;
|
|||
|
},
|
|||
|
addChildrenToStorage: function (storage) {
|
|||
|
for (var i = 0; i < this._children.length; i++) {
|
|||
|
var child = this._children[i];
|
|||
|
storage.addToStorage(child);
|
|||
|
|
|||
|
if (child instanceof Group) {
|
|||
|
child.addChildrenToStorage(storage);
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
delChildrenFromStorage: function (storage) {
|
|||
|
for (var i = 0; i < this._children.length; i++) {
|
|||
|
var child = this._children[i];
|
|||
|
storage.delFromStorage(child);
|
|||
|
|
|||
|
if (child instanceof Group) {
|
|||
|
child.delChildrenFromStorage(storage);
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
dirty: function () {
|
|||
|
this.__dirty = true;
|
|||
|
this.__zr && this.__zr.refresh();
|
|||
|
return this;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* @return {module:zrender/core/BoundingRect}
|
|||
|
*/
|
|||
|
getBoundingRect: function (includeChildren) {
|
|||
|
// TODO Caching
|
|||
|
var rect = null;
|
|||
|
var tmpRect = new BoundingRect(0, 0, 0, 0);
|
|||
|
var children = includeChildren || this._children;
|
|||
|
var tmpMat = [];
|
|||
|
|
|||
|
for (var i = 0; i < children.length; i++) {
|
|||
|
var child = children[i];
|
|||
|
|
|||
|
if (child.ignore || child.invisible) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
var childRect = child.getBoundingRect();
|
|||
|
var transform = child.getLocalTransform(tmpMat); // TODO
|
|||
|
// The boundingRect cacluated by transforming original
|
|||
|
// rect may be bigger than the actual bundingRect when rotation
|
|||
|
// is used. (Consider a circle rotated aginst its center, where
|
|||
|
// the actual boundingRect should be the same as that not be
|
|||
|
// rotated.) But we can not find better approach to calculate
|
|||
|
// actual boundingRect yet, considering performance.
|
|||
|
|
|||
|
if (transform) {
|
|||
|
tmpRect.copy(childRect);
|
|||
|
tmpRect.applyTransform(transform);
|
|||
|
rect = rect || tmpRect.clone();
|
|||
|
rect.union(tmpRect);
|
|||
|
} else {
|
|||
|
rect = rect || childRect.clone();
|
|||
|
rect.union(childRect);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return rect || tmpRect;
|
|||
|
}
|
|||
|
};
|
|||
|
zrUtil.inherits(Group, Element);
|
|||
|
var _default = Group;
|
|||
|
module.exports = _default;
|