reanimated-skia-performance by andreev-danila/skills
npx skills add https://github.com/andreev-danila/skills --skill reanimated-skia-performanceuseSharedValue、useDerivedValue 和 worklets。Animated。shared.get() / shared.set() 而非 shared.value(对 React Compiler 友好)。scheduleOnRN/runOnJS。SharedValue 直接传递给 Skia 属性或 uniforms。广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
withTiming;对于物理动画,使用 withSpring;对于动量动画,使用 withDecay。setState)。references/perf-checklist.md)。progress.get()progress.set(withTiming(1))import { useEffect } from 'react';
import { useSharedValue, withTiming } from 'react-native-reanimated';
const progress = useSharedValue(0);
useEffect(() => {
progress.set(withTiming(1, { duration: 400 }));
}, [progress]);
适用于状态驱动的样式变化,且无需编写自定义 worklets。
import Animated from 'react-native-reanimated';
<Animated.View
style={{
width: expanded ? 240 : 160,
opacity: enabled ? 1 : 0.6,
transitionProperty: ['width', 'opacity'],
transitionDuration: 220,
transitionTimingFunction: 'ease-in-out',
}}
/>
适用于类似关键帧的序列(脉冲、摆动、重复循环),而无需编写自定义 worklets。
支持的设置:
animationName(关键帧对象)animationDurationanimationDelayanimationTimingFunctionanimationDirectionanimationIterationCountanimationFillModeanimationPlayStateimport Animated from 'react-native-reanimated';
const pulse = {
from: { transform: [{ scale: 1 }], opacity: 0.9 },
'50%': { transform: [{ scale: 1.06 }], opacity: 1 },
to: { transform: [{ scale: 1 }], opacity: 0.9 },
};
<Animated.View
style={{
animationName: pulse,
animationDuration: '900ms',
animationDelay: '80ms',
animationTimingFunction: 'ease-in-out',
animationDirection: 'alternate',
animationIterationCount: 'infinite',
animationFillMode: 'both',
animationPlayState: paused ? 'paused' : 'running',
}}
/>
在 __DEV__ 模式下使用滑块来调整动画配置或着色器 uniforms。
.set() 将滑块值写入 SharedValue。useDerivedValue 将 SharedValue 作为 uniforms 传入。SharedValue 中,并在启动/重启动画时读取它们。参见:references/dev-tuning.md。
在 onUpdate 中更新共享值,并通过动画样式驱动视觉效果。
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
const x = useSharedValue(0);
const gesture = Gesture.Pan()
.onUpdate((e) => {
x.set(e.translationX);
})
.onEnd(() => {
x.set(withSpring(0));
});
const style = useAnimatedStyle(() => ({ transform: [{ translateX: x.get() }] }));
<GestureDetector gesture={gesture}>
<Animated.View style={style} />
</GestureDetector>;
useMemo)。SharedValue<Uniforms> 传递(Skia 通过 { value: T } 检测动画属性)。.value;传递 SharedValue 对象。import { useMemo } from 'react';
import { Skia, Canvas, Fill, Paint, Shader, type Uniforms } from '@shopify/react-native-skia';
import { useDerivedValue } from 'react-native-reanimated';
import { useClock } from '@shopify/react-native-skia';
const sksl = `
uniform float2 u_resolution;
uniform float u_time;
half4 main(float2 xy) {
float2 uv = xy / u_resolution;
float v = 0.5 + 0.5 * sin(u_time * 0.002 + uv.x * 8.0);
return half4(v, v * 0.6, 1.0 - v, 1.0);
}
`;
const effect = useMemo(() => Skia.RuntimeEffect.Make(sksl), []);
if (!effect) return null;
const clock = useClock(); // 自第一帧以来的毫秒数
const uniforms = useDerivedValue<Uniforms>(() => ({
u_resolution: Skia.Point(width, height),
u_time: clock.get(),
}));
<Canvas style={{ width, height }}>
<Fill>
<Paint>
<Shader source={effect} uniforms={uniforms} />
</Paint>
</Fill>
</Canvas>;
useAnimatedStyle、useDerivedValue)中读取它们。onUpdate 中调用 runOnJS/scheduleOnRN。references/reanimated-v4.mdreferences/skia-shaders.mdreferences/dev-tuning.mdreferences/perf-checklist.md每周安装量
292
仓库
GitHub 星标数
22
首次出现
2026年1月20日
安全审计
安装于
opencode238
gemini-cli234
codex231
github-copilot212
claude-code209
cursor208
useSharedValue, useDerivedValue, worklets.Animated.shared.get() / shared.set() over shared.value in app code (React Compiler friendly).scheduleOnRN/runOnJS except for unavoidable side effects.SharedValues directly to Skia props/uniforms.withTiming for tweens, withSpring for physics, withDecay for momentum.setState per frame).references/perf-checklist.md).Read: progress.get()
Write: progress.set(withTiming(1))
import { useEffect } from 'react'; import { useSharedValue, withTiming } from 'react-native-reanimated';
const progress = useSharedValue(0);
useEffect(() => { progress.set(withTiming(1, { duration: 400 })); }, [progress]);
Use for state-driven style changes where you do not need bespoke worklets.
import Animated from 'react-native-reanimated';
<Animated.View
style={{
width: expanded ? 240 : 160,
opacity: enabled ? 1 : 0.6,
transitionProperty: ['width', 'opacity'],
transitionDuration: 220,
transitionTimingFunction: 'ease-in-out',
}}
/>
Use for keyframe-like sequences (pulses, wiggles, repeated loops) without writing custom worklets.
Supported settings:
animationName (keyframes object)
animationDuration
animationDelay
animationTimingFunction
animationDirection
animationIterationCount
animationFillMode
animationPlayState
import Animated from 'react-native-reanimated';
Use sliders to tune animation configs or shader uniforms in __DEV__.
SharedValues via .set().SharedValues into uniforms via useDerivedValue.SharedValues and read them when starting/restarting the animation.See: references/dev-tuning.md.
Update shared values in onUpdate and drive visuals via animated styles.
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
const x = useSharedValue(0);
const gesture = Gesture.Pan()
.onUpdate((e) => {
x.set(e.translationX);
})
.onEnd(() => {
x.set(withSpring(0));
});
const style = useAnimatedStyle(() => ({ transform: [{ translateX: x.get() }] }));
<GestureDetector gesture={gesture}>
<Animated.View style={style} />
</GestureDetector>;
Compile the runtime effect once (useMemo).
Pass uniforms as a SharedValue<Uniforms> (Skia detects animated props by { value: T }).
Do not access .value in your app code; pass the SharedValue object.
import { useMemo } from 'react'; import { Skia, Canvas, Fill, Paint, Shader, type Uniforms } from '@shopify/react-native-skia'; import { useDerivedValue } from 'react-native-reanimated'; import { useClock } from '@shopify/react-native-skia';
const sksl = ` uniform float2 u_resolution; uniform float u_time;
half4 main(float2 xy) { float2 uv = xy / u_resolution; float v = 0.5 + 0.5 * sin(u_time * 0.002 + uv.x * 8.0); return half4(v, v * 0.6, 1.0 - v, 1.0); } `;
const effect = useMemo(() => Skia.RuntimeEffect.Make(sksl), []); if (!effect) return null;
const clock = useClock(); // ms since first frame const uniforms = useDerivedValue<Uniforms>(() => ({ u_resolution: Skia.Point(width, height), u_time: clock.get(), }));
<Canvas style={{ width, height }}> <Fill> <Paint> <Shader source={effect} uniforms={uniforms} /> </Paint> </Fill> </Canvas>;
useAnimatedStyle, useDerivedValue).runOnJS/scheduleOnRN in onUpdate unless you must.references/reanimated-v4.mdreferences/skia-shaders.mdreferences/dev-tuning.mdreferences/perf-checklist.mdWeekly Installs
292
Repository
GitHub Stars
22
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode238
gemini-cli234
codex231
github-copilot212
claude-code209
cursor208
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
105,000 周安装
const pulse = { from: { transform: [{ scale: 1 }], opacity: 0.9 }, '50%': { transform: [{ scale: 1.06 }], opacity: 1 }, to: { transform: [{ scale: 1 }], opacity: 0.9 }, };
<Animated.View style={{ animationName: pulse, animationDuration: '900ms', animationDelay: '80ms', animationTimingFunction: 'ease-in-out', animationDirection: 'alternate', animationIterationCount: 'infinite', animationFillMode: 'both', animationPlayState: paused ? 'paused' : 'running', }} />