first commit

This commit is contained in:
jefferyzhao
2025-07-31 17:44:12 +08:00
commit b9bdc8598b
42390 changed files with 4467935 additions and 0 deletions

156
node_modules/zrender/lib/svg/helper/ClippathManager.js generated vendored Normal file
View File

@ -0,0 +1,156 @@
var Definable = require("./Definable");
var zrUtil = require("../../core/util");
var matrix = require("../../core/matrix");
/**
* @file Manages SVG clipPath elements.
* @author Zhang Wenli
*/
/**
* Manages SVG clipPath elements.
*
* @class
* @extends Definable
* @param {number} zrId zrender instance id
* @param {SVGElement} svgRoot root of SVG document
*/
function ClippathManager(zrId, svgRoot) {
Definable.call(this, zrId, svgRoot, 'clipPath', '__clippath_in_use__');
}
zrUtil.inherits(ClippathManager, Definable);
/**
* Update clipPath.
*
* @param {Displayable} displayable displayable element
*/
ClippathManager.prototype.update = function (displayable) {
var svgEl = this.getSvgElement(displayable);
if (svgEl) {
this.updateDom(svgEl, displayable.__clipPaths, false);
}
var textEl = this.getTextSvgElement(displayable);
if (textEl) {
// Make another clipPath for text, since it's transform
// matrix is not the same with svgElement
this.updateDom(textEl, displayable.__clipPaths, true);
}
this.markUsed(displayable);
};
/**
* Create an SVGElement of displayable and create a <clipPath> of its
* clipPath
*
* @param {Displayable} parentEl parent element
* @param {ClipPath[]} clipPaths clipPaths of parent element
* @param {boolean} isText if parent element is Text
*/
ClippathManager.prototype.updateDom = function (parentEl, clipPaths, isText) {
if (clipPaths && clipPaths.length > 0) {
// Has clipPath, create <clipPath> with the first clipPath
var defs = this.getDefs(true);
var clipPath = clipPaths[0];
var clipPathEl;
var id;
var dom = isText ? '_textDom' : '_dom';
if (clipPath[dom]) {
// Use a dom that is already in <defs>
id = clipPath[dom].getAttribute('id');
clipPathEl = clipPath[dom]; // Use a dom that is already in <defs>
if (!defs.contains(clipPathEl)) {
// This happens when set old clipPath that has
// been previously removed
defs.appendChild(clipPathEl);
}
} else {
// New <clipPath>
id = 'zr' + this._zrId + '-clip-' + this.nextId;
++this.nextId;
clipPathEl = this.createElement('clipPath');
clipPathEl.setAttribute('id', id);
defs.appendChild(clipPathEl);
clipPath[dom] = clipPathEl;
} // Build path and add to <clipPath>
var svgProxy = this.getSvgProxy(clipPath);
if (clipPath.transform && clipPath.parent.invTransform && !isText) {
/**
* If a clipPath has a parent with transform, the transform
* of parent should not be considered when setting transform
* of clipPath. So we need to transform back from parent's
* transform, which is done by multiplying parent's inverse
* transform.
*/
// Store old transform
var transform = Array.prototype.slice.call(clipPath.transform); // Transform back from parent, and brush path
matrix.mul(clipPath.transform, clipPath.parent.invTransform, clipPath.transform);
svgProxy.brush(clipPath); // Set back transform of clipPath
clipPath.transform = transform;
} else {
svgProxy.brush(clipPath);
}
var pathEl = this.getSvgElement(clipPath);
clipPathEl.innerHTML = '';
/**
* Use `cloneNode()` here to appendChild to multiple parents,
* which may happend when Text and other shapes are using the same
* clipPath. Since Text will create an extra clipPath DOM due to
* different transform rules.
*/
clipPathEl.appendChild(pathEl.cloneNode());
parentEl.setAttribute('clip-path', 'url(#' + id + ')');
if (clipPaths.length > 1) {
// Make the other clipPaths recursively
this.updateDom(clipPathEl, clipPaths.slice(1), isText);
}
} else {
// No clipPath
if (parentEl) {
parentEl.setAttribute('clip-path', 'none');
}
}
};
/**
* Mark a single clipPath to be used
*
* @param {Displayable} displayable displayable element
*/
ClippathManager.prototype.markUsed = function (displayable) {
var that = this; // displayable.__clipPaths can only be `null`/`undefined` or an non-empty array.
if (displayable.__clipPaths) {
zrUtil.each(displayable.__clipPaths, function (clipPath) {
if (clipPath._dom) {
Definable.prototype.markUsed.call(that, clipPath._dom);
}
if (clipPath._textDom) {
Definable.prototype.markUsed.call(that, clipPath._textDom);
}
});
}
};
var _default = ClippathManager;
module.exports = _default;

