Skip to content

Commit 122e3f6

Browse files
committed
feat: support AStageAnimate
1 parent 4020998 commit 122e3f6

File tree

13 files changed

+174
-14
lines changed

13 files changed

+174
-14
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@visactor/vrender-animate",
5+
"comment": "feat: support AStageAnimate",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@visactor/vrender-animate"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@visactor/vrender-core",
5+
"comment": "feat: support AStageAnimate",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@visactor/vrender-core"
10+
}

packages/vrender-animate/src/animate.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,10 @@ export class Animate implements IAnimate {
492492
this._onFrame = [];
493493
this._onEnd = [];
494494
this._onRemove = [];
495+
496+
this.forEachStep(step => {
497+
step.release();
498+
});
495499
}
496500

497501
/**
@@ -716,4 +720,12 @@ export class Animate implements IAnimate {
716720
getLoop(): number {
717721
return this._loopCount;
718722
}
723+
724+
protected forEachStep(cb: (step: IStep) => void): void {
725+
let step = this._firstStep;
726+
while (step) {
727+
cb(step);
728+
step = step.next;
729+
}
730+
}
719731
}

packages/vrender-animate/src/custom/custom-animate.ts

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ComponentAnimator } from '../component';
2-
import type { EasingType, IAnimateStepType, ICustomAnimate } from '@visactor/vrender-core';
2+
import type { EasingType, IAnimateStepType, ICustomAnimate, Stage } from '@visactor/vrender-core';
33
import { Step } from '../step';
44

55
export abstract class ACustomAnimate<T> extends Step implements ICustomAnimate {
@@ -52,3 +52,78 @@ export abstract class AComponentAnimate<T> extends ACustomAnimate<T> {
5252
this._animator && this._animator.stop();
5353
}
5454
}
55+
56+
export abstract class AStageAnimate<T> extends ACustomAnimate<T> {
57+
willCallBeforeStageRender: boolean = true;
58+
willCallAfterStageRender: boolean = true;
59+
constructor(customFrom: T, customTo: T, duration: number, easing: EasingType, params?: any) {
60+
super(customFrom, customTo, duration, easing, params);
61+
this.props = {} as T;
62+
}
63+
64+
// 用户重载
65+
protected beforeStageRender(stage: Stage, canvas: HTMLCanvasElement): HTMLCanvasElement | void | null | false {
66+
return false;
67+
}
68+
69+
// 用户重载
70+
protected afterStageRender(stage: Stage, canvas: HTMLCanvasElement): HTMLCanvasElement | void | null | false {
71+
return false;
72+
}
73+
74+
onFirstRun(): void {
75+
super.onFirstRun();
76+
this.target.stage.setBeforeRender(this._beforeStageRender);
77+
this.target.stage.setAfterRender(this._afterStageRender);
78+
// 禁用脏矩形,因为stage动画可能会批量修改整体画面
79+
this.target.stage.disableDirtyBounds();
80+
}
81+
82+
stop() {
83+
super.stop();
84+
this.target.stage.removeBeforeRender(this._beforeStageRender);
85+
this.target.stage.removeAfterRender(this._afterStageRender);
86+
}
87+
onUpdate(end: boolean, ratio: number, out: Record<string, any>): void {
88+
super.onUpdate(end, ratio, out);
89+
this.willCallBeforeStageRender = true;
90+
this.willCallAfterStageRender = true;
91+
}
92+
93+
protected _beforeStageRender = () => {
94+
if (!this.willCallBeforeStageRender) {
95+
return;
96+
}
97+
this.willCallBeforeStageRender = false;
98+
const stage = this.target.stage as any;
99+
const canvas = stage.window.getContext().canvas.nativeCanvas;
100+
const outputCanvas = this.beforeStageRender(stage, canvas);
101+
if (outputCanvas) {
102+
this.renderToStage(stage, outputCanvas);
103+
}
104+
};
105+
106+
protected _afterStageRender = () => {
107+
if (!this.willCallAfterStageRender) {
108+
return;
109+
}
110+
this.willCallAfterStageRender = false;
111+
const stage = this.target.stage as any;
112+
const canvas = stage.window.getContext().canvas.nativeCanvas;
113+
const outputCanvas = this.afterStageRender(stage, canvas);
114+
if (outputCanvas) {
115+
this.renderToStage(stage, outputCanvas);
116+
}
117+
};
118+
119+
protected renderToStage(stage: Stage, canvas: HTMLCanvasElement): HTMLCanvasElement | void | null | false {
120+
const stageCanvas = stage.window.getContext().canvas.nativeCanvas;
121+
const ctx = stageCanvas.getContext('2d');
122+
if (!ctx) {
123+
return false;
124+
}
125+
ctx.clearRect(0, 0, stageCanvas.width, stageCanvas.height);
126+
ctx.drawImage(canvas, 0, 0);
127+
return stageCanvas;
128+
}
129+
}

packages/vrender-animate/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export { Step as AnimateStep } from './step';
99
export * from './utils/easing-func';
1010
export * from './utils/easing';
1111
export { registerAnimate } from './register';
12-
export { ACustomAnimate, AComponentAnimate } from './custom/custom-animate';
12+
export { ACustomAnimate, AComponentAnimate, AStageAnimate } from './custom/custom-animate';
1313
export { ComponentAnimator } from './component/component-animator';
1414
export { IncreaseCount } from './custom/number';
1515
export { MorphingPath, MultiToOneMorphingPath, oneToMultiMorph, multiToOneMorph, morphPath } from './custom/morphing';

packages/vrender-animate/src/step.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ export class Step implements IStep {
316316
stop(): void {
317317
// ...
318318
}
319+
320+
release(): void {
321+
// ...
322+
}
319323
}
320324

321325
export class WaitStep extends Step {

packages/vrender-core/src/core/stage.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,8 @@ export class Stage extends Group implements IStage {
185185
return this._eventSystem;
186186
}
187187

188-
protected _beforeRender?: (stage: IStage) => void;
189-
protected _afterRender?: (stage: IStage) => void;
188+
protected _beforeRenderList: Array<(stage: IStage) => void>;
189+
protected _afterRenderList: Array<(stage: IStage) => void>;
190190
// 0: 正常渲染, > 0: 跳过隐藏canvas的渲染, < 0: 禁止渲染
191191
protected _skipRender?: number;
192192
protected _afterNextRenderCbs?: ((stage: IStage) => void)[];
@@ -245,6 +245,8 @@ export class Stage extends Group implements IStage {
245245
this.layerService = container.get<ILayerService>(LayerService);
246246
this.graphicService = container.get<IGraphicService>(GraphicService);
247247
this.pluginService.active(this, params);
248+
this._beforeRenderList = [];
249+
this._afterRenderList = [];
248250

249251
this.window.create({
250252
width: params.width,
@@ -301,8 +303,12 @@ export class Stage extends Group implements IStage {
301303
params.enableLayout && this.enableLayout();
302304
this.hooks.beforeRender.tap('constructor', this.beforeRender);
303305
this.hooks.afterRender.tap('constructor', this.afterRender);
304-
this._beforeRender = params.beforeRender;
305-
this._afterRender = params.afterRender;
306+
if (params.beforeRender) {
307+
this._beforeRenderList.push(params.beforeRender);
308+
}
309+
if (params.afterRender) {
310+
this._afterRenderList.push(params.afterRender);
311+
}
306312
this.supportInteractiveLayer = params.interactiveLayer !== false;
307313
if (!params.optimize) {
308314
params.optimize = {
@@ -488,12 +494,12 @@ export class Stage extends Group implements IStage {
488494
}
489495

490496
protected beforeRender = (stage: IStage) => {
491-
this._beforeRender && this._beforeRender(stage);
497+
this._beforeRenderList.forEach(cb => cb(stage));
492498
};
493499

494500
protected afterRender = (stage: IStage) => {
495501
this.renderCount++;
496-
this._afterRender && this._afterRender(stage);
502+
this._afterRenderList.forEach(cb => cb(stage));
497503
this._afterNextRenderCbs && this._afterNextRenderCbs.forEach(cb => cb(stage));
498504
this._afterNextRenderCbs = null;
499505
this.tickedBeforeRender = false;
@@ -506,11 +512,19 @@ export class Stage extends Group implements IStage {
506512
};
507513

508514
setBeforeRender(cb: (stage: IStage) => void) {
509-
this._beforeRender = cb;
515+
this._beforeRenderList.push(cb);
516+
}
517+
518+
removeBeforeRender(cb: (stage: IStage) => void) {
519+
this._beforeRenderList = this._beforeRenderList.filter(c => c !== cb);
510520
}
511521

512522
setAfterRender(cb: (stage: IStage) => void) {
513-
this._afterRender = cb;
523+
this._afterRenderList.push(cb);
524+
}
525+
526+
removeAfterRender(cb: (stage: IStage) => void) {
527+
this._afterRenderList = this._afterRenderList.filter(c => c !== cb);
514528
}
515529

516530
afterNextRender(cb: (stage: IStage) => void) {

packages/vrender-core/src/event/event-target.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,6 @@ export const EventTarget: Omit<IEventTarget, Exclude<keyof INode, 'dispatchEvent
6161
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
6262
// @ts-ignore
6363
emit(eventName: string, object: Dict<any>) {
64-
return this.dispatchEvent(new CustomEvent(eventName, object));
64+
return (this as any).dispatchEvent(new CustomEvent(eventName, object));
6565
}
6666
};

packages/vrender-core/src/graphic/graphic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,9 @@ export abstract class Graphic<T extends Partial<IGraphicAttribute> = Partial<IGr
691691
}
692692

693693
setAttributes(params: Partial<T>, forceUpdateTag: boolean = false, context?: ISetAttributeContext) {
694+
if (!params) {
695+
return;
696+
}
694697
params =
695698
(this.onBeforeAttributeUpdate && this.onBeforeAttributeUpdate(params, this.attribute, null, context)) || params;
696699

packages/vrender-core/src/interface/animation/animate.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export interface IStep {
6666

6767
// 停止
6868
stop: () => void;
69+
70+
// 释放
71+
release: () => void;
6972
}
7073

7174
export interface IAnimate {

0 commit comments

Comments
 (0)