Skip to content

Commit

Permalink
fix:自然播放结束后重播 & 跳转时结束当前动画 (#283)
Browse files Browse the repository at this point in the history
* fix: 自然播放结束后重播情况

* fix: 结束上一个animator

* chore: 补充重播单测

---------

Co-authored-by: xuying.xu <[email protected]>
  • Loading branch information
tangying1027 and xuying.xu authored Jul 23, 2024
1 parent e796675 commit 3726d85
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 10 deletions.
21 changes: 12 additions & 9 deletions packages/f-engine/src/canvas/timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Timeline extends EE {
endFrame: number;
speed: number;
time: number;
totalDuration: number;

constructor(props) {
super();
Expand All @@ -29,6 +30,8 @@ class Timeline extends EE {
this.endFrame = animUnits.length - 1;
this.speed = speed;
this.time = time;

this.totalDuration = animUnits.reduce((accumulator, current) => accumulator + current.time, 0);
}

start() {
Expand Down Expand Up @@ -117,9 +120,14 @@ class Timeline extends EE {
}

goTo(time) {
const { frame, animUnits, playState } = this;
let target;
const { frame, animUnits, playState, totalDuration } = this;
// 超出了总时长
if (time > totalDuration && playState !== 'finish') {
this.setFinishState();
return;
}

let target;
for (target = 0; target < animUnits.length; target++) {
const cur = animUnits[target];
if (time >= cur.time) {
Expand All @@ -129,16 +137,11 @@ class Timeline extends EE {
}
}

// 超出了总时长
const threshold = 0.0001;
if (target === animUnits.length && Math.abs(time - threshold) >= 0) {
this.setFinishState();
return;
}

if (frame !== target) {
this.frame = target;
this.drawFrame();
// 结束当前动画
this.setPlayState('finish');
this.animator.run();
this.setPlayState(playState);
}
Expand Down
10 changes: 10 additions & 0 deletions packages/f-engine/src/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ class Player extends Component<PlayerProps> {
const { state, goTo: nextTime, speed: newSpeed } = nextProps;
const { goTo: lastTime, speed: lastSpeed } = lastProps;

if (!isEqual(state, timeline.getPlayState()) && timeline.getPlayState() === 'finish') {
// 重播
if (nextTime < timeline.totalDuration) {
timeline.updateState(state);
timeline.goTo(nextTime);
}
//保持结束播放状态
return;
}

// state 更新
if (!isEqual(state, timeline.getPlayState())) {
timeline.updateState(state);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
132 changes: 131 additions & 1 deletion packages/f-engine/test/timeline/player.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ describe('player', () => {
easing: 'linear',
duration: 10,
property: ['width'],
start: {
width: 5,
},
},
update: {
easing: 'linear',
duration: 10,
property: ['x', 'fill', 'width', 'height'],
property: ['x', 'fill', 'width', 'height', 'opacity'],
},
}}
/>
Expand Down Expand Up @@ -266,6 +269,133 @@ describe('player', () => {
Number(canvas.container.childNodes[1].childNodes[0].childNodes[0].childNodes[0].style.width),
).toEqual(40);
});

it('多组动画回跳', async () => {
const context = createContext('多组动画回跳');
const ref = { current: null };
const { props } = (
<Canvas context={context}>
<Player
state="pause"
goTo={2000}
ref={ref}
keyFrames={[
{
view: {
to: {
visible: true,
width: '80px',
},
duration: 400,
},
},
{
view: {
to: {
width: '200px',
},
duration: 800,
},
},
]}
>
<View key={'view'} visible={false} />
</Player>
</Canvas>
);

const canvas = new Canvas(props);
await canvas.render();

ref.current.goTo(700);
ref.current.setPlayState('pause');
await delay(200);
ref.current.goTo(200);
ref.current.setPlayState('pause');
await delay(200);

ref.current.setPlayState('play');

await delay(2000);
expect(context).toMatchImageSnapshot();
});

it('自然播放结束后重播', async () => {
const context = createContext('自然播放结束后重播');
const ref = { current: null };
const { props } = (
<Canvas context={context}>
<Player
state="play"
goTo={0}
ref={ref}
keyFrames={[
{
view: {
to: {
visible: true,
},
duration: 200,
},
},
{
view: {
to: {
width: '200px',
},
duration: 200,
},
},
]}
>
<View key={'view'} visible={false} />
</Player>
</Canvas>
);

const canvas = new Canvas(props);
await canvas.render();
await delay(1000);

const { props: newProps } = (
<Canvas context={context}>
<Player
state="pause"
goTo={0}
ref={ref}
keyFrames={[
{
view: {
to: {
visible: true,
},
duration: 200,
},
},
{
view: {
to: {
width: '200px',
},
duration: 200,
},
},
]}
>
<View key={'view'} visible={false} />
</Player>
</Canvas>
);
await canvas.update(newProps);
// 重播
await canvas.update(props);
await delay(10);

expect(
//@ts-ignore
Number(canvas.container.getElementsByTagName('rect')[0].style.width),
).toBeLessThan(10);
});
});

describe('clip animation', () => {
Expand Down

0 comments on commit 3726d85

Please sign in to comment.