399 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			399 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
import { __extends } from "tslib";
 | 
						|
import Displayable, { DEFAULT_COMMON_STYLE, DEFAULT_COMMON_ANIMATION_PROPS } from './Displayable.js';
 | 
						|
import PathProxy from '../core/PathProxy.js';
 | 
						|
import * as pathContain from '../contain/path.js';
 | 
						|
import { defaults, keys, extend, clone, isString, createObject } from '../core/util.js';
 | 
						|
import { lum } from '../tool/color.js';
 | 
						|
import { DARK_LABEL_COLOR, LIGHT_LABEL_COLOR, DARK_MODE_THRESHOLD, LIGHTER_LABEL_COLOR } from '../config.js';
 | 
						|
import { REDRAW_BIT, SHAPE_CHANGED_BIT, STYLE_CHANGED_BIT } from './constants.js';
 | 
						|
import { TRANSFORMABLE_PROPS } from '../core/Transformable.js';
 | 
						|
export var DEFAULT_PATH_STYLE = defaults({
 | 
						|
    fill: '#000',
 | 
						|
    stroke: null,
 | 
						|
    strokePercent: 1,
 | 
						|
    fillOpacity: 1,
 | 
						|
    strokeOpacity: 1,
 | 
						|
    lineDashOffset: 0,
 | 
						|
    lineWidth: 1,
 | 
						|
    lineCap: 'butt',
 | 
						|
    miterLimit: 10,
 | 
						|
    strokeNoScale: false,
 | 
						|
    strokeFirst: false
 | 
						|
}, DEFAULT_COMMON_STYLE);
 | 
						|
export var DEFAULT_PATH_ANIMATION_PROPS = {
 | 
						|
    style: defaults({
 | 
						|
        fill: true,
 | 
						|
        stroke: true,
 | 
						|
        strokePercent: true,
 | 
						|
        fillOpacity: true,
 | 
						|
        strokeOpacity: true,
 | 
						|
        lineDashOffset: true,
 | 
						|
        lineWidth: true,
 | 
						|
        miterLimit: true
 | 
						|
    }, DEFAULT_COMMON_ANIMATION_PROPS.style)
 | 
						|
};
 | 
						|
var pathCopyParams = TRANSFORMABLE_PROPS.concat(['invisible',
 | 
						|
    'culling', 'z', 'z2', 'zlevel', 'parent'
 | 
						|
]);
 | 
						|
var Path = (function (_super) {
 | 
						|
    __extends(Path, _super);
 | 
						|
    function Path(opts) {
 | 
						|
        return _super.call(this, opts) || this;
 | 
						|
    }
 | 
						|
    Path.prototype.update = function () {
 | 
						|
        var _this = this;
 | 
						|
        _super.prototype.update.call(this);
 | 
						|
        var style = this.style;
 | 
						|
        if (style.decal) {
 | 
						|
            var decalEl = this._decalEl = this._decalEl || new Path();
 | 
						|
            if (decalEl.buildPath === Path.prototype.buildPath) {
 | 
						|
                decalEl.buildPath = function (ctx) {
 | 
						|
                    _this.buildPath(ctx, _this.shape);
 | 
						|
                };
 | 
						|
            }
 | 
						|
            decalEl.silent = true;
 | 
						|
            var decalElStyle = decalEl.style;
 | 
						|
            for (var key in style) {
 | 
						|
                if (decalElStyle[key] !== style[key]) {
 | 
						|
                    decalElStyle[key] = style[key];
 | 
						|
                }
 | 
						|
            }
 | 
						|
            decalElStyle.fill = style.fill ? style.decal : null;
 | 
						|
            decalElStyle.decal = null;
 | 
						|
            decalElStyle.shadowColor = null;
 | 
						|
            style.strokeFirst && (decalElStyle.stroke = null);
 | 
						|
            for (var i = 0; i < pathCopyParams.length; ++i) {
 | 
						|
                decalEl[pathCopyParams[i]] = this[pathCopyParams[i]];
 | 
						|
            }
 | 
						|
            decalEl.__dirty |= REDRAW_BIT;
 | 
						|
        }
 | 
						|
        else if (this._decalEl) {
 | 
						|
            this._decalEl = null;
 | 
						|
        }
 | 
						|
    };
 | 
						|
    Path.prototype.getDecalElement = function () {
 | 
						|
        return this._decalEl;
 | 
						|
    };
 | 
						|
    Path.prototype._init = function (props) {
 | 
						|
        var keysArr = keys(props);
 | 
						|
        this.shape = this.getDefaultShape();
 | 
						|
        var defaultStyle = this.getDefaultStyle();
 | 
						|
        if (defaultStyle) {
 | 
						|
            this.useStyle(defaultStyle);
 | 
						|
        }
 | 
						|
        for (var i = 0; i < keysArr.length; i++) {
 | 
						|
            var key = keysArr[i];
 | 
						|
            var value = props[key];
 | 
						|
            if (key === 'style') {
 | 
						|
                if (!this.style) {
 | 
						|
                    this.useStyle(value);
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    extend(this.style, value);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else if (key === 'shape') {
 | 
						|
                extend(this.shape, value);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                _super.prototype.attrKV.call(this, key, value);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (!this.style) {
 | 
						|
            this.useStyle({});
 | 
						|
        }
 | 
						|
    };
 | 
						|
    Path.prototype.getDefaultStyle = function () {
 | 
						|
        return null;
 | 
						|
    };
 | 
						|
    Path.prototype.getDefaultShape = function () {
 | 
						|
        return {};
 | 
						|
    };
 | 
						|
    Path.prototype.canBeInsideText = function () {
 | 
						|
        return this.hasFill();
 | 
						|
    };
 | 
						|
    Path.prototype.getInsideTextFill = function () {
 | 
						|
        var pathFill = this.style.fill;
 | 
						|
        if (pathFill !== 'none') {
 | 
						|
            if (isString(pathFill)) {
 | 
						|
                var fillLum = lum(pathFill, 0);
 | 
						|
                if (fillLum > 0.5) {
 | 
						|
                    return DARK_LABEL_COLOR;
 | 
						|
                }
 | 
						|
                else if (fillLum > 0.2) {
 | 
						|
                    return LIGHTER_LABEL_COLOR;
 | 
						|
                }
 | 
						|
                return LIGHT_LABEL_COLOR;
 | 
						|
            }
 | 
						|
            else if (pathFill) {
 | 
						|
                return LIGHT_LABEL_COLOR;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return DARK_LABEL_COLOR;
 | 
						|
    };
 | 
						|
    Path.prototype.getInsideTextStroke = function (textFill) {
 | 
						|
        var pathFill = this.style.fill;
 | 
						|
        if (isString(pathFill)) {
 | 
						|
            var zr = this.__zr;
 | 
						|
            var isDarkMode = !!(zr && zr.isDarkMode());
 | 
						|
            var isDarkLabel = lum(textFill, 0) < DARK_MODE_THRESHOLD;
 | 
						|
            if (isDarkMode === isDarkLabel) {
 | 
						|
                return pathFill;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    };
 | 
						|
    Path.prototype.buildPath = function (ctx, shapeCfg, inBatch) { };
 | 
						|
    Path.prototype.pathUpdated = function () {
 | 
						|
        this.__dirty &= ~SHAPE_CHANGED_BIT;
 | 
						|
    };
 | 
						|
    Path.prototype.getUpdatedPathProxy = function (inBatch) {
 | 
						|
        !this.path && this.createPathProxy();
 | 
						|
        this.path.beginPath();
 | 
						|
        this.buildPath(this.path, this.shape, inBatch);
 | 
						|
        return this.path;
 | 
						|
    };
 | 
						|
    Path.prototype.createPathProxy = function () {
 | 
						|
        this.path = new PathProxy(false);
 | 
						|
    };
 | 
						|
    Path.prototype.hasStroke = function () {
 | 
						|
        var style = this.style;
 | 
						|
        var stroke = style.stroke;
 | 
						|
        return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0));
 | 
						|
    };
 | 
						|
    Path.prototype.hasFill = function () {
 | 
						|
        var style = this.style;
 | 
						|
        var fill = style.fill;
 | 
						|
        return fill != null && fill !== 'none';
 | 
						|
    };
 | 
						|
    Path.prototype.getBoundingRect = function () {
 | 
						|
        var rect = this._rect;
 | 
						|
        var style = this.style;
 | 
						|
        var needsUpdateRect = !rect;
 | 
						|
        if (needsUpdateRect) {
 | 
						|
            var firstInvoke = false;
 | 
						|
            if (!this.path) {
 | 
						|
                firstInvoke = true;
 | 
						|
                this.createPathProxy();
 | 
						|
            }
 | 
						|
            var path = this.path;
 | 
						|
            if (firstInvoke || (this.__dirty & SHAPE_CHANGED_BIT)) {
 | 
						|
                path.beginPath();
 | 
						|
                this.buildPath(path, this.shape, false);
 | 
						|
                this.pathUpdated();
 | 
						|
            }
 | 
						|
            rect = path.getBoundingRect();
 | 
						|
        }
 | 
						|
        this._rect = rect;
 | 
						|
        if (this.hasStroke() && this.path && this.path.len() > 0) {
 | 
						|
            var rectStroke = this._rectStroke || (this._rectStroke = rect.clone());
 | 
						|
            if (this.__dirty || needsUpdateRect) {
 | 
						|
                rectStroke.copy(rect);
 | 
						|
                var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
 | 
						|
                var w = style.lineWidth;
 | 
						|
                if (!this.hasFill()) {
 | 
						|
                    var strokeContainThreshold = this.strokeContainThreshold;
 | 
						|
                    w = Math.max(w, strokeContainThreshold == null ? 4 : strokeContainThreshold);
 | 
						|
                }
 | 
						|
                if (lineScale > 1e-10) {
 | 
						|
                    rectStroke.width += w / lineScale;
 | 
						|
                    rectStroke.height += w / lineScale;
 | 
						|
                    rectStroke.x -= w / lineScale / 2;
 | 
						|
                    rectStroke.y -= w / lineScale / 2;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return rectStroke;
 | 
						|
        }
 | 
						|
        return rect;
 | 
						|
    };
 | 
						|
    Path.prototype.contain = function (x, y) {
 | 
						|
        var localPos = this.transformCoordToLocal(x, y);
 | 
						|
        var rect = this.getBoundingRect();
 | 
						|
        var style = this.style;
 | 
						|
        x = localPos[0];
 | 
						|
        y = localPos[1];
 | 
						|
        if (rect.contain(x, y)) {
 | 
						|
            var pathProxy = this.path;
 | 
						|
            if (this.hasStroke()) {
 | 
						|
                var lineWidth = style.lineWidth;
 | 
						|
                var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
 | 
						|
                if (lineScale > 1e-10) {
 | 
						|
                    if (!this.hasFill()) {
 | 
						|
                        lineWidth = Math.max(lineWidth, this.strokeContainThreshold);
 | 
						|
                    }
 | 
						|
                    if (pathContain.containStroke(pathProxy, lineWidth / lineScale, x, y)) {
 | 
						|
                        return true;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (this.hasFill()) {
 | 
						|
                return pathContain.contain(pathProxy, x, y);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    };
 | 
						|
    Path.prototype.dirtyShape = function () {
 | 
						|
        this.__dirty |= SHAPE_CHANGED_BIT;
 | 
						|
        if (this._rect) {
 | 
						|
            this._rect = null;
 | 
						|
        }
 | 
						|
        if (this._decalEl) {
 | 
						|
            this._decalEl.dirtyShape();
 | 
						|
        }
 | 
						|
        this.markRedraw();
 | 
						|
    };
 | 
						|
    Path.prototype.dirty = function () {
 | 
						|
        this.dirtyStyle();
 | 
						|
        this.dirtyShape();
 | 
						|
    };
 | 
						|
    Path.prototype.animateShape = function (loop) {
 | 
						|
        return this.animate('shape', loop);
 | 
						|
    };
 | 
						|
    Path.prototype.updateDuringAnimation = function (targetKey) {
 | 
						|
        if (targetKey === 'style') {
 | 
						|
            this.dirtyStyle();
 | 
						|
        }
 | 
						|
        else if (targetKey === 'shape') {
 | 
						|
            this.dirtyShape();
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            this.markRedraw();
 | 
						|
        }
 | 
						|
    };
 | 
						|
    Path.prototype.attrKV = function (key, value) {
 | 
						|
        if (key === 'shape') {
 | 
						|
            this.setShape(value);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            _super.prototype.attrKV.call(this, key, value);
 | 
						|
        }
 | 
						|
    };
 | 
						|
    Path.prototype.setShape = function (keyOrObj, value) {
 | 
						|
        var shape = this.shape;
 | 
						|
        if (!shape) {
 | 
						|
            shape = this.shape = {};
 | 
						|
        }
 | 
						|
        if (typeof keyOrObj === 'string') {
 | 
						|
            shape[keyOrObj] = value;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            extend(shape, keyOrObj);
 | 
						|
        }
 | 
						|
        this.dirtyShape();
 | 
						|
        return this;
 | 
						|
    };
 | 
						|
    Path.prototype.shapeChanged = function () {
 | 
						|
        return !!(this.__dirty & SHAPE_CHANGED_BIT);
 | 
						|
    };
 | 
						|
    Path.prototype.createStyle = function (obj) {
 | 
						|
        return createObject(DEFAULT_PATH_STYLE, obj);
 | 
						|
    };
 | 
						|
    Path.prototype._innerSaveToNormal = function (toState) {
 | 
						|
        _super.prototype._innerSaveToNormal.call(this, toState);
 | 
						|
        var normalState = this._normalState;
 | 
						|
        if (toState.shape && !normalState.shape) {
 | 
						|
            normalState.shape = extend({}, this.shape);
 | 
						|
        }
 | 
						|
    };
 | 
						|
    Path.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) {
 | 
						|
        _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg);
 | 
						|
        var needsRestoreToNormal = !(state && keepCurrentStates);
 | 
						|
        var targetShape;
 | 
						|
        if (state && state.shape) {
 | 
						|
            if (transition) {
 | 
						|
                if (keepCurrentStates) {
 | 
						|
                    targetShape = state.shape;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    targetShape = extend({}, normalState.shape);
 | 
						|
                    extend(targetShape, state.shape);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                targetShape = extend({}, keepCurrentStates ? this.shape : normalState.shape);
 | 
						|
                extend(targetShape, state.shape);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else if (needsRestoreToNormal) {
 | 
						|
            targetShape = normalState.shape;
 | 
						|
        }
 | 
						|
        if (targetShape) {
 | 
						|
            if (transition) {
 | 
						|
                this.shape = extend({}, this.shape);
 | 
						|
                var targetShapePrimaryProps = {};
 | 
						|
                var shapeKeys = keys(targetShape);
 | 
						|
                for (var i = 0; i < shapeKeys.length; i++) {
 | 
						|
                    var key = shapeKeys[i];
 | 
						|
                    if (typeof targetShape[key] === 'object') {
 | 
						|
                        this.shape[key] = targetShape[key];
 | 
						|
                    }
 | 
						|
                    else {
 | 
						|
                        targetShapePrimaryProps[key] = targetShape[key];
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                this._transitionState(stateName, {
 | 
						|
                    shape: targetShapePrimaryProps
 | 
						|
                }, animationCfg);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                this.shape = targetShape;
 | 
						|
                this.dirtyShape();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    };
 | 
						|
    Path.prototype._mergeStates = function (states) {
 | 
						|
        var mergedState = _super.prototype._mergeStates.call(this, states);
 | 
						|
        var mergedShape;
 | 
						|
        for (var i = 0; i < states.length; i++) {
 | 
						|
            var state = states[i];
 | 
						|
            if (state.shape) {
 | 
						|
                mergedShape = mergedShape || {};
 | 
						|
                this._mergeStyle(mergedShape, state.shape);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (mergedShape) {
 | 
						|
            mergedState.shape = mergedShape;
 | 
						|
        }
 | 
						|
        return mergedState;
 | 
						|
    };
 | 
						|
    Path.prototype.getAnimationStyleProps = function () {
 | 
						|
        return DEFAULT_PATH_ANIMATION_PROPS;
 | 
						|
    };
 | 
						|
    Path.prototype.isZeroArea = function () {
 | 
						|
        return false;
 | 
						|
    };
 | 
						|
    Path.extend = function (defaultProps) {
 | 
						|
        var Sub = (function (_super) {
 | 
						|
            __extends(Sub, _super);
 | 
						|
            function Sub(opts) {
 | 
						|
                var _this = _super.call(this, opts) || this;
 | 
						|
                defaultProps.init && defaultProps.init.call(_this, opts);
 | 
						|
                return _this;
 | 
						|
            }
 | 
						|
            Sub.prototype.getDefaultStyle = function () {
 | 
						|
                return clone(defaultProps.style);
 | 
						|
            };
 | 
						|
            Sub.prototype.getDefaultShape = function () {
 | 
						|
                return clone(defaultProps.shape);
 | 
						|
            };
 | 
						|
            return Sub;
 | 
						|
        }(Path));
 | 
						|
        for (var key in defaultProps) {
 | 
						|
            if (typeof defaultProps[key] === 'function') {
 | 
						|
                Sub.prototype[key] = defaultProps[key];
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return Sub;
 | 
						|
    };
 | 
						|
    Path.initDefaultProps = (function () {
 | 
						|
        var pathProto = Path.prototype;
 | 
						|
        pathProto.type = 'path';
 | 
						|
        pathProto.strokeContainThreshold = 5;
 | 
						|
        pathProto.segmentIgnoreThreshold = 0;
 | 
						|
        pathProto.subPixelOptimize = false;
 | 
						|
        pathProto.autoBatch = false;
 | 
						|
        pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT;
 | 
						|
    })();
 | 
						|
    return Path;
 | 
						|
}(Displayable));
 | 
						|
export default Path;
 |