266
node_modules/zrender/lib/svg/helper/Definable.js generated vendored Normal file
View File

@ -0,0 +1,266 @@
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;

208
node_modules/zrender/lib/svg/helper/GradientManager.js generated vendored Normal file
View File

@ -0,0 +1,208 @@
var Definable = require("./Definable");
var zrUtil = require("../../core/util");
var logError = require("../../core/log");
var colorTool = require("../../tool/color");
/**
* @file Manages SVG gradient elements.
* @author Zhang Wenli
*/
/**
* Manages SVG gradient elements.
*
* @class
* @extends Definable
* @param {number} zrId zrender instance id
* @param {SVGElement} svgRoot root of SVG document
*/
function GradientManager(zrId, svgRoot) {
Definable.call(this, zrId, svgRoot, ['linearGradient', 'radialGradient'], '__gradient_in_use__');
}
zrUtil.inherits(GradientManager, Definable);
/**
* Create new gradient DOM for fill or stroke if not exist,
* but will not update gradient if exists.
*
* @param {SvgElement} svgElement SVG element to paint
* @param {Displayable} displayable zrender displayable element
*/
GradientManager.prototype.addWithoutUpdate = function (svgElement, displayable) {
if (displayable && displayable.style) {
var that = this;
zrUtil.each(['fill', 'stroke'], function (fillOrStroke) {
if (displayable.style[fillOrStroke] && (displayable.style[fillOrStroke].type === 'linear' || displayable.style[fillOrStroke].type === 'radial')) {
var gradient = displayable.style[fillOrStroke];
var defs = that.getDefs(true); // Create dom in <defs> if not exists
var dom;
if (gradient._dom) {
// Gradient exists
dom = gradient._dom;
if (!defs.contains(gradient._dom)) {
// _dom is no longer in defs, recreate
that.addDom(dom);
}
} else {
// New dom
dom = that.add(gradient);
}
that.markUsed(displayable);
var id = dom.getAttribute('id');
svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')');
}
});
}
};
/**
* Add a new gradient tag in <defs>
*
* @param {Gradient} gradient zr gradient instance
* @return {SVGLinearGradientElement | SVGRadialGradientElement}
* created DOM
*/
GradientManager.prototype.add = function (gradient) {
var dom;
if (gradient.type === 'linear') {
dom = this.createElement('linearGradient');
} else if (gradient.type === 'radial') {
dom = this.createElement('radialGradient');
} else {
logError('Illegal gradient type.');
return null;
} // Set dom id with gradient id, since each gradient instance
// will have no more than one dom element.
// id may exists before for those dirty elements, in which case
// id should remain the same, and other attributes should be
// updated.
gradient.id = gradient.id || this.nextId++;
dom.setAttribute('id', 'zr' + this._zrId + '-gradient-' + gradient.id);
this.updateDom(gradient, dom);
this.addDom(dom);
return dom;
};
/**
* Update gradient.
*
* @param {Gradient} gradient zr gradient instance
*/
GradientManager.prototype.update = function (gradient) {
var that = this;
Definable.prototype.update.call(this, gradient, function () {
var type = gradient.type;
var tagName = gradient._dom.tagName;
if (type === 'linear' && tagName === 'linearGradient' || type === 'radial' && tagName === 'radialGradient') {
// Gradient type is not changed, update gradient
that.updateDom(gradient, gradient._dom);
} else {
// Remove and re-create if type is changed
that.removeDom(gradient);
that.add(gradient);
}
});
};
/**
* Update gradient dom
*
* @param {Gradient} gradient zr gradient instance
* @param {SVGLinearGradientElement | SVGRadialGradientElement} dom
* DOM to update
*/
GradientManager.prototype.updateDom = function (gradient, dom) {
if (gradient.type === 'linear') {
dom.setAttribute('x1', gradient.x);
dom.setAttribute('y1', gradient.y);
dom.setAttribute('x2', gradient.x2);
dom.setAttribute('y2', gradient.y2);
} else if (gradient.type === 'radial') {
dom.setAttribute('cx', gradient.x);
dom.setAttribute('cy', gradient.y);
dom.setAttribute('r', gradient.r);
} else {
logError('Illegal gradient type.');
return;
}
if (gradient.global) {
// x1, x2, y1, y2 in range of 0 to canvas width or height
dom.setAttribute('gradientUnits', 'userSpaceOnUse');
} else {
// x1, x2, y1, y2 in range of 0 to 1
dom.setAttribute('gradientUnits', 'objectBoundingBox');
} // Remove color stops if exists
dom.innerHTML = ''; // Add color stops
var colors = gradient.colorStops;
for (var i = 0, len = colors.length; i < len; ++i) {
var stop = this.createElement('stop');
stop.setAttribute('offset', colors[i].offset * 100 + '%');
var color = colors[i].color;
if (color.indexOf('rgba') > -1) {
// Fix Safari bug that stop-color not recognizing alpha #9014
var opacity = colorTool.parse(color)[3];
var hex = colorTool.toHex(color); // stop-color cannot be color, since:
// The opacity value used for the gradient calculation is the
// *product* of the value of stop-opacity and the opacity of the
// value of stop-color.
// See https://www.w3.org/TR/SVG2/pservers.html#StopOpacityProperty
stop.setAttribute('stop-color', '#' + hex);
stop.setAttribute('stop-opacity', opacity);
} else {
stop.setAttribute('stop-color', colors[i].color);
}
dom.appendChild(stop);
} // Store dom element in gradient, to avoid creating multiple
// dom instances for the same gradient element
gradient._dom = dom;
};
/**
* Mark a single gradient to be used
*
* @param {Displayable} displayable displayable element
*/
GradientManager.prototype.markUsed = function (displayable) {
if (displayable.style) {
var gradient = displayable.style.fill;
if (gradient && gradient._dom) {
Definable.prototype.markUsed.call(this, gradient._dom);
}
gradient = displayable.style.stroke;
if (gradient && gradient._dom) {
Definable.prototype.markUsed.call(this, gradient._dom);
}
}
};
var _default = GradientManager;
module.exports = _default;

