123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- var _core = require("../core");
- var createElement = _core.createElement;
- var zrUtil = require("../../core/util");
- var Path = require("../../graphic/Path");
- var ZImage = require("../../graphic/Image");
- var ZText = require("../../graphic/Text");
- var _graphic = require("../graphic");
- var svgPath = _graphic.path;
- var svgImage = _graphic.image;
- var svgText = _graphic.text;
- /**
- * @file Manages elements that can be defined in <defs> in SVG,
- * e.g., gradients, clip path, etc.
- * @author Zhang Wenli
- */
- var MARK_UNUSED = '0';
- var MARK_USED = '1';
- /**
- * Manages elements that can be defined in <defs> in SVG,
- * e.g., gradients, clip path, etc.
- *
- * @class
- * @param {number} zrId zrender instance id
- * @param {SVGElement} svgRoot root of SVG document
- * @param {string|string[]} tagNames possible tag names
- * @param {string} markLabel label name to make if the element
- * is used
- */
- function Definable(zrId, svgRoot, tagNames, markLabel, domName) {
- this._zrId = zrId;
- this._svgRoot = svgRoot;
- this._tagNames = typeof tagNames === 'string' ? [tagNames] : tagNames;
- this._markLabel = markLabel;
- this._domName = domName || '_dom';
- this.nextId = 0;
- }
- Definable.prototype.createElement = createElement;
- /**
- * Get the <defs> tag for svgRoot; optionally creates one if not exists.
- *
- * @param {boolean} isForceCreating if need to create when not exists
- * @return {SVGDefsElement} SVG <defs> element, null if it doesn't
- * exist and isForceCreating is false
- */
- Definable.prototype.getDefs = function (isForceCreating) {
- var svgRoot = this._svgRoot;
- var defs = this._svgRoot.getElementsByTagName('defs');
- if (defs.length === 0) {
- // Not exist
- if (isForceCreating) {
- defs = svgRoot.insertBefore(this.createElement('defs'), // Create new tag
- svgRoot.firstChild // Insert in the front of svg
- );
- if (!defs.contains) {
- // IE doesn't support contains method
- defs.contains = function (el) {
- var children = defs.children;
- if (!children) {
- return false;
- }
- for (var i = children.length - 1; i >= 0; --i) {
- if (children[i] === el) {
- return true;
- }
- }
- return false;
- };
- }
- return defs;
- } else {
- return null;
- }
- } else {
- return defs[0];
- }
- };
- /**
- * Update DOM element if necessary.
- *
- * @param {Object|string} element style element. e.g., for gradient,
- * it may be '#ccc' or {type: 'linear', ...}
- * @param {Function|undefined} onUpdate update callback
- */
- Definable.prototype.update = function (element, onUpdate) {
- if (!element) {
- return;
- }
- var defs = this.getDefs(false);
- if (element[this._domName] && defs.contains(element[this._domName])) {
- // Update DOM
- if (typeof onUpdate === 'function') {
- onUpdate(element);
- }
- } else {
- // No previous dom, create new
- var dom = this.add(element);
- if (dom) {
- element[this._domName] = dom;
- }
- }
- };
- /**
- * Add gradient dom to defs
- *
- * @param {SVGElement} dom DOM to be added to <defs>
- */
- Definable.prototype.addDom = function (dom) {
- var defs = this.getDefs(true);
- defs.appendChild(dom);
- };
- /**
- * Remove DOM of a given element.
- *
- * @param {SVGElement} element element to remove dom
- */
- Definable.prototype.removeDom = function (element) {
- var defs = this.getDefs(false);
- if (defs && element[this._domName]) {
- defs.removeChild(element[this._domName]);
- element[this._domName] = null;
- }
- };
- /**
- * Get DOMs of this element.
- *
- * @return {HTMLDomElement} doms of this defineable elements in <defs>
- */
- Definable.prototype.getDoms = function () {
- var defs = this.getDefs(false);
- if (!defs) {
- // No dom when defs is not defined
- return [];
- }
- var doms = [];
- zrUtil.each(this._tagNames, function (tagName) {
- var tags = defs.getElementsByTagName(tagName); // Note that tags is HTMLCollection, which is array-like
- // rather than real array.
- // So `doms.concat(tags)` add tags as one object.
- doms = doms.concat([].slice.call(tags));
- });
- return doms;
- };
- /**
- * Mark DOMs to be unused before painting, and clear unused ones at the end
- * of the painting.
- */
- Definable.prototype.markAllUnused = function () {
- var doms = this.getDoms();
- var that = this;
- zrUtil.each(doms, function (dom) {
- dom[that._markLabel] = MARK_UNUSED;
- });
- };
- /**
- * Mark a single DOM to be used.
- *
- * @param {SVGElement} dom DOM to mark
- */
- Definable.prototype.markUsed = function (dom) {
- if (dom) {
- dom[this._markLabel] = MARK_USED;
- }
- };
- /**
- * Remove unused DOMs defined in <defs>
- */
- Definable.prototype.removeUnused = function () {
- var defs = this.getDefs(false);
- if (!defs) {
- // Nothing to remove
- return;
- }
- var doms = this.getDoms();
- var that = this;
- zrUtil.each(doms, function (dom) {
- if (dom[that._markLabel] !== MARK_USED) {
- // Remove gradient
- defs.removeChild(dom);
- }
- });
- };
- /**
- * Get SVG proxy.
- *
- * @param {Displayable} displayable displayable element
- * @return {Path|Image|Text} svg proxy of given element
- */
- Definable.prototype.getSvgProxy = function (displayable) {
- if (displayable instanceof Path) {
- return svgPath;
- } else if (displayable instanceof ZImage) {
- return svgImage;
- } else if (displayable instanceof ZText) {
- return svgText;
- } else {
- return svgPath;
- }
- };
- /**
- * Get text SVG element.
- *
- * @param {Displayable} displayable displayable element
- * @return {SVGElement} SVG element of text
- */
- Definable.prototype.getTextSvgElement = function (displayable) {
- return displayable.__textSvgEl;
- };
- /**
- * Get SVG element.
- *
- * @param {Displayable} displayable displayable element
- * @return {SVGElement} SVG element
- */
- Definable.prototype.getSvgElement = function (displayable) {
- return displayable.__svgEl;
- };
- var _default = Definable;
- module.exports = _default;
|