You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
398 lines
14 KiB
398 lines
14 KiB
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;
|
|
|