@visactor/vrender-core
Version:
## Description
771 lines (746 loc) • 38.6 kB
JavaScript
import { isArray, max, OBBBounds } from "@visactor/vutils";
import { AABBBounds, Matrix, normalTransform, Point, isNil, has, isString, isValidUrl, isBase64, isObject } from "@visactor/vutils";
import { Node } from "./node-tree";
import { EventTarget, CustomEvent } from "../event";
import { DefaultTransform } from "./config";
import { application } from "../application";
import { Animate, DefaultStateAnimateConfig, defaultTimeline } from "../animate";
import { interpolateColor } from "../color-string/interpolate";
import { CustomPath2D } from "../common/custom-path2d";
import { ResourceLoader } from "../resource-loader/loader";
import { AttributeUpdateType, IContainPointMode, UpdateTag } from "../common/enums";
import { BoundsContext } from "../common/bounds-context";
import { renderCommandList } from "../common/render-command-list";
import { parsePadding } from "../common/utils";
import { builtinSymbolsMap, builtInSymbolStrMap, CustomSymbolClass } from "./builtin-symbol";
import { isSvg, XMLParser } from "../common/xml";
import { SVG_PARSE_ATTRIBUTE_MAP, SVG_PARSE_ATTRIBUTE_MAP_KEYS } from "./constants";
const _tempBounds = new AABBBounds, tempMatrix = new Matrix, tempBounds = new AABBBounds;
export const PURE_STYLE_KEY = [ "stroke", "opacity", "strokeOpacity", "lineDash", "lineDashOffset", "lineCap", "lineJoin", "miterLimit", "fill", "fillOpacity" ];
export const GRAPHIC_UPDATE_TAG_KEY = [ "lineWidth", "scaleX", "scaleY", "angle", "anchor", "visible" ];
const tempConstantXYKey = [ "x", "y" ], tempConstantScaleXYKey = [ "scaleX", "scaleY" ], tempConstantAngleKey = [ "angle" ], point = new Point;
export const NOWORK_ANIMATE_ATTR = {
strokeSeg: 1,
boundsPadding: 2,
pickMode: 1,
boundsMode: 1,
customPickShape: 1,
pickable: 1,
childrenPickable: 1,
visible: 1,
zIndex: 1,
layout: 1,
keepDirIn3d: 1,
globalZIndex: 1,
outerBorder: 1,
innerBorder: 1,
lineDash: 1,
lineCap: 1,
lineJoin: 1,
miterLimit: 2,
strokeBoundsBuffer: 2,
scaleCenter: 1,
anchor: 1,
anchor3d: 1,
postMatrix: 1,
backgroundMode: 2,
background: 1,
texture: 1,
cursor: 1,
html: 1
};
export class Graphic extends Node {
static mixin(source) {
const keys = Object.keys(source);
for (let i = 0; i < keys.length; ++i) {
const propertyName = keys[i];
Object.defineProperty(Graphic.prototype, propertyName, Object.getOwnPropertyDescriptor(source, propertyName));
}
}
get AABBBounds() {
return this.tryUpdateAABBBounds();
}
get OBBBounds() {
return this.tryUpdateOBBBounds();
}
get globalAABBBounds() {
return this.tryUpdateGlobalAABBBounds();
}
get transMatrix() {
return this.tryUpdateLocalTransMatrix(!0);
}
get globalTransMatrix() {
return this.tryUpdateGlobalTransMatrix(!0);
}
constructor(params = {}) {
var _a;
super(), this._AABBBounds = new AABBBounds, this._updateTag = UpdateTag.INIT, this.attribute = params,
this.valid = this.isValid(), this.updateAABBBoundsStamp = 0, params.background ? this.loadImage(null !== (_a = params.background.background) && void 0 !== _a ? _a : params.background, !0) : params.shadowGraphic && this.setShadowGraphic(params.shadowGraphic);
}
setMode(mode) {
"3d" === mode ? this.set3dMode() : this.set2dMode();
}
set3dMode() {
this.in3dMode = !0;
}
set2dMode() {
this.in3dMode = !1;
}
getOffsetXY(attr, includeScroll = !1) {
var _a, _b;
const {dx: dx = attr.dx, dy: dy = attr.dy} = this.attribute;
if (includeScroll && this.parent) {
const attribute = this.parent.attribute;
point.x = dx + (null !== (_a = attribute.scrollX) && void 0 !== _a ? _a : 0), point.y = dy + (null !== (_b = attribute.scrollY) && void 0 !== _b ? _b : 0);
} else point.x = dx, point.y = dy;
return point;
}
onAnimateBind(animate) {
this._emitCustomEvent("animate-bind", animate);
}
tryUpdateAABBBounds() {
const full = "imprecise" === this.attribute.boundsMode;
if (!this.shouldUpdateAABBBounds()) return this._AABBBounds;
if (!this.valid) return this._AABBBounds.clear(), this._AABBBounds;
application.graphicService.beforeUpdateAABBBounds(this, this.stage, !0, this._AABBBounds);
const bounds = this.doUpdateAABBBounds(full);
return application.graphicService.afterUpdateAABBBounds(this, this.stage, this._AABBBounds, this, !0),
"empty" === this.attribute.boundsMode && bounds.clear(), bounds;
}
tryUpdateOBBBounds() {
if (this._OBBBounds || (this._OBBBounds = new OBBBounds), this.tryUpdateAABBBounds(),
this.updateOBBBoundsStamp === this.updateAABBBoundsStamp) return this._OBBBounds;
if (this.updateOBBBoundsStamp = this.updateAABBBoundsStamp, !this.valid) return this._OBBBounds.clear(),
this._OBBBounds;
return this.doUpdateOBBBounds();
}
combindShadowAABBBounds(bounds) {
if (this.shadowRoot) {
const b = this.shadowRoot.AABBBounds.clone();
bounds.union(b);
}
}
doUpdateOBBBounds() {
return this._OBBBounds;
}
getClipPath() {
const {clipConfig: clipConfig} = this.attribute;
if (!clipConfig) return null;
this.clipPathMap || (this.clipPathMap = new Map);
const {shape: shape} = clipConfig;
let path = this.clipPathMap.get(shape) || null;
return path || (this.clipPathMap.size > 10 && this.clipPathMap.clear(), path = this.parsePath(shape),
path && this.clipPathMap.set(shape, path)), path;
}
parsePath(symbolType) {
if (!symbolType) return null;
let path = builtinSymbolsMap[symbolType];
if (path) return path;
if (path = Graphic.userSymbolMap[symbolType], path) return path;
const _symbolType = builtInSymbolStrMap[symbolType];
if (!0 === isSvg(symbolType = _symbolType || symbolType)) {
const parser = new XMLParser, {svg: svg} = parser.parse(symbolType);
if (!svg) return null;
const path = isArray(svg.path) ? svg.path : [ svg.path ];
_tempBounds.clear();
const cacheList = [];
path.forEach((item => {
const cache = (new CustomPath2D).fromString(item.d), attribute = {};
SVG_PARSE_ATTRIBUTE_MAP_KEYS.forEach((k => {
item[k] && (attribute[SVG_PARSE_ATTRIBUTE_MAP[k]] = item[k]);
})), cacheList.push({
path: cache,
attribute: attribute
}), _tempBounds.union(cache.bounds);
}));
const width = _tempBounds.width(), height = _tempBounds.height(), scale = 1 / max(width, height);
cacheList.forEach((cache => cache.path.transform(0, 0, scale, scale)));
const _parsedPath = new CustomSymbolClass(symbolType, cacheList, !0);
return Graphic.userSymbolMap[symbolType] = _parsedPath, _parsedPath;
}
const cache = (new CustomPath2D).fromString(symbolType), width = cache.bounds.width(), height = cache.bounds.height(), scale = 1 / max(width, height);
cache.transform(0, 0, scale, scale);
const _parsedPath = new CustomSymbolClass(symbolType, cache);
return Graphic.userSymbolMap[symbolType] = _parsedPath, _parsedPath;
}
doUpdateAABBBounds(full) {
this.updateAABBBoundsStamp++;
const graphicTheme = this.getGraphicTheme();
this._AABBBounds.clear();
const attribute = this.attribute, bounds = this.updateAABBBounds(attribute, graphicTheme, this._AABBBounds, full), {boundsPadding: boundsPadding = graphicTheme.boundsPadding} = attribute, paddingArray = parsePadding(boundsPadding);
return paddingArray && bounds.expand(paddingArray), this.clearUpdateBoundTag(),
bounds;
}
updatePathProxyAABBBounds(aabbBounds) {
const path = "function" == typeof this.pathProxy ? this.pathProxy(this.attribute) : this.pathProxy;
if (!path) return !1;
const boundsContext = new BoundsContext(aabbBounds);
return renderCommandList(path.commandList, boundsContext, 0, 0), !0;
}
tryUpdateGlobalAABBBounds() {
const b = this.AABBBounds;
return this._globalAABBBounds ? this._globalAABBBounds.setValue(b.x1, b.y1, b.x2, b.y2) : this._globalAABBBounds = b.clone(),
this._globalAABBBounds.empty() || this.parent && this._globalAABBBounds.transformWithMatrix(this.parent.globalTransMatrix),
this._globalAABBBounds;
}
tryUpdateGlobalTransMatrix(clearTag = !0) {
if (this._globalTransMatrix) {
if (this.parent) {
const m = this.parent.globalTransMatrix;
this._globalTransMatrix.setValue(m.a, m.b, m.c, m.d, m.e, m.f);
}
} else this._globalTransMatrix = this.parent ? this.parent.globalTransMatrix.clone() : this.transMatrix.clone();
return this.shouldUpdateGlobalMatrix() && this.doUpdateGlobalMatrix(), this._globalTransMatrix;
}
shouldUpdateGlobalMatrix() {
return !0;
}
tryUpdateLocalTransMatrix(clearTag = !0) {
return this._transMatrix || (this._transMatrix = new Matrix), this.shouldUpdateLocalMatrix() && (this.doUpdateLocalMatrix(),
clearTag && this.clearUpdateLocalPositionTag()), this._transMatrix;
}
shouldUpdateAABBBounds() {
return this.shadowRoot ? (!!(this._updateTag & UpdateTag.UPDATE_BOUNDS) || this.shadowRoot.shouldUpdateAABBBounds()) && application.graphicService.validCheck(this.attribute, this.getGraphicTheme(), this._AABBBounds, this) : !!(this._updateTag & UpdateTag.UPDATE_BOUNDS) && application.graphicService.validCheck(this.attribute, this.getGraphicTheme(), this._AABBBounds, this);
}
shouldSelfChangeUpdateAABBBounds() {
return this.shadowRoot ? !!(this._updateTag & UpdateTag.UPDATE_BOUNDS) || this.shadowRoot.shouldUpdateAABBBounds() : !!(this._updateTag & UpdateTag.UPDATE_BOUNDS);
}
shouldUpdateLocalMatrix() {
return !!(this._updateTag & UpdateTag.UPDATE_LOCAL_MATRIX);
}
isValid() {
var _a, _b;
const attribute = this.attribute;
return Number.isFinite((null !== (_a = attribute.x) && void 0 !== _a ? _a : 0) + (null !== (_b = attribute.y) && void 0 !== _b ? _b : 0));
}
_validNumber(num) {
return null == num || Number.isFinite(num);
}
shouldUpdateShape() {
return !!(this._updateTag & UpdateTag.UPDATE_SHAPE);
}
clearUpdateShapeTag() {
this._updateTag &= UpdateTag.CLEAR_SHAPE;
}
containsPoint(x, y, mode, picker) {
if (!picker) return !1;
if (mode === IContainPointMode.GLOBAL) {
const point = new Point(x, y);
this.parent && this.parent.globalTransMatrix.transformPoint(point, point), x = point.x,
y = point.y;
}
return picker.containsPoint(this, {
x: x,
y: y
});
}
setAttributes(params, forceUpdateTag = !1, context) {
(params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate(params, this.attribute, null, context) || params).background ? this.loadImage(params.background, !0) : params.shadowGraphic && this.setShadowGraphic(params.shadowGraphic),
this._setAttributes(params, forceUpdateTag, context);
}
_setAttributes(params, forceUpdateTag = !1, context) {
const keys = Object.keys(params);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
this.attribute[key] = params[key];
}
this.valid = this.isValid(), this.updateShapeAndBoundsTagSetted() || !forceUpdateTag && !this.needUpdateTags(keys) ? this.addUpdateBoundTag() : this.addUpdateShapeAndBoundsTag(),
this.addUpdatePositionTag(), this.addUpdateLayoutTag(), this.onAttributeUpdate(context);
}
setAttribute(key, value, forceUpdateTag, context) {
var _a;
const params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate({
[key]: value
}, this.attribute, key, context);
params ? this._setAttributes(params, forceUpdateTag, context) : isNil(null === (_a = this.normalAttrs) || void 0 === _a ? void 0 : _a[key]) ? (this.attribute[key] = value,
this.valid = this.isValid(), this.updateShapeAndBoundsTagSetted() || !forceUpdateTag && !this.needUpdateTag(key) ? this.addUpdateBoundTag() : this.addUpdateShapeAndBoundsTag(),
this.addUpdatePositionTag(), this.addUpdateLayoutTag(), this.onAttributeUpdate(context)) : this.normalAttrs[key] = value,
"background" === key ? this.loadImage(value, !0) : "shadowGraphic" === key && this.setShadowGraphic(value);
}
needUpdateTags(keys, k = GRAPHIC_UPDATE_TAG_KEY) {
for (let i = 0; i < k.length; i++) {
const attrKey = k[i];
if (-1 !== keys.indexOf(attrKey)) return !0;
}
return !1;
}
needUpdateTag(key, k = GRAPHIC_UPDATE_TAG_KEY) {
for (let i = 0; i < k.length; i++) {
if (key === k[i]) return !0;
}
return !1;
}
initAttributes(params) {
const context = {
type: AttributeUpdateType.INIT
};
params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate(params, this.attribute, null, context) || params,
this.attribute = params, params.background ? this.loadImage(params.background, !0) : params.shadowGraphic && this.setShadowGraphic(params.shadowGraphic),
this._updateTag = UpdateTag.INIT, this.valid = this.isValid(), this.onAttributeUpdate(context);
}
translate(x, y) {
var _a, _b;
if (0 === x && 0 === y) return this;
const context = {
type: AttributeUpdateType.TRANSLATE
}, params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate({
x: x,
y: y
}, this.attribute, tempConstantXYKey, context);
params && (x = params.x, y = params.y, delete params.x, delete params.y, this._setAttributes(params));
const attribute = this.attribute, postMatrix = attribute.postMatrix;
return postMatrix ? application.transformUtil.fromMatrix(postMatrix, postMatrix).translate(x, y) : (attribute.x = (null !== (_a = attribute.x) && void 0 !== _a ? _a : DefaultTransform.x) + x,
attribute.y = (null !== (_b = attribute.y) && void 0 !== _b ? _b : DefaultTransform.y) + y),
this.addUpdatePositionTag(), this.addUpdateBoundTag(), this.addUpdateLayoutTag(),
this.onAttributeUpdate(context), this;
}
translateTo(x, y) {
const attribute = this.attribute;
if (attribute.x === x && attribute.y === y) return this;
const context = {
type: AttributeUpdateType.TRANSLATE_TO
}, params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate({
x: x,
y: y
}, this.attribute, tempConstantXYKey, context);
return params ? (this._setAttributes(params, !1, context), this) : (attribute.x = x,
attribute.y = y, this.addUpdatePositionTag(), this.addUpdateBoundTag(), this.addUpdateLayoutTag(),
this.onAttributeUpdate(context), this);
}
scale(scaleX, scaleY, scaleCenter) {
var _a, _b;
if (1 === scaleX && 1 === scaleY) return this;
const context = {
type: AttributeUpdateType.SCALE
}, params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate({
scaleX: scaleX,
scaleY: scaleY,
scaleCenter: scaleCenter
}, this.attribute, tempConstantScaleXYKey, context);
params && (scaleX = params.scaleX, scaleY = params.scaleY, delete params.scaleX,
delete params.scaleY, this._setAttributes(params));
const attribute = this.attribute;
if (scaleCenter) {
let {postMatrix: postMatrix} = this.attribute;
postMatrix || (postMatrix = new Matrix, attribute.postMatrix = postMatrix), application.transformUtil.fromMatrix(postMatrix, postMatrix).scale(scaleX, scaleY, scaleCenter);
} else attribute.scaleX = (null !== (_a = attribute.scaleX) && void 0 !== _a ? _a : DefaultTransform.scaleX) * scaleX,
attribute.scaleY = (null !== (_b = attribute.scaleY) && void 0 !== _b ? _b : DefaultTransform.scaleY) * scaleY;
return this.addUpdatePositionTag(), this.addUpdateBoundTag(), this.addUpdateLayoutTag(),
this.onAttributeUpdate(context), this;
}
scaleTo(scaleX, scaleY) {
const attribute = this.attribute;
if (attribute.scaleX === scaleX && attribute.scaleY === scaleY) return this;
const context = {
type: AttributeUpdateType.SCALE_TO
}, params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate({
scaleX: scaleX,
scaleY: scaleY
}, this.attribute, tempConstantScaleXYKey, context);
return params ? (this._setAttributes(params, !1, context), this) : (attribute.scaleX = scaleX,
attribute.scaleY = scaleY, this.addUpdatePositionTag(), this.addUpdateBoundTag(),
this.addUpdateLayoutTag(), this.onAttributeUpdate(context), this);
}
rotate(angle, rotateCenter) {
var _a;
if (0 === angle) return this;
const context = {
type: AttributeUpdateType.ROTATE
}, params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate({
angle: angle,
rotateCenter: rotateCenter
}, this.attribute, tempConstantAngleKey, context);
params && (delete params.angle, this._setAttributes(params, !1, context));
const attribute = this.attribute;
if (rotateCenter) {
let {postMatrix: postMatrix} = this.attribute;
postMatrix || (postMatrix = new Matrix, attribute.postMatrix = postMatrix), application.transformUtil.fromMatrix(postMatrix, postMatrix).rotate(angle, rotateCenter);
} else attribute.angle = (null !== (_a = attribute.angle) && void 0 !== _a ? _a : DefaultTransform.angle) + angle;
return this.addUpdatePositionTag(), this.addUpdateBoundTag(), this.addUpdateLayoutTag(),
this.onAttributeUpdate(context), this;
}
rotateTo(angle) {
const attribute = this.attribute;
if (attribute.angle === angle) return this;
const context = {
type: AttributeUpdateType.ROTATE_TO
}, params = this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate(angle, this.attribute, tempConstantAngleKey, context);
return params ? (this._setAttributes(params, !1, context), this) : (attribute.angle = angle,
this.addUpdatePositionTag(), this.addUpdateBoundTag(), this.addUpdateLayoutTag(),
this.onAttributeUpdate(context), this);
}
skewTo(b, c) {
return this;
}
animate(params) {
var _a;
this.animates || (this.animates = new Map);
const animate = new Animate(null == params ? void 0 : params.id, null !== (_a = null == params ? void 0 : params.timeline) && void 0 !== _a ? _a : this.stage && this.stage.getTimeline(), null == params ? void 0 : params.slience);
if (animate.bind(this), params) {
const {onStart: onStart, onFrame: onFrame, onEnd: onEnd, onRemove: onRemove} = params;
null != onStart && animate.onStart(onStart), null != onFrame && animate.onFrame(onFrame),
null != onEnd && animate.onEnd(onEnd), null != onRemove && animate.onRemove(onRemove),
animate.interpolateFunc = params.interpolate;
}
return this.animates.set(animate.id, animate), animate.onRemove((() => {
animate.stop(), this.animates.delete(animate.id);
})), animate;
}
onAttributeUpdate(context) {
context && context.skipUpdateCallback || (application.graphicService.onAttributeUpdate(this),
this._emitCustomEvent("afterAttributeUpdate", context));
}
update(d) {
d ? (d.bounds && this.tryUpdateAABBBounds(), d.trans && this.tryUpdateLocalTransMatrix()) : (this.tryUpdateAABBBounds(),
this.tryUpdateLocalTransMatrix());
}
hasState(stateName) {
return !(!this.currentStates || !this.currentStates.length) && (!!isNil(stateName) || this.currentStates.includes(stateName));
}
getState(stateName) {
var _a;
return null === (_a = this.states) || void 0 === _a ? void 0 : _a[stateName];
}
applyStateAttrs(attrs, stateNames, hasAnimation, isClear) {
var _a, _b, _c, _d;
if (hasAnimation) {
const keys = Object.keys(attrs), noWorkAttrs = this.getNoWorkAnimateAttr(), animateAttrs = {};
let noAnimateAttrs;
keys.forEach((key => {
noWorkAttrs[key] ? (noAnimateAttrs || (noAnimateAttrs = {}), noAnimateAttrs[key] = attrs[key]) : animateAttrs[key] = isClear && void 0 === attrs[key] ? this.getDefaultAttribute(key) : attrs[key];
}));
const animate = this.animate({
slience: !0
});
animate.stateNames = stateNames, animate.to(animateAttrs, null !== (_b = null === (_a = this.stateAnimateConfig) || void 0 === _a ? void 0 : _a.duration) && void 0 !== _b ? _b : DefaultStateAnimateConfig.duration, null !== (_d = null === (_c = this.stateAnimateConfig) || void 0 === _c ? void 0 : _c.easing) && void 0 !== _d ? _d : DefaultStateAnimateConfig.easing),
noAnimateAttrs && this.setAttributes(noAnimateAttrs, !1, {
type: AttributeUpdateType.STATE
});
} else this.stopStateAnimates(), this.setAttributes(attrs, !1, {
type: AttributeUpdateType.STATE
});
}
updateNormalAttrs(stateAttrs) {
const newNormalAttrs = {};
this.normalAttrs ? (Object.keys(stateAttrs).forEach((key => {
key in this.normalAttrs ? (newNormalAttrs[key] = this.normalAttrs[key], delete this.normalAttrs[key]) : newNormalAttrs[key] = this.getNormalAttribute(key);
})), Object.keys(this.normalAttrs).forEach((key => {
stateAttrs[key] = this.normalAttrs[key];
}))) : Object.keys(stateAttrs).forEach((key => {
newNormalAttrs[key] = this.getNormalAttribute(key);
})), this.normalAttrs = newNormalAttrs;
}
stopStateAnimates(type = "end") {
this.animates && this.animates.forEach((animate => {
animate.stateNames && (animate.stop(type), this.animates.delete(animate.id));
}));
}
getNormalAttribute(key) {
let value = this.attribute[key];
return this.animates && this.animates.forEach((animate => {
if (animate.stateNames) {
const endProps = animate.getEndProps();
has(endProps, key) && (value = endProps[key]);
}
})), value;
}
clearStates(hasAnimation) {
this.hasState() && this.normalAttrs ? (this.currentStates = [], this.applyStateAttrs(this.normalAttrs, this.currentStates, hasAnimation, !0)) : this.currentStates = [],
this.normalAttrs = null;
}
removeState(stateName, hasAnimation) {
if (this.currentStates) {
const filter = isArray(stateName) ? s => !stateName.includes(s) : s => s !== stateName, newStates = this.currentStates.filter(filter);
newStates.length !== this.currentStates.length && this.useStates(newStates, hasAnimation);
}
}
toggleState(stateName, hasAnimation) {
if (this.hasState(stateName)) this.removeState(stateName, hasAnimation); else {
if ((this.currentStates ? this.currentStates.indexOf(stateName) : -1) < 0) {
const nextStates = this.currentStates ? this.currentStates.slice() : [];
nextStates.push(stateName), this.useStates(nextStates, hasAnimation);
}
}
}
addState(stateName, keepCurrentStates, hasAnimation) {
var _a;
if (this.currentStates && this.currentStates.includes(stateName) && (keepCurrentStates || 1 === this.currentStates.length)) return;
const newStates = keepCurrentStates && (null === (_a = this.currentStates) || void 0 === _a ? void 0 : _a.length) ? this.currentStates.concat([ stateName ]) : [ stateName ];
this.useStates(newStates, hasAnimation);
}
useStates(states, hasAnimation) {
var _a;
if (!states.length) return void this.clearStates(hasAnimation);
if (!((null === (_a = this.currentStates) || void 0 === _a ? void 0 : _a.length) !== states.length || states.some(((stateName, index) => this.currentStates[index] !== stateName)))) return;
const stateAttrs = {};
states.forEach((stateName => {
var _a;
const attrs = this.stateProxy ? this.stateProxy(stateName, states) : null === (_a = this.states) || void 0 === _a ? void 0 : _a[stateName];
attrs && Object.assign(stateAttrs, attrs);
})), this.updateNormalAttrs(stateAttrs), this.currentStates = states, this.applyStateAttrs(stateAttrs, states, hasAnimation);
}
addUpdateBoundTag() {
this._updateTag |= UpdateTag.UPDATE_BOUNDS, this.parent && this.parent.addChildUpdateBoundTag(),
this.glyphHost && this.glyphHost.addUpdateBoundTag();
}
addUpdateShapeTag() {
this._updateTag |= UpdateTag.UPDATE_SHAPE;
}
addUpdateShapeAndBoundsTag() {
this._updateTag |= UpdateTag.UPDATE_SHAPE_AND_BOUNDS, this.parent && this.parent.addChildUpdateBoundTag(),
this.glyphHost && this.glyphHost.addUpdateBoundTag();
}
updateShapeAndBoundsTagSetted() {
return (this._updateTag & UpdateTag.UPDATE_SHAPE_AND_BOUNDS) === UpdateTag.UPDATE_SHAPE_AND_BOUNDS;
}
clearUpdateBoundTag() {
this._updateTag &= UpdateTag.CLEAR_BOUNDS;
}
addUpdatePositionTag() {
this.shadowRoot && this.shadowRoot.addUpdateGlobalPositionTag(), this._updateTag |= UpdateTag.UPDATE_GLOBAL_LOCAL_MATRIX;
}
addUpdateGlobalPositionTag() {
this.shadowRoot && this.shadowRoot.addUpdateGlobalPositionTag(), this._updateTag |= UpdateTag.UPDATE_GLOBAL_MATRIX;
}
clearUpdateLocalPositionTag() {
this._updateTag &= UpdateTag.CLEAR_LOCAL_MATRIX;
}
clearUpdateGlobalPositionTag() {
this._updateTag &= UpdateTag.CLEAR_GLOBAL_MATRIX;
}
addUpdateLayoutTag() {
this._updateTag |= UpdateTag.UPDATE_LAYOUT;
}
clearUpdateLayoutTag() {
this._updateTag &= UpdateTag.CLEAR_LAYOUT;
}
needUpdateLayout() {
return !!(this._updateTag & UpdateTag.UPDATE_LAYOUT);
}
getAnchor(anchor, params) {
const _anchor = [ 0, 0 ], getBounds = () => {
if (params.b) return params.b;
const {scaleX: scaleX, scaleY: scaleY, angle: angle} = this.attribute;
return tempBounds.copy(this._AABBBounds), this.setAttributes({
scaleX: 1,
scaleY: 1,
angle: 0
}), params.b = this.AABBBounds.clone(), this._AABBBounds.copy(tempBounds), this.setAttributes({
scaleX: scaleX,
scaleY: scaleY,
angle: angle
}), params.b;
};
if ("string" == typeof anchor[0]) {
const ratio = parseFloat(anchor[0]) / 100, bounds = getBounds();
_anchor[0] = bounds.x1 + (bounds.x2 - bounds.x1) * ratio;
} else _anchor[0] = anchor[0];
if ("string" == typeof anchor[1]) {
const ratio = parseFloat(anchor[1]) / 100, bounds = getBounds();
_anchor[1] = bounds.y1 + (bounds.y2 - bounds.y1) * ratio;
} else _anchor[1] = anchor[1];
return _anchor;
}
doUpdateLocalMatrix() {
const {x: x = DefaultTransform.x, y: y = DefaultTransform.y, scaleX: scaleX = DefaultTransform.scaleX, scaleY: scaleY = DefaultTransform.scaleY, angle: angle = DefaultTransform.angle, scaleCenter: scaleCenter, anchor: anchor, postMatrix: postMatrix} = this.attribute;
let _anchor = [ 0, 0 ];
const params = {};
if (anchor && (_anchor = this.getAnchor(anchor, params)), !scaleCenter || 1 === scaleX && 1 === scaleY) normalTransform(this._transMatrix, this._transMatrix.reset(), x, y, scaleX, scaleY, angle, anchor && _anchor); else {
const m = this._transMatrix;
m.reset(), m.translate(_anchor[0], _anchor[1]), m.rotate(angle), m.translate(-_anchor[0], -_anchor[1]),
m.translate(x, y), _anchor = this.getAnchor(scaleCenter, params), application.transformUtil.fromMatrix(m, m).scale(scaleX, scaleY, {
x: _anchor[0],
y: _anchor[1]
});
}
const p = this.getOffsetXY(DefaultTransform);
if (this._transMatrix.e += p.x, this._transMatrix.f += p.y, postMatrix) {
const m1 = tempMatrix.setValue(postMatrix.a, postMatrix.b, postMatrix.c, postMatrix.d, postMatrix.e, postMatrix.f), m2 = this._transMatrix;
m1.multiply(m2.a, m2.b, m2.c, m2.d, m2.e, m2.f), m2.setValue(m1.a, m1.b, m1.c, m1.d, m1.e, m1.f);
}
}
doUpdateGlobalMatrix() {
if (this.parent) {
this._globalTransMatrix.multiply(this.transMatrix.a, this.transMatrix.b, this.transMatrix.c, this.transMatrix.d, this.transMatrix.e, this.transMatrix.f);
const {scrollX: scrollX = 0, scrollY: scrollY = 0} = this.parent.attribute;
this._globalTransMatrix.translate(scrollX, scrollY);
}
}
setStage(stage, layer) {
if (this.stage !== stage) {
if (this.stage = stage, this.layer = layer, this.setStageToShadowRoot(stage, layer),
this.animates && this.animates.size) {
const timeline = stage.getTimeline();
this.animates.forEach((a => {
a.timeline === defaultTimeline && a.setTimeline(timeline);
}));
}
this._onSetStage && this._onSetStage(this, stage, layer), application.graphicService.onSetStage(this, stage);
}
}
setStageToShadowRoot(stage, layer) {
this.shadowRoot && this.shadowRoot.setStage(stage, layer);
}
onAddStep(step) {}
onStop(props) {
props && this.setAttributes(props, !1, {
type: AttributeUpdateType.ANIMATE_END
});
}
onStep(subAnimate, animate, step, ratio, end) {
const nextAttributes = {};
if (step.customAnimate) step.customAnimate.update(end, ratio, nextAttributes); else {
const nextProps = step.props, nextParsedProps = step.parsedProps, propKeys = step.propKeys;
this.stepInterpolate(subAnimate, animate, nextAttributes, step, ratio, end, nextProps, void 0, nextParsedProps, propKeys);
}
this.setAttributes(nextAttributes, !1, {
type: AttributeUpdateType.ANIMATE_UPDATE,
animationState: {
ratio: ratio,
end: end,
step: step,
isFirstFrameOfStep: subAnimate.getLastStep() !== step
}
}), this.stage && this.stage.renderNextFrame();
}
stepInterpolate(subAnimate, animate, nextAttributes, step, ratio, end, nextProps, lastProps, nextParsedProps, propKeys) {
propKeys || (propKeys = Object.keys(nextProps), step.propKeys = propKeys), end ? step.propKeys.forEach((key => {
animate.validAttr(key) && (nextAttributes[key] = nextProps[key]);
})) : propKeys.forEach((key => {
var _a;
if (!animate.validAttr(key)) return;
const nextStepVal = nextProps[key], lastStepVal = null !== (_a = lastProps && lastProps[key]) && void 0 !== _a ? _a : subAnimate.getLastPropByName(key, step);
if (null == nextStepVal || null == lastStepVal || nextStepVal === lastStepVal) return void (nextAttributes[key] = nextStepVal);
let match;
match = animate.interpolateFunc && animate.interpolateFunc(key, ratio, lastStepVal, nextStepVal, nextAttributes),
match || (match = animate.customInterpolate(key, ratio, lastStepVal, nextStepVal, this, nextAttributes),
match || this.defaultInterpolate(nextStepVal, lastStepVal, key, nextAttributes, nextParsedProps, ratio) || this._interpolate(key, ratio, lastStepVal, nextStepVal, nextAttributes));
})), step.parsedProps = nextParsedProps;
}
defaultInterpolate(nextStepVal, lastStepVal, key, nextAttributes, nextParsedProps, ratio) {
if (Number.isFinite(nextStepVal) && Number.isFinite(lastStepVal)) return nextAttributes[key] = lastStepVal + (nextStepVal - lastStepVal) * ratio,
!0;
if ("fill" === key) {
nextParsedProps || (nextParsedProps = {});
const fillColorArray = nextParsedProps.fillColorArray, color = interpolateColor(lastStepVal, null != fillColorArray ? fillColorArray : nextStepVal, ratio, !1, ((fArray, tArray) => {
nextParsedProps.fillColorArray = tArray;
}));
return color && (nextAttributes[key] = color), !0;
}
if ("stroke" === key) {
nextParsedProps || (nextParsedProps = {});
const strokeColorArray = nextParsedProps.strokeColorArray, color = interpolateColor(lastStepVal, null != strokeColorArray ? strokeColorArray : nextStepVal, ratio, !1, ((fArray, tArray) => {
nextParsedProps.strokeColorArray = tArray;
}));
return color && (nextAttributes[key] = color), !0;
}
if ("shadowColor" === key) {
nextParsedProps || (nextParsedProps = {});
const shadowColorArray = nextParsedProps.shadowColorArray, color = interpolateColor(lastStepVal, null != shadowColorArray ? shadowColorArray : nextStepVal, ratio, !0, ((fArray, tArray) => {
nextParsedProps.shadowColorArray = tArray;
}));
return color && (nextAttributes[key] = color), !0;
}
if (Array.isArray(nextStepVal) && nextStepVal.length === lastStepVal.length) {
const nextList = [];
let valid = !0;
for (let i = 0; i < nextStepVal.length; i++) {
const v = lastStepVal[i], val = v + (nextStepVal[i] - v) * ratio;
if (!Number.isFinite(val)) {
valid = !1;
break;
}
nextList.push(val);
}
valid && (nextAttributes[key] = nextList);
}
return !1;
}
_interpolate(key, ratio, lastStepVal, nextStepVal, nextAttributes) {}
getDefaultAttribute(name) {
return this.getGraphicTheme()[name];
}
getComputedAttribute(name) {
var _a;
return null !== (_a = this.attribute[name]) && void 0 !== _a ? _a : this.getDefaultAttribute(name);
}
onSetStage(cb, immediate = !1) {
this._onSetStage = cb, immediate && this.stage && cb(this, this.stage);
}
attachShadow(shadowRoot) {
return shadowRoot && (shadowRoot.shadowHost = this), this.shadowRoot = null != shadowRoot ? shadowRoot : application.graphicService.creator.shadowRoot(this),
this.addUpdateBoundTag(), this.shadowRoot.setStage(this.stage, this.layer), this.shadowRoot;
}
detachShadow() {
this.shadowRoot && (this.addUpdateBoundTag(), this.shadowRoot.release(!0), this.shadowRoot = null);
}
toJson() {
return {
attribute: this.attribute,
_uid: this._uid,
type: this.type,
name: this.name,
children: this.children.map((item => item.toJson()))
};
}
createPathProxy(path) {
return isString(path, !0) ? this.pathProxy = (new CustomPath2D).fromString(path) : this.pathProxy = new CustomPath2D,
this.pathProxy;
}
loadImage(image, background = !1) {
if (!image || background && backgroundNotImage(image)) return;
const url = image;
this.resources || (this.resources = new Map);
const cache = {
data: "init",
state: null
};
this.resources.set(url, cache), "string" == typeof image ? (cache.state = "loading",
image.startsWith("<svg") ? (ResourceLoader.GetSvg(image, this), this.backgroundImg = this.backgroundImg || background) : (isValidUrl(image) || image.includes("/") || isBase64(image)) && (ResourceLoader.GetImage(image, this),
this.backgroundImg = this.backgroundImg || background)) : isObject(image) ? (cache.state = "success",
cache.data = image, this.backgroundImg = this.backgroundImg || background) : cache.state = "fail";
}
setShadowGraphic(graphic) {
if (graphic) {
this.attachShadow().add(graphic);
} else this.detachShadow();
}
imageLoadSuccess(url, image, cb) {
if (!this.resources) return;
const res = this.resources.get(url);
res && (res.state = "success", res.data = image, cb && cb(), this.addUpdateBoundTag(),
this.stage && this.stage.renderNextFrame());
}
imageLoadFail(url, cb) {
if (!this.resources) return;
const res = this.resources.get(url);
res && (res.state = "fail", cb && cb());
}
_stopAnimates(animates) {
animates && animates.forEach((animate => {
animate.stop();
}));
}
stopAnimates(stopChildren = !1) {
this._stopAnimates(this.animates), this.shadowRoot && this.shadowRoot.stopAnimates(!0),
this.isContainer && stopChildren && this.forEachChildren((c => {
c.stopAnimates(stopChildren);
}));
}
release() {
this.releaseStatus = "released", this.stopAnimates(), application.graphicService.onRelease(this);
}
_emitCustomEvent(type, context) {
var _a, _b;
if (this._events && type in this._events) {
const changeEvent = new CustomEvent(type, context);
changeEvent.bubbles = !1, changeEvent.manager = null === (_b = null === (_a = this.stage) || void 0 === _a ? void 0 : _a.eventSystem) || void 0 === _b ? void 0 : _b.manager,
this.dispatchEvent(changeEvent);
}
}
}
function backgroundNotImage(image) {
return !(!image.fill && !image.stroke);
}
Graphic.userSymbolMap = {}, Graphic.mixin(EventTarget);
//# sourceMappingURL=graphic.js.map