| Current Path : /home/cbequiperp/www/components/com_flexicontent/librairies/zrender/ |
| Current File : /home/cbequiperp/www/components/com_flexicontent/librairies/zrender/Storage.js |
/**
* Storage内容仓库模块
* @module zrender/Storage
* @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
* @author errorrik (errorrik@gmail.com)
* @author pissang (https://github.com/pissang/)
*/
define(
function (require) {
'use strict';
var util = require('./tool/util');
var Group = require('./Group');
var defaultIterateOption = {
hover: false,
normal: 'down',
update: false
};
function shapeCompareFunc(a, b) {
if (a.zlevel == b.zlevel) {
if (a.z == b.z) {
return a.__renderidx - b.__renderidx;
}
return a.z - b.z;
}
return a.zlevel - b.zlevel;
}
/**
* 内容仓库 (M)
* @alias module:zrender/Storage
* @constructor
*/
var Storage = function () {
// 所有常规形状,id索引的map
this._elements = {};
// 高亮层形状,不稳定,动态增删,数组位置也是z轴方向,靠前显示在下方
this._hoverElements = [];
this._roots = [];
this._shapeList = [];
this._shapeListOffset = 0;
};
/**
* 遍历迭代器
*
* @param {Function} fun 迭代回调函数,return true终止迭代
* @param {Object} [option] 迭代参数,缺省为仅降序遍历普通层图形
* @param {boolean} [option.hover=true] 是否是高亮层图形
* @param {string} [option.normal='up'] 是否是普通层图形,迭代时是否指定及z轴顺序
* @param {boolean} [option.update=false] 是否在迭代前更新形状列表
*
*/
Storage.prototype.iterShape = function (fun, option) {
if (!option) {
option = defaultIterateOption;
}
if (option.hover) {
// 高亮层数据遍历
for (var i = 0, l = this._hoverElements.length; i < l; i++) {
var el = this._hoverElements[i];
el.updateTransform();
if (fun(el)) {
return this;
}
}
}
if (option.update) {
this.updateShapeList();
}
// 遍历: 'down' | 'up'
switch (option.normal) {
case 'down':
// 降序遍历,高层优先
var l = this._shapeList.length;
while (l--) {
if (fun(this._shapeList[l])) {
return this;
}
}
break;
// case 'up':
default:
// 升序遍历,底层优先
for (var i = 0, l = this._shapeList.length; i < l; i++) {
if (fun(this._shapeList[i])) {
return this;
}
}
break;
}
return this;
};
/**
* 返回hover层的形状数组
* @param {boolean} [update=false] 是否在返回前更新图形的变换
* @return {Array.<module:zrender/shape/Base>}
*/
Storage.prototype.getHoverShapes = function (update) {
// hoverConnect
var hoverElements = [];
for (var i = 0, l = this._hoverElements.length; i < l; i++) {
hoverElements.push(this._hoverElements[i]);
var target = this._hoverElements[i].hoverConnect;
if (target) {
var shape;
target = target instanceof Array ? target : [target];
for (var j = 0, k = target.length; j < k; j++) {
shape = target[j].id ? target[j] : this.get(target[j]);
if (shape) {
hoverElements.push(shape);
}
}
}
}
hoverElements.sort(shapeCompareFunc);
if (update) {
for (var i = 0, l = hoverElements.length; i < l; i++) {
hoverElements[i].updateTransform();
}
}
return hoverElements;
};
/**
* 返回所有图形的绘制队列
* @param {boolean} [update=false] 是否在返回前更新该数组
* 详见{@link module:zrender/shape/Base.prototype.updateShapeList}
* @return {Array.<module:zrender/shape/Base>}
*/
Storage.prototype.getShapeList = function (update) {
if (update) {
this.updateShapeList();
}
return this._shapeList;
};
/**
* 更新图形的绘制队列。
* 每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中,
* 最后根据绘制的优先级(zlevel > z > 插入顺序)排序得到绘制队列
*/
Storage.prototype.updateShapeList = function () {
this._shapeListOffset = 0;
for (var i = 0, len = this._roots.length; i < len; i++) {
var root = this._roots[i];
this._updateAndAddShape(root);
}
this._shapeList.length = this._shapeListOffset;
for (var i = 0, len = this._shapeList.length; i < len; i++) {
this._shapeList[i].__renderidx = i;
}
this._shapeList.sort(shapeCompareFunc);
};
Storage.prototype._updateAndAddShape = function (el, clipShapes) {
if (el.ignore) {
return;
}
el.updateTransform();
if (el.type == 'group') {
if (el.clipShape) {
// clipShape 的变换是基于 group 的变换
el.clipShape.parent = el;
el.clipShape.updateTransform();
// PENDING 效率影响
if (clipShapes) {
clipShapes = clipShapes.slice();
clipShapes.push(el.clipShape);
} else {
clipShapes = [el.clipShape];
}
}
for (var i = 0; i < el._children.length; i++) {
var child = el._children[i];
// Force to mark as dirty if group is dirty
child.__dirty = el.__dirty || child.__dirty;
this._updateAndAddShape(child, clipShapes);
}
// Mark group clean here
el.__dirty = false;
}
else {
el.__clipShapes = clipShapes;
this._shapeList[this._shapeListOffset++] = el;
}
};
/**
* 修改图形(Shape)或者组(Group)
*
* @param {string} elId 唯一标识
* @param {Object} [params] 参数
*/
Storage.prototype.mod = function (elId, params) {
var el = this._elements[elId];
if (el) {
el.modSelf();
if (params) {
// 如果第二个参数直接使用 shape
// parent, _storage, __clipShapes 三个属性会有循环引用
// 主要为了向 1.x 版本兼容,2.x 版本不建议使用第二个参数
if (params.parent || params._storage || params.__clipShapes) {
var target = {};
for (var name in params) {
if (
name === 'parent'
|| name === '_storage'
|| name === '__clipShapes'
) {
continue;
}
if (params.hasOwnProperty(name)) {
target[name] = params[name];
}
}
util.merge(el, target, true);
}
else {
util.merge(el, params, true);
}
}
}
return this;
};
/**
* 移动指定的图形(Shape)或者组(Group)的位置
* @param {string} shapeId 形状唯一标识
* @param {number} dx
* @param {number} dy
*/
Storage.prototype.drift = function (shapeId, dx, dy) {
var shape = this._elements[shapeId];
if (shape) {
shape.needTransform = true;
if (shape.draggable === 'horizontal') {
dy = 0;
}
else if (shape.draggable === 'vertical') {
dx = 0;
}
if (!shape.ondrift // ondrift
// 有onbrush并且调用执行返回false或undefined则继续
|| (shape.ondrift && !shape.ondrift(dx, dy))
) {
shape.drift(dx, dy);
}
}
return this;
};
/**
* 添加高亮层数据
*
* @param {module:zrender/shape/Base} shape
*/
Storage.prototype.addHover = function (shape) {
shape.updateNeedTransform();
this._hoverElements.push(shape);
return this;
};
/**
* 清空高亮层数据
*/
Storage.prototype.delHover = function () {
this._hoverElements = [];
return this;
};
/**
* 是否有图形在高亮层里
* @return {boolean}
*/
Storage.prototype.hasHoverShape = function () {
return this._hoverElements.length > 0;
};
/**
* 添加图形(Shape)或者组(Group)到根节点
* @param {module:zrender/shape/Shape|module:zrender/Group} el
*/
Storage.prototype.addRoot = function (el) {
if (el instanceof Group) {
el.addChildrenToStorage(this);
}
this.addToMap(el);
this._roots.push(el);
};
/**
* 删除指定的图形(Shape)或者组(Group)
* @param {string|Array.<string>} [elId] 如果为空清空整个Storage
*/
Storage.prototype.delRoot = function (elId) {
if (typeof(elId) == 'undefined') {
// 不指定elId清空
for (var i = 0; i < this._roots.length; i++) {
var root = this._roots[i];
if (root instanceof Group) {
root.delChildrenFromStorage(this);
}
}
this._elements = {};
this._hoverElements = [];
this._roots = [];
this._shapeList = [];
this._shapeListOffset = 0;
return;
}
if (elId instanceof Array) {
for (var i = 0, l = elId.length; i < l; i++) {
this.delRoot(elId[i]);
}
return;
}
var el;
if (typeof(elId) == 'string') {
el = this._elements[elId];
}
else {
el = elId;
}
var idx = util.indexOf(this._roots, el);
if (idx >= 0) {
this.delFromMap(el.id);
this._roots.splice(idx, 1);
if (el instanceof Group) {
el.delChildrenFromStorage(this);
}
}
};
Storage.prototype.addToMap = function (el) {
if (el instanceof Group) {
el._storage = this;
}
el.modSelf();
this._elements[el.id] = el;
return this;
};
Storage.prototype.get = function (elId) {
return this._elements[elId];
};
Storage.prototype.delFromMap = function (elId) {
var el = this._elements[elId];
if (el) {
delete this._elements[elId];
if (el instanceof Group) {
el._storage = null;
}
}
return this;
};
/**
* 清空并且释放Storage
*/
Storage.prototype.dispose = function () {
this._elements =
this._renderList =
this._roots =
this._hoverElements = null;
};
return Storage;
}
);