|
@@ -1,212 +0,0 @@
|
|
-/**
|
|
|
|
- * @file Manages SVG shadow elements.
|
|
|
|
- * @author Zhang Wenli
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
-import Definable from './Definable';
|
|
|
|
-import * as zrUtil from '../../core/util';
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * 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)) {
|
|
|
|
- var style = displayable.style;
|
|
|
|
-
|
|
|
|
- // Create dom in <defs> if not exists
|
|
|
|
- var dom;
|
|
|
|
- if (style._shadowDom) {
|
|
|
|
- // Gradient exists
|
|
|
|
- dom = style._shadowDom;
|
|
|
|
-
|
|
|
|
- var defs = this.getDefs(true);
|
|
|
|
- if (!defs.contains(style._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');
|
|
|
|
- var style = displayable.style;
|
|
|
|
-
|
|
|
|
- // 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.
|
|
|
|
- style._shadowDomId = style._shadowDomId || this.nextId++;
|
|
|
|
- dom.setAttribute('id', 'zr' + this._zrId
|
|
|
|
- + '-shadow-' + style._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 (style) {
|
|
|
|
- that.updateDom(displayable, style._shadowDom);
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- // Remove shadow
|
|
|
|
- this.remove(svgElement, style);
|
|
|
|
- }
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * Remove DOM and clear parent filter
|
|
|
|
- */
|
|
|
|
-ShadowManager.prototype.remove = function (svgElement, style) {
|
|
|
|
- if (style._shadowDomId != null) {
|
|
|
|
- this.removeDom(style);
|
|
|
|
- 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, offsetY, blur, 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
|
|
|
|
- style._shadowDom = dom;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * Mark a single shadow to be used
|
|
|
|
- *
|
|
|
|
- * @param {Displayable} displayable displayable element
|
|
|
|
- */
|
|
|
|
-ShadowManager.prototype.markUsed = function (displayable) {
|
|
|
|
- var style = displayable.style;
|
|
|
|
- if (style && style._shadowDom) {
|
|
|
|
- Definable.prototype.markUsed.call(this, style._shadowDom);
|
|
|
|
- }
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-function hasShadow(style) {
|
|
|
|
- // TODO: textBoxShadowBlur is not supported yet
|
|
|
|
- return style
|
|
|
|
- && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY
|
|
|
|
- || style.textShadowBlur || style.textShadowOffsetX
|
|
|
|
- || style.textShadowOffsetY);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-export default ShadowManager;
|
|
|