187
node_modules/zrender/lib/svg/helper/ShadowManager.js generated vendored Normal file
View File

@ -0,0 +1,187 @@
var Definable = require("./Definable");
var zrUtil = require("../../core/util");
/**
* @file Manages SVG shadow elements.
* @author Zhang Wenli
*/
/**
* Manages SVG shadow elements.
*
* @class
* @extends Definable
* @param {number} zrId zrender instance id
* @param {SVGElement} svgRoot root of SVG document
*/
function ShadowManager(zrId, svgRoot) {
Definable.call(this, zrId, svgRoot, ['filter'], '__filter_in_use__', '_shadowDom');
}
zrUtil.inherits(ShadowManager, Definable);
/**
* Create new shadow DOM for fill or stroke if not exist,
* but will not update shadow if exists.
*
* @param {SvgElement} svgElement SVG element to paint
* @param {Displayable} displayable zrender displayable element
*/
ShadowManager.prototype.addWithoutUpdate = function (svgElement, displayable) {
if (displayable && hasShadow(displayable.style)) {
// Create dom in <defs> if not exists
var dom;
if (displayable._shadowDom) {
// Gradient exists
dom = displayable._shadowDom;
var defs = this.getDefs(true);
if (!defs.contains(displayable._shadowDom)) {
// _shadowDom is no longer in defs, recreate
this.addDom(dom);
}
} else {
// New dom
dom = this.add(displayable);
}
this.markUsed(displayable);
var id = dom.getAttribute('id');
svgElement.style.filter = 'url(#' + id + ')';
}
};
/**
* Add a new shadow tag in <defs>
*
* @param {Displayable} displayable zrender displayable element
* @return {SVGFilterElement} created DOM
*/
ShadowManager.prototype.add = function (displayable) {
var dom = this.createElement('filter'); // Set dom id with shadow id, since each shadow instance
// will have no more than one dom element.
// id may exists before for those dirty elements, in which case
// id should remain the same, and other attributes should be
// updated.
displayable._shadowDomId = displayable._shadowDomId || this.nextId++;
dom.setAttribute('id', 'zr' + this._zrId + '-shadow-' + displayable._shadowDomId);
this.updateDom(displayable, dom);
this.addDom(dom);
return dom;
};
/**
* Update shadow.
*
* @param {Displayable} displayable zrender displayable element
*/
ShadowManager.prototype.update = function (svgElement, displayable) {
var style = displayable.style;
if (hasShadow(style)) {
var that = this;
Definable.prototype.update.call(this, displayable, function () {
that.updateDom(displayable, displayable._shadowDom);
});
} else {
// Remove shadow
this.remove(svgElement, displayable);
}
};
/**
* Remove DOM and clear parent filter
*/
ShadowManager.prototype.remove = function (svgElement, displayable) {
if (displayable._shadowDomId != null) {
this.removeDom(svgElement);
svgElement.style.filter = '';
}
};
/**
* Update shadow dom
*
* @param {Displayable} displayable zrender displayable element
* @param {SVGFilterElement} dom DOM to update
*/
ShadowManager.prototype.updateDom = function (displayable, dom) {
var domChild = dom.getElementsByTagName('feDropShadow');
if (domChild.length === 0) {
domChild = this.createElement('feDropShadow');
} else {
domChild = domChild[0];
}
var style = displayable.style;
var scaleX = displayable.scale ? displayable.scale[0] || 1 : 1;
var scaleY = displayable.scale ? displayable.scale[1] || 1 : 1; // TODO: textBoxShadowBlur is not supported yet
var offsetX;
var offsetY;
var blur;
var color;
if (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY) {
offsetX = style.shadowOffsetX || 0;
offsetY = style.shadowOffsetY || 0;
blur = style.shadowBlur;
color = style.shadowColor;
} else if (style.textShadowBlur) {
offsetX = style.textShadowOffsetX || 0;
offsetY = style.textShadowOffsetY || 0;
blur = style.textShadowBlur;
color = style.textShadowColor;
} else {
// Remove shadow
this.removeDom(dom, style);
return;
}
domChild.setAttribute('dx', offsetX / scaleX);
domChild.setAttribute('dy', offsetY / scaleY);
domChild.setAttribute('flood-color', color); // Divide by two here so that it looks the same as in canvas
// See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur
var stdDx = blur / 2 / scaleX;
var stdDy = blur / 2 / scaleY;
var stdDeviation = stdDx + ' ' + stdDy;
domChild.setAttribute('stdDeviation', stdDeviation); // Fix filter clipping problem
dom.setAttribute('x', '-100%');
dom.setAttribute('y', '-100%');
dom.setAttribute('width', Math.ceil(blur / 2 * 200) + '%');
dom.setAttribute('height', Math.ceil(blur / 2 * 200) + '%');
dom.appendChild(domChild); // Store dom element in shadow, to avoid creating multiple
// dom instances for the same shadow element
displayable._shadowDom = dom;
};
/**
* Mark a single shadow to be used
*
* @param {Displayable} displayable displayable element
*/
ShadowManager.prototype.markUsed = function (displayable) {
if (displayable._shadowDom) {
Definable.prototype.markUsed.call(this, displayable._shadowDom);
}
};
function hasShadow(style) {
// TODO: textBoxShadowBlur is not supported yet
return style && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY || style.textShadowBlur || style.textShadowOffsetX || style.textShadowOffsetY);
}
var _default = ShadowManager;
module.exports = _default;