Skip to content

Commit

Permalink
Merge pull request #35 from VisActor/feat/play-loop
Browse files Browse the repository at this point in the history
Feat/play loop
  • Loading branch information
neuqzxy authored Aug 8, 2024
2 parents e40cf41 + 949cc01 commit 8b6e3f6
Show file tree
Hide file tree
Showing 19 changed files with 98 additions and 340 deletions.
2 changes: 1 addition & 1 deletion packages/vstory/demo/src/demos/BarLineSeries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const BarLineSeries = () => {
style: {},
animation: {
// effect: 'fade',
duration: 10000,
duration: 1000,
easing: 'linear'
} as any
}
Expand Down
20 changes: 10 additions & 10 deletions packages/vstory/demo/src/demos/VChartSite/VChartSite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ export const VChartSiteDemo = () => {
// ...scene5Characters,
// ...scene6Characters,
// ...scene7Characters,
// ...scene8Characters,
// ...scene9Characters,
// ...scene8Characters
// ...scene9Characters
// ...scene10Characters,
// ...scene11Characters,
// ...scene12Characters,
...scene12_2_Characters
// ...scene13Characters
// ...scene12Characters
// ...scene12_2_Characters
...scene13Characters
],
acts: [
{
Expand All @@ -49,13 +49,13 @@ export const VChartSiteDemo = () => {
// scene5,
// scene6,
// scene7,
// scene8,
// scene9,
// scene8
// scene9
// scene10,
// scene11,
// scene12,
scene12_2
// scene13
// scene12
// scene12_2
scene13
]
}
]
Expand Down
7 changes: 4 additions & 3 deletions packages/vstory/demo/src/demos/VChartSite/scene13.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const scene13: ISceneSpec = {
characterActions: [
{
action: 'appear',
startTime: 1,
startTime: 0,
duration: 1000,
payload: {
animation: {
Expand All @@ -65,11 +65,12 @@ export const scene13: ISceneSpec = {
characterActions: [
{
action: 'appear',
startTime: 1,
startTime: 0,
duration: 1000,
payload: {
animation: {
duration: 1000,
duration: 2000,
effect: 'scale',
easing: easeInOutQuad,
fade: { opacity: 1 }
}
Expand Down
4 changes: 3 additions & 1 deletion packages/vstory/src/player/interface/player.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { EventEmitter } from '@visactor/vutils';
import { ICharacter } from '../../story/character';
import type { IActSpec } from '../../story/interface/dsl-interface';

export interface IPlayer {
export interface IPlayer extends EventEmitter {
tickTo: (t: number) => void;
play: () => void;
encodeToVideo: (millsecond: number, fps: number) => Promise<string>;
pause: () => void;
release: () => void;
initActs: (acts: IActSpec[]) => void;
reset: () => void;
}
2 changes: 1 addition & 1 deletion packages/vstory/src/player/interface/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { IActSpec } from '../../story/interface';
import type { IActionItem } from '../scheduler';

export interface IScheduler {
initActs: (acts: IActSpec[]) => void;
init: (acts: IActSpec[]) => void;
getActionsInRange: (fromTime: number, toTime: number) => IActionItem[];
clearState: () => void;
getTotalTime: () => number;
Expand Down
43 changes: 27 additions & 16 deletions packages/vstory/src/player/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,36 @@ import { ActionProcessor } from './processor/processor';
import { processorMap } from './processor/processorMap';
import type { IScheduler } from './interface/scheduler';
import { Scheduler } from './scheduler';
import { EventEmitter } from '@visactor/vutils';

export class Ticker {
cb?: (delta: number) => void;
rafIdx = 0;
running: boolean;
start(cb: (t: number) => void) {
this.stop();
this.cb = cb;
this.running = true;
this._tick(0);
}

_tick = (lt: number) => {
if (!this.running) {
return;
}
const ct = Date.now();
this.cb && this.cb(lt === 0 ? 0 : ct - lt);
this.rafIdx = requestAnimationFrame(() => this._tick(ct));
this.cb && this.cb(lt === 0 ? 0 : ct - lt);
};

stop() {
this.rafIdx && cancelAnimationFrame(this.rafIdx);
this.rafIdx = 0;
this.running = false;
}
}

export class Player implements IPlayer {
export class Player extends EventEmitter implements IPlayer {
protected _story: IStory;
protected _ticker: Ticker;
protected _currTime: number;
Expand All @@ -38,6 +45,7 @@ export class Player implements IPlayer {
protected _scheduler: IScheduler;

constructor(story: IStory, options?: { scaleX?: number; scaleY?: number }) {
super();
this._story = story;
this._ticker = new Ticker();
this._currTime = 0;
Expand All @@ -51,32 +59,25 @@ export class Player implements IPlayer {
}

initActs(acts: IActSpec[]) {
this._scheduler.initActs(acts);
this._scheduler.init(acts);
}

// 清除当前状态,一般用于回放操作
reset() {
this._scheduler.clearState();
this._story.canvas.getStage().getTimeline().clear();
this._currTime = 0;
return;
}

tickTo(t: number) {
// console.log(t);
const lastTime = this._currTime;
const totalTime = this._scheduler.getTotalTime();
while (t > totalTime) {
t -= totalTime;
}
// 如果时间倒退,那就重置,从头开始(需要上层场景树也重置)
if (lastTime > t) {
// 先结束这一块内容,设置到totalTime,让动画结束
if (lastTime < totalTime) {
t = totalTime + 0.01;
} else {
this.reset();
this._currTime = 0;
this.tickTo(0);
}
this.reset();
// this._currTime = 0;
// this.tickTo(0);
}

const actions = this._scheduler.getActionsInRange(lastTime, t);
Expand All @@ -103,7 +104,17 @@ export class Player implements IPlayer {
this._currTime = 0;
this.reset();
this._ticker.start(t => {
this.tickTo(this._currTime + t);
let nextT = this._currTime + t;
const totalTime = this._scheduler.getTotalTime();
// 时间超过总时长之后,停止ticker执行
if (nextT >= totalTime) {
nextT = totalTime;
this.tickTo(nextT);
this._ticker.stop();
this.emit('onstop');
} else {
this.tickTo(nextT);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ export const commonFade = (
) => {
const { duration, easing } = animation;
const { disappear } = option;
const currOpacity = instance.attribute.baseOpacity;
const opacityMap = disappear ? { from: 1, to: 0 } : { from: 0, to: 1 };

instance.setAttributes({ baseOpacity: opacityMap.from });
instance.setAttributes({ baseOpacity: currOpacity ?? opacityMap.from });
instance.animate().to({ baseOpacity: opacityMap.to }, duration, easing);
};
export const commonGrow = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { IGroup } from '@visactor/vrender-core';
import type { IChartVisibilityAction } from '../../interface/appear-action';
import { commonFade } from '../common/commonAppear';

export const commonGrow = (
instance: IGroup,
Expand Down Expand Up @@ -32,18 +33,6 @@ export const commonGrow = (
}
};

export const commonFade = (
instance: IGroup,
animation: IChartVisibilityAction['payload']['animation'],
option: { disappear: boolean }
) => {
const { duration, easing } = animation;
const { disappear } = option;
const opacityMap = disappear ? { from: 1, to: 0 } : { from: 0, to: 1 };
instance.setAttributes({ baseOpacity: opacityMap.from });
instance.animate().to({ baseOpacity: opacityMap.to }, duration, easing);
};

export const runAppearOrDisAppear = (
instance: IGroup,
animation: IChartVisibilityAction['payload']['animation'],
Expand Down
2 changes: 1 addition & 1 deletion packages/vstory/src/player/processor/chart/transformMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export const transformMap = {
axis: runAxisAppear,
title: runTitleAppear,
// chart:
chart: runAppearOrDisAppear
chart: runChartAppear
}
};
17 changes: 11 additions & 6 deletions packages/vstory/src/player/processor/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,17 @@ export class ActionProcessor implements IActionProcessor {
doAction(name: string, actionName: string, character: ICharacter, actionSpec: IAction): void {
const processor = this.getProcessor(name, actionName);
if (processor) {
// eslint-disable-next-line no-console
logger('info', `Execute action => ${actionName}, character => ${name}`); // TODO: remove log
const actionResult = processor.run(character, actionSpec);
// eslint-disable-next-line no-console
logger('info', `Action Executed:`, actionResult); // TODO: remove log
return actionResult;
try {
// eslint-disable-next-line no-console
logger('info', `Execute action => ${actionName}, character => ${name}`); // TODO: remove log
const actionResult = processor.run(character, actionSpec);
// eslint-disable-next-line no-console
logger('info', `Action Executed:`, actionResult); // TODO: remove log
return actionResult;
} catch (err) {
logger('error', `Action Executed Error: ${err}`);
return null;
}
}
// eslint-disable-next-line no-console
logger('error', `Action not found: character => ${name}, action => ${actionName} `); // TODO: remove log
Expand Down
7 changes: 6 additions & 1 deletion packages/vstory/src/player/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ export class Scheduler implements IScheduler {
this._runnedAct = new Set();
}

init(acts: IActSpec[]) {
this.clearState();
this.initActs(acts);
}

clearState(): void {
this._runnedAct.clear();
}
Expand Down Expand Up @@ -112,7 +117,7 @@ export class Scheduler implements IScheduler {
return actions;
}

initActs(acts: IActSpec[]) {
protected initActs(acts: IActSpec[]) {
// act与act之间是串联的
let startTime = 0;
this._actsInfo = acts.map(act => {
Expand Down
9 changes: 9 additions & 0 deletions packages/vstory/src/story/character-tree/character-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export class CharacterTree implements ICharacterTree {
}

initCharacters(specs: ICharacterSpec[]): void {
this.releaseOldCharacters();
this._characters = {};
const option = {
story: this._story,
canvas: this._story.canvas,
Expand All @@ -49,4 +51,11 @@ export class CharacterTree implements ICharacterTree {
}
});
}

releaseOldCharacters() {
Object.keys(this._characters).forEach(k => {
const c = this._characters[k];
c.release();
});
}
}
4 changes: 4 additions & 0 deletions packages/vstory/src/story/character/chart/character.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,8 @@ export class CharacterChart extends CharacterVisactor {
checkEvent(event: StoryEvent): false | ICharacterPickInfo {
return false;
}

release(): void {
this.option.graphicParent.removeChild(this._graphic as any);
}
}
4 changes: 4 additions & 0 deletions packages/vstory/src/story/character/component/character.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ export abstract class CharacterComponent extends CharacterBase {
graphicType: this.graphicType
};
}

release() {
this.option.graphicParent.removeChild(this._group);
}
}

// export abstract class CharacterGraphicComponent extends CharacterBase {
Expand Down
1 change: 1 addition & 0 deletions packages/vstory/src/story/character/runtime-interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface ICharacter {
updateSpec: (spec: Omit<Partial<ICharacterSpec>, 'id' | 'type'>) => void;

setAttributes: (attr: Record<string, any>) => void;
release: () => void;
}

export interface ICharacterInitOption {
Expand Down
Loading

0 comments on commit 8b6e3f6

Please sign in to comment.