diff --git a/packages/vchart/src/animation/animate-manager.ts b/packages/vchart/src/animation/animate-manager.ts index b85b7797fb..c17fb26be2 100644 --- a/packages/vchart/src/animation/animate-manager.ts +++ b/packages/vchart/src/animation/animate-manager.ts @@ -1,66 +1,65 @@ -import { StateManager } from '../compile/state-manager'; -import { createID } from '../util/id'; -import type { IAnimate, IAnimateState } from './interface'; -// eslint-disable-next-line no-duplicate-imports -import { AnimationStateEnum } from './interface'; -import type { StateValueMap } from '../compile/interface/compilable-item'; -import type { IMarkGraphic } from '../mark/interface/common'; +// import { StateManager } from '../compile/state-manager'; +// import { createID } from '../util/id'; +// import type { IAnimate, IAnimateState } from './interface'; +// // eslint-disable-next-line no-duplicate-imports +// import { AnimationStateEnum } from './interface'; +// import type { StateValueMap } from '../compile/interface/compilable-item'; +// import type { IMarkGraphic } from '../mark/interface/common'; -// todo @feifei -export class AnimateManager extends StateManager implements IAnimate { - protected declare _stateMap: IAnimateState & StateValueMap; +// export class AnimateManager extends StateManager implements IAnimate { +// protected declare _stateMap: IAnimateState & StateValueMap; - readonly id: number = createID(); +// readonly id: number = createID(); - updateAnimateState(state: AnimationStateEnum, noRender?: boolean) { - // when animation state is 'update', do animations by element diffState(enter & update & exit) - if (state === AnimationStateEnum.update) { - this.updateState( - { - animationState: { - callback: (datum: any, g: IMarkGraphic) => g.context.diffState - } - }, - noRender - ); - } - // when animation state is 'appear', all valid elements would do appear animation except from exit elements - else if (state === AnimationStateEnum.appear) { - this.updateState( - { - animationState: { - callback: (datum: any, g: IMarkGraphic) => { - return g.context.diffState === 'exit' ? AnimationStateEnum.none : AnimationStateEnum.appear; - } - } - }, - noRender - ); - } - // when animation state is other types, all elements would do animation by state - else { - this.updateState( - { - animationState: { - callback: (datum: any, g: IMarkGraphic) => state - } - }, - noRender - ); - } - } +// updateAnimateState(state: AnimationStateEnum, noRender?: boolean) { +// // when animation state is 'update', do animations by element diffState(enter & update & exit) +// if (state === AnimationStateEnum.update) { +// this.updateState( +// { +// animationState: { +// callback: (datum: any, g: IMarkGraphic) => g.context.diffState +// } +// }, +// noRender +// ); +// } +// // when animation state is 'appear', all valid elements would do appear animation except from exit elements +// else if (state === AnimationStateEnum.appear) { +// this.updateState( +// { +// animationState: { +// callback: (datum: any, g: IMarkGraphic) => { +// return g.context.diffState === 'exit' ? AnimationStateEnum.none : AnimationStateEnum.appear; +// } +// } +// }, +// noRender +// ); +// } +// // when animation state is other types, all elements would do animation by state +// else { +// this.updateState( +// { +// animationState: { +// callback: (datum: any, g: IMarkGraphic) => state +// } +// }, +// noRender +// ); +// } +// } - protected _getDefaultStateMap(): IAnimateState & StateValueMap { - return { - animationState: { - callback: (datum: any, g: IMarkGraphic) => { - return g.context.diffState === 'exit' - ? AnimationStateEnum.exit - : g.context.diffState === 'update' - ? AnimationStateEnum.update - : AnimationStateEnum.appear; - } - } - }; - } -} +// protected _getDefaultStateMap(): IAnimateState & StateValueMap { +// return { +// animationState: { +// callback: (datum: any, g: IMarkGraphic) => { +// return g.context.diffState === 'exit' +// ? AnimationStateEnum.exit +// : g.context.diffState === 'update' +// ? AnimationStateEnum.update +// : AnimationStateEnum.appear; +// } +// } +// }; +// } +// } diff --git a/packages/vchart/src/animation/interface.ts b/packages/vchart/src/animation/interface.ts index 941fa09a73..6cba5a77c0 100644 --- a/packages/vchart/src/animation/interface.ts +++ b/packages/vchart/src/animation/interface.ts @@ -20,14 +20,6 @@ export interface IAnimateState { animationState: { callback: (datum: any, element: any) => AnimationStateEnum }; } -export interface IAnimate extends ICompilable { - id: number; - updateAnimateState: (state: AnimationStateEnum, noRender?: boolean) => void; - // TODO: animation control - // pause: () => void; - // resume: () => void; -} - export interface ICartesianGroupAnimationParams { direction: () => 'x' | 'y'; orient: () => 'positive' | 'negative'; diff --git a/packages/vchart/src/compile/compiler.ts b/packages/vchart/src/compile/compiler.ts index 5c7895cafc..0f95548a0b 100644 --- a/packages/vchart/src/compile/compiler.ts +++ b/packages/vchart/src/compile/compiler.ts @@ -13,7 +13,7 @@ import { isMobileLikeMode, isTrueBrowser } from '../util/env'; import { isString } from '../util/type'; import type { IBoundsLike } from '@visactor/vutils'; // eslint-disable-next-line no-duplicate-imports -import { isObject, isValid, Logger, LoggerLevel } from '@visactor/vutils'; +import { isObject, isValid } from '@visactor/vutils'; import type { EventSourceType } from '../event/interface'; import type { IChart } from '../chart/interface'; import { createGroup, Stage, vglobal, waitForAllSubLayers } from '@visactor/vrender-core'; diff --git a/packages/vchart/src/component/base/base-component.ts b/packages/vchart/src/component/base/base-component.ts index 75c2028048..b629da9173 100644 --- a/packages/vchart/src/component/base/base-component.ts +++ b/packages/vchart/src/component/base/base-component.ts @@ -7,8 +7,6 @@ import type { IBoundsLike } from '@visactor/vutils'; // eslint-disable-next-line no-duplicate-imports import { isEqual } from '@visactor/vutils'; import { Event_Source_Type } from '../../constant/event'; -import type { IAnimate } from '../../animation/interface'; -import { AnimateManager } from '../../animation/animate-manager'; // import { preprocessSpecOrTheme } from '../../util/spec/preprocess'; import type { Datum, ILayoutRect } from '../../typings'; import type { IComponentSpec } from './interface'; @@ -46,18 +44,6 @@ export class BaseComponent extends La this.pluginService = new ComponentPluginService(this); } - animate?: IAnimate; - - constructor(spec: T, options: IComponentOption) { - super(spec, options); - // 创建组件自己的动画管理器 - if (this._option.animation) { - this.animate = new AnimateManager({ - getCompiler: options.getCompiler - }); - } - } - initLayout(): void { super.initLayout(); this._regions = this._regions ?? this._option.getRegionsInIndex(); diff --git a/packages/vchart/src/component/interface/common.ts b/packages/vchart/src/component/interface/common.ts index 670431a75a..0268a352ee 100644 --- a/packages/vchart/src/component/interface/common.ts +++ b/packages/vchart/src/component/interface/common.ts @@ -1,5 +1,4 @@ import type { ISeriesFilter } from '../../region/interface'; -import type { IAnimate } from '../../animation/interface'; import type { ILayoutModel, IModelConstructor, IModelOption, IModelSpecInfo } from '../../model/interface'; // eslint-disable-next-line no-duplicate-imports import type { IRegion } from '../../region/interface'; @@ -35,7 +34,6 @@ export interface IComponentOption extends IModelOption { export interface IComponent extends ILayoutModel { readonly name: string; - readonly animate?: IAnimate; // 区域 getRegions: () => IRegion[]; diff --git a/packages/vchart/src/core/vchart.ts b/packages/vchart/src/core/vchart.ts index 6e5e1f5ae3..9b04a9df85 100644 --- a/packages/vchart/src/core/vchart.ts +++ b/packages/vchart/src/core/vchart.ts @@ -47,7 +47,7 @@ import type { GeoSourceOption } from '../series/map/geo-source'; // eslint-disable-next-line no-duplicate-imports import { getMapSource } from '../series/map/geo-source'; // eslint-disable-next-line no-duplicate-imports -import type { IMark, MarkConstructor } from '../mark/interface'; +import type { IMark, IMarkGraphic, MarkConstructor } from '../mark/interface'; import { registerDataSetInstanceParser, registerDataSetInstanceTransform } from '../data/register'; import { dataToDataView } from '../data/initialize'; import { copyDataView } from '../data/transforms/copy-data-view'; @@ -773,7 +773,6 @@ export class VChart implements IVChart { if (this._isReleased) { return false; } - this._updateAnimateState(); this._event.emit(ChartEvent.rendered, { chart: this._chart, vchart: this @@ -823,18 +822,17 @@ export class VChart implements IVChart { } private _updateAnimateState(initial?: boolean) { - // todo @feifei if (this._option.animation) { - const animationState = initial ? AnimationStateEnum.appear : AnimationStateEnum.update; - - this._chart?.getAllRegions().forEach(region => { - // region.getAllMarks().forEach(mark => { + const updateGraphicAnimationState = (graphic: IMarkGraphic) => { + const diffState = graphic.context.diffState; + if (initial) { + return diffState === 'exit' ? undefined : AnimationStateEnum.appear; + } + return diffState; + }; - // }) - region.animate?.updateAnimateState(animationState, true); - }); - this._chart?.getAllComponents().forEach(component => { - component.animate?.updateAnimateState(animationState, true); + this._compiler.getRootMarks().forEach(mark => { + mark.updateAnimationState(updateGraphicAnimationState); }); } } @@ -954,15 +952,15 @@ export class VChart implements IVChart { return this as unknown as IVChart; } if (this._chart) { - if (userUpdateOptions?.reAnimate) { - this.stopAnimation(); - this._updateAnimateState(true); - } - this._chart.updateData(id, data, true, parserOptions); // after layout this._compiler.render(); + + if (userUpdateOptions?.reAnimate) { + this.stopAnimation(); + this._updateAnimateState(true); + } return this as unknown as IVChart; } this._spec.data = array(this._spec.data); @@ -983,13 +981,13 @@ export class VChart implements IVChart { userUpdateOptions?: IUpdateSpecResult ) { if (this._chart) { - if (userUpdateOptions?.reAnimate) { - this.stopAnimation(); - this._updateAnimateState(true); - } this._chart.updateFullData(data); if (reRender) { this._compiler.render(); + if (userUpdateOptions?.reAnimate) { + this.stopAnimation(); + this._updateAnimateState(true); + } } return this as unknown as IVChart; } diff --git a/packages/vchart/src/mark/base/base-mark.ts b/packages/vchart/src/mark/base/base-mark.ts index 03ecfed73f..65138465b6 100644 --- a/packages/vchart/src/mark/base/base-mark.ts +++ b/packages/vchart/src/mark/base/base-mark.ts @@ -1,3 +1,4 @@ +import { DiffState } from './../interface/enum'; import { type IStateInfo, type IModelMarkAttributeContext, STATE_VALUE_ENUM } from '../../compile/mark/interface'; import type { BaseSeries } from '../../series/base/base-series'; import type { @@ -34,7 +35,8 @@ import type { DiffStateValues, ProgressiveContext, IProgressiveTransformResult, - MarkType + MarkType, + AnimationStateValues } from '../interface'; import { DiffState } from '../interface/enum'; import { GradientType, DEFAULT_GRADIENT_CONFIG } from '../../constant/gradient'; @@ -57,7 +59,7 @@ import { GrammarItem } from '../../compile/grammar-item'; import { LayoutZIndex } from '../../constant/layout'; import type { IModel } from '../../model/interface'; import type { ICompilableData } from '../../compile/data/interface'; -import type { MarkAnimationSpec } from '../../animation/interface'; +import { AnimationStateEnum, type MarkAnimationSpec } from '../../animation/interface'; import { CompilableData } from '../../compile/data/compilable-data'; import { log } from '../../util'; @@ -1126,7 +1128,7 @@ export class BaseMark extends GrammarItem implements IMar g.context = { ...this._getCommonContext(), diffState, - // todo @feifei animationState + animationState: diffState, data: newData, uniqueKey: key, key: newData ? this._keyGetter(newData[0]) : g.context?.key, @@ -1134,6 +1136,7 @@ export class BaseMark extends GrammarItem implements IMar }; enterGraphics.delete(g); } + return g; }; if (prevGroupedData && newGroupedData) { @@ -1152,13 +1155,17 @@ export class BaseMark extends GrammarItem implements IMar }); } else if (newGroupedData) { newGroupedData.keys.forEach(key => { - // enter - callback(key, newGroupedData.data.get(key), null); + // appear + const g = callback(key, newGroupedData.data.get(key), null); + if (g) { + g.context.animationState = AnimationStateEnum.appear; + } }); } else if (prevGroupedData) { prevGroupedData.keys.forEach(key => { - // exit - callback(key, null, prevGroupedData.data.get(key)); + // disappear + const g = callback(key, null, prevGroupedData.data.get(key)); + g.context.animationState = AnimationStateEnum.disappear; }); } @@ -1672,4 +1679,10 @@ export class BaseMark extends GrammarItem implements IMar this._runProgressiveStep(); } } + + updateAnimationState(callback: (graphic: IMarkGraphic) => AnimationStateValues) { + if (this._graphics) { + this._graphics.forEach(g => (g.context.animationState = callback(g))); + } + } } diff --git a/packages/vchart/src/mark/group.ts b/packages/vchart/src/mark/group.ts index 050d4c5d36..b2255e91f3 100644 --- a/packages/vchart/src/mark/group.ts +++ b/packages/vchart/src/mark/group.ts @@ -4,7 +4,7 @@ import type { Maybe } from '../typings'; import { log, warn } from '../util/debug'; import type { IGroupMarkSpec } from '../typings/visual'; import { BaseMark } from './base/base-mark'; -import type { IGroupMark, IMark, IMarkGraphic, MarkType } from './interface'; +import type { AnimationStateValues, IGroupMark, IMark, IMarkGraphic, MarkType } from './interface'; // eslint-disable-next-line no-duplicate-imports import { MarkTypeEnum } from './interface/type'; import { type IMarkCompileOption } from '../compile/mark'; @@ -126,6 +126,12 @@ export class GroupMark extends BaseMark implements IGroupMark { }); } + updateAnimationState(callback: (g: IMarkGraphic) => AnimationStateValues) { + this.getMarks().forEach(mark => { + mark.updateAnimationState(callback); + }); + } + release() { super.release(); this.removeProduct(); diff --git a/packages/vchart/src/mark/interface/common.ts b/packages/vchart/src/mark/interface/common.ts index b5edbceca7..b36c1ed0f4 100644 --- a/packages/vchart/src/mark/interface/common.ts +++ b/packages/vchart/src/mark/interface/common.ts @@ -59,6 +59,8 @@ export type IMarkStyle = { export type DiffStateValues = 'update' | 'enter' | 'exit'; +export type AnimationStateValues = 'appear' | 'enter' | 'update' | 'exit' | 'disappear'; + export interface IGraphicContext { markType: MarkTypeEnum; /** @@ -84,7 +86,7 @@ export interface IGraphicContext { /** * 动画状态管理: 'appear' / 'enter' / 'update' / 'exit' / 'disappear' */ - animationState?: MarkAnimationType; + animationState?: AnimationStateValues; /** * 数据 */ @@ -169,6 +171,8 @@ export interface IMarkRaw extends ICompilableMark { renderProgressive: () => void; /** 增量流程后,是否执行动画 */ canAnimateAfterProgressive: () => boolean; + /** 更新图元动画状态 */ + updateAnimationState: (callback: (graphic: IMarkGraphic) => AnimationStateValues) => void; } export type IMark = IMarkRaw; diff --git a/packages/vchart/src/region/region.ts b/packages/vchart/src/region/region.ts index 0095fe70f1..6a5e172eab 100644 --- a/packages/vchart/src/region/region.ts +++ b/packages/vchart/src/region/region.ts @@ -8,8 +8,6 @@ import type { IGeoRegionSpec, IRegion, IRegionSpec, IRegionSpecInfo } from './in import { ChartEvent } from '../constant/event'; import { LayoutZIndex } from '../constant/layout'; import { AttributeLevel } from '../constant/attribute'; -import { AnimateManager } from '../animation/animate-manager'; -import type { IAnimate } from '../animation/interface'; import type { ILayoutType, StringOrNumber } from '../typings'; import { LayoutModel } from '../model/layout-model'; import { RegionSpecTransformer } from './region-transformer'; @@ -29,8 +27,6 @@ export class Region extends LayoutModel layoutType: ILayoutType = 'region'; layoutZIndex: number = LayoutZIndex.Region; - animate?: IAnimate; - declare getSpecInfo: () => IRegionSpecInfo; getMaxWidth() { @@ -72,11 +68,6 @@ export class Region extends LayoutModel super(spec, ctx); this.userId = spec.id; this.coordinate = spec.coordinate ?? 'cartesian'; - if (this._option.animation) { - this.animate = new AnimateManager({ - getCompiler: ctx.getCompiler - }); - } } protected _getClipDefaultValue() { @@ -334,7 +325,6 @@ export class Region extends LayoutModel } compile() { - this.animate?.compile(); this.compileMarks(); }