-
Notifications
You must be signed in to change notification settings - Fork 476
/
Copy pathuseAnimatedImageValue.ts
52 lines (44 loc) · 1.54 KB
/
useAnimatedImageValue.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import type { FrameInfo, SharedValue } from "react-native-reanimated";
import { useAnimatedImage } from "../../skia/core/AnimatedImage";
import type { DataSourceParam, SkImage } from "../../skia/types";
import Rea from "./ReanimatedProxy";
const DEFAULT_FRAME_DURATION = 60;
export const useAnimatedImageValue = (
source: DataSourceParam,
paused?: SharedValue<boolean>
) => {
const defaultPaused = Rea.useSharedValue(false);
const isPaused = paused ?? defaultPaused;
const currentFrame = Rea.useSharedValue<null | SkImage>(null);
const lastTimestamp = Rea.useSharedValue(-1);
const animatedImage = useAnimatedImage(source, (err) => {
console.error(err);
throw new Error(`Could not load animated image - got '${err.message}'`);
});
const frameDuration =
animatedImage?.currentFrameDuration() || DEFAULT_FRAME_DURATION;
Rea.useFrameCallback((frameInfo: FrameInfo) => {
if (!animatedImage) {
currentFrame.value = null;
return;
}
if (isPaused.value && lastTimestamp.value !== -1) {
return;
}
const { timestamp } = frameInfo;
const elapsed = timestamp - lastTimestamp.value;
// Check if it's time to switch frames based on GIF frame duration
if (elapsed < frameDuration) {
return;
}
// Update the current frame
animatedImage.decodeNextFrame();
if (currentFrame.value) {
currentFrame.value.dispose();
}
currentFrame.value = animatedImage.getCurrentFrame();
// Update the last timestamp
lastTimestamp.value = timestamp;
});
return currentFrame;
};