@mapgis/webclient-es6-mapboxgl
Version:
477 lines (421 loc) • 14.9 kB
JavaScript
import { Common } from '@mapgis/webclient-es6-service';
const { Zondy, indexOf, merge } = Common;
import {Group} from './Group';
/**
* @private
* @class Zondy.LevelRenderer.Storage
* @classdesc 内容(图像)仓库 (M) 。
*/
class Storage {
/**
* @function Zondy.LevelRenderer.Storage.constructor
* @description 构造函数。
*/
constructor() {
/**
* @member {Object} Zondy.LevelRenderer.Storage.prototype._elements
* @description 所有常规形状,id 索引的 map。
*/
this._elements = {};
/**
* @member {Array} Zondy.LevelRenderer.Storage.prototype._hoverElements
* @description 高亮层形状,不稳定,动态增删,数组位置也是 z 轴方向,靠前显示在下方。
*
*/
this._hoverElements = [];
/**
* @member {Array} Zondy.LevelRenderer.Storage.prototype._roots
* @description _roots。
*
*/
this._roots = [];
/**
* @member {Array} Zondy.LevelRenderer.Storage.prototype._shapeList
* @description _shapeList。
*
*/
this._shapeList = [];
/**
* @member {number} Zondy.LevelRenderer.Storage.prototype._shapeListOffset
* @description _shapeListOffset。默认值:0。
*
*/
this._shapeListOffset = 0;
this.CLASS_NAME = "Zondy.LevelRenderer.Storage";
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.destroy
* @description 销毁对象,释放资源。调用此函数后所有属性将被置为 null。
*/
destroy() {
this.dispose();
this._shapeList = null;
this._shapeListOffset = null;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.iterShape
* @description 遍历迭代器。
*
* @param {Function} fun - 迭代回调函数,return true终止迭代。
* @param {Object} option - 迭代参数,缺省为仅降序遍历普通层图形。
* @param {boolean} [hover=true] - 是否是高亮层图形。
* @param {string} [normal='down'] - 是否是普通层图形,迭代时是否指定及z轴顺序。可设值:'down' ,'up'。
* @param {boolean} [update=false] - 是否在迭代前更新形状列表。
* @return {Zondy.LevelRenderer.Storage} this。
*/
iterShape(fun, option) {
if (!option) {
var defaultIterateOption = {
hover: false,
normal: 'down',
update: false
};
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': {
// 降序遍历,高层优先
let l = this._shapeList.length;
while (l--) {
if (fun(this._shapeList[l])) {
return this;
}
}
break;
}
// case 'up':
default: {
// 升序遍历,底层优先
for (let i = 0, l = this._shapeList.length; i < l; i++) {
if (fun(this._shapeList[i])) {
return this;
}
}
break;
}
}
return this;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.getHoverShapes
* @param {boolean} [update=false] - 是否在返回前更新图形的变换。
* @return {Array.<Zondy.LevelRenderer.Shape>} 图形数组。
*/
getHoverShapes(update) {
// hoverConnect
var hoverElements = [],
len = this._hoverElements.length;
for (let i = 0; i < len; 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(Storage.shapeCompareFunc);
if (update) {
for (let i = 0, l = hoverElements.length; i < l; i++) {
hoverElements[i].updateTransform();
}
}
return hoverElements;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.getShapeList
* @description 返回所有图形的绘制队列。
*
* @param {boolean} [update=false] - 是否在返回前更新该数组。 详见:<Zondy.LevelRenderer.Shape> updateShapeList。
* @return {Zondy.LevelRenderer.Shape} 图形。
*/
getShapeList(update) {
if (update) {
this.updateShapeList();
}
return this._shapeList;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.updateShapeList
* @description 更新图形的绘制队列。每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中,最后根据绘制的优先级(zlevel > z > 插入顺序)排序得到绘制队列。
*/
updateShapeList() {
this._shapeListOffset = 0;
var rootsLen = this._roots.length;
for (let i = 0; i < rootsLen; i++) {
let root = this._roots[i];
this._updateAndAddShape(root);
}
this._shapeList.length = this._shapeListOffset;
var shapeListLen = this._shapeList.length;
for (let i = 0; i < shapeListLen; i++) {
this._shapeList[i].__renderidx = i;
}
this._shapeList.sort(Storage.shapeCompareFunc);
}
/**
* @function Zondy.LevelRenderer.Storage.prototype._updateAndAddShape
* @description 更新并添加图形。
*/
_updateAndAddShape(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;
}
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.mod
* @description 修改图形(Shape)或者组(Group)。
*
* @param {string} elId - 唯一标识。
* @param {Object} params - 参数。
* @return {Zondy.LevelRenderer.Storage} this。
*/
mod(elId, params) {
var el = this._elements[elId];
if (el) {
el.modSelf();
if (params) {
// 如果第二个参数直接使用 shape
// parent, _storage, __startClip 三个属性会有循环引用
if (params.parent || params._storage || params.__startClip) {
var target = {};
for (var name in params) {
if (
name === 'parent'
|| name === '_storage'
|| name === '__startClip'
) {
continue;
}
if (params.hasOwnProperty(name)) {
target[name] = params[name];
}
}
merge(el, target, true);
} else {
merge(el, params, true);
}
}
}
return this;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.drift
* @description 移动指定的图形(Shape)的位置。
* @param {string} shapeId - 唯一标识。
* @param {number} dx
* @param {number} dy
* @return {Zondy.LevelRenderer.Storage} this。
*/
drift(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;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.addHover
* @description 添加高亮层数据。
* @param {Zondy.LevelRenderer.Shape} shape - 图形。
* @return {Zondy.LevelRenderer.Storage} this。
*/
addHover(shape) {
shape.updateNeedTransform();
this._hoverElements.push(shape);
return this;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.delHover
* @description 清空高亮层数据。
* @return {Zondy.LevelRenderer.Storage} this。
*/
delHover() {
this._hoverElements = [];
return this;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.hasHoverShape
* @description 是否有图形在高亮层里。
* @return {boolean} 是否有图形在高亮层里。
*/
hasHoverShape() {
return this._hoverElements.length > 0;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.addRoot
* @description 添加图形(Shape)或者组(Group)到根节点。
*
* @param {(Zondy.LevelRenderer.Shape/Zondy.LevelRenderer.Group)} el - 图形。
*
*/
addRoot(el) {
if (el instanceof Group) {
el.addChildrenToStorage(this);
}
this.addToMap(el);
this._roots.push(el);
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.delRoot
* @description 删除指定的图形(Shape)或者组(Group)。
*
* @param {Array.<string>} elId - 删除图形(Shape)或者组(Group)的 id 数组。如果为空清空整个Storage。
*
*/
delRoot(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 = [];
return;
}
if (elId instanceof Array) {
var elIdLen = elId.length;
for (let i = 0; i < elIdLen; i++) {
this.delRoot(elId[i]);
}
return;
}
var el;
if (typeof (elId) == 'string') {
el = this._elements[elId];
} else {
el = elId;
}
var idx = indexOf(this._roots, el);
if (idx >= 0) {
this.delFromMap(el.id);
this._roots.splice(idx, 1);
if (el instanceof Group) {
el.delChildrenFromStorage(this);
}
}
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.addToMap
* @description 添加图形到 map。
*
* @param {Zondy.LevelRenderer.Shape} el - 图形。
* @return {Zondy.LevelRenderer.Storage} this。
*/
addToMap(el) {
if (el instanceof Group) {
el._storage = this;
}
el.modSelf();
this._elements[el.id] = el;
return this;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.get
* @description 获取指定图形。
*
* @param {string} elId - 图形 id。
* @return {Zondy.LevelRenderer.Shape} 图形。
*/
get(elId) {
return this._elements[elId];
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.delFromMap
* @description 从 map 中删除指定图形。
*
* @param {string} elId - 图形id。
* @return {Zondy.LevelRenderer.Storage} this。
*/
delFromMap(elId) {
var el = this._elements[elId];
if (el) {
delete this._elements[elId];
if (el instanceof Group) {
el._storage = null;
}
}
return this;
}
/**
* @function Zondy.LevelRenderer.Storage.prototype.dispose
* @description 清空并且释放 Storage。
*/
dispose() {
this._elements = null;
// this._renderList = null;
this._roots = null;
this._hoverElements = null;
}
static 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;
}
}
export {Storage};
Zondy.LevelRenderer.Storage = Storage;