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;