| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 | var util = require("./core/util");var env = require("./core/env");var Group = require("./container/Group");var timsort = require("./core/timsort");// Use timsort because in most case elements are partially sorted// https://jsfiddle.net/pissang/jr4x7mdm/8/function shapeCompareFunc(a, b) {  if (a.zlevel === b.zlevel) {    if (a.z === b.z) {      // if (a.z2 === b.z2) {      //     // FIXME Slow has renderidx compare      //     // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement      //     // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012      //     return a.__renderidx - b.__renderidx;      // }      return a.z2 - b.z2;    }    return a.z - b.z;  }  return a.zlevel - b.zlevel;}/** * 内容仓库 (M) * @alias module:zrender/Storage * @constructor */var Storage = function () {  // jshint ignore:line  this._roots = [];  this._displayList = [];  this._displayListLen = 0;};Storage.prototype = {  constructor: Storage,  /**   * @param  {Function} cb   *   */  traverse: function (cb, context) {    for (var i = 0; i < this._roots.length; i++) {      this._roots[i].traverse(cb, context);    }  },  /**   * 返回所有图形的绘制队列   * @param {boolean} [update=false] 是否在返回前更新该数组   * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效   *   * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList}   * @return {Array.<module:zrender/graphic/Displayable>}   */  getDisplayList: function (update, includeIgnore) {    includeIgnore = includeIgnore || false;    if (update) {      this.updateDisplayList(includeIgnore);    }    return this._displayList;  },  /**   * 更新图形的绘制队列。   * 每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中,   * 最后根据绘制的优先级(zlevel > z > 插入顺序)排序得到绘制队列   * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组   */  updateDisplayList: function (includeIgnore) {    this._displayListLen = 0;    var roots = this._roots;    var displayList = this._displayList;    for (var i = 0, len = roots.length; i < len; i++) {      this._updateAndAddDisplayable(roots[i], null, includeIgnore);    }    displayList.length = this._displayListLen;    env.canvasSupported && timsort(displayList, shapeCompareFunc);  },  _updateAndAddDisplayable: function (el, clipPaths, includeIgnore) {    if (el.ignore && !includeIgnore) {      return;    }    el.beforeUpdate();    if (el.__dirty) {      el.update();    }    el.afterUpdate();    var userSetClipPath = el.clipPath;    if (userSetClipPath) {      // FIXME 效率影响      if (clipPaths) {        clipPaths = clipPaths.slice();      } else {        clipPaths = [];      }      var currentClipPath = userSetClipPath;      var parentClipPath = el; // Recursively add clip path      while (currentClipPath) {        // clipPath 的变换是基于使用这个 clipPath 的元素        currentClipPath.parent = parentClipPath;        currentClipPath.updateTransform();        clipPaths.push(currentClipPath);        parentClipPath = currentClipPath;        currentClipPath = currentClipPath.clipPath;      }    }    if (el.isGroup) {      var children = el._children;      for (var i = 0; i < children.length; i++) {        var child = children[i]; // Force to mark as dirty if group is dirty        // FIXME __dirtyPath ?        if (el.__dirty) {          child.__dirty = true;        }        this._updateAndAddDisplayable(child, clipPaths, includeIgnore);      } // Mark group clean here      el.__dirty = false;    } else {      el.__clipPaths = clipPaths;      this._displayList[this._displayListLen++] = el;    }  },  /**   * 添加图形(Shape)或者组(Group)到根节点   * @param {module:zrender/Element} el   */  addRoot: function (el) {    if (el.__storage === this) {      return;    }    if (el instanceof Group) {      el.addChildrenToStorage(this);    }    this.addToStorage(el);    this._roots.push(el);  },  /**   * 删除指定的图形(Shape)或者组(Group)   * @param {string|Array.<string>} [el] 如果为空清空整个Storage   */  delRoot: function (el) {    if (el == null) {      // 不指定el清空      for (var i = 0; i < this._roots.length; i++) {        var root = this._roots[i];        if (root instanceof Group) {          root.delChildrenFromStorage(this);        }      }      this._roots = [];      this._displayList = [];      this._displayListLen = 0;      return;    }    if (el instanceof Array) {      for (var i = 0, l = el.length; i < l; i++) {        this.delRoot(el[i]);      }      return;    }    var idx = util.indexOf(this._roots, el);    if (idx >= 0) {      this.delFromStorage(el);      this._roots.splice(idx, 1);      if (el instanceof Group) {        el.delChildrenFromStorage(this);      }    }  },  addToStorage: function (el) {    if (el) {      el.__storage = this;      el.dirty(false);    }    return this;  },  delFromStorage: function (el) {    if (el) {      el.__storage = null;    }    return this;  },  /**   * 清空并且释放Storage   */  dispose: function () {    this._renderList = this._roots = null;  },  displayableSortFunc: shapeCompareFunc};var _default = Storage;module.exports = _default;
 |