แอนิเมชันแบบสปริงและการลดความเร็ว
ใช้ Animated.spring เพื่อสร้างการเคลื่อนไหวตามหลักฟิสิกส์ที่เด้งได้ ปรับพารามิเตอร์ tension และ friction และใช้ Animated.decay เพื่อสร้างเอฟเฟกต์การเลื่อนตามแรงเฉื่อย
แอนิเมชันแบบสปริงและการลดความเร็ว เป็นบทเรียน React Native Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Native Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Beyond Linear: Physics-Based Motion
Linear timing animations feel mechanical because real-world objects rarely move at a constant speed. Physics-based animations simulate natural forces like springs and momentum, making UI motion feel alive and natural. React Native's Animated API provides two physics engines: Animated.spring for elastic bounce and Animated.decay for momentum-based deceleration.
Choosing the right animation type dramatically affects perceived quality. Timing suits opacity fades; spring suits interactive elements like buttons and cards; decay suits swipe-to-dismiss gestures.
Animated.spring: Bouncy Motion
Animated.spring simulates a spring pulling a value toward a target. The value overshoots the target and oscillates until it settles — the classic bouncy effect. At minimum you provide toValue and useNativeDriver.
Spring animations feel natural for elements that respond to user interaction, such as a button scaling up on press or a modal sliding in from below. The default spring parameters are already tuned to feel good on mobile, but you can customize them.
import { Animated } from 'react-native';
import { useRef } from 'react';
const scale = useRef(new Animated.Value(0)).current;
Animated.spring(scale, {
toValue: 1,
useNativeDriver: true,
}).start();Tuning Spring with Tension and Friction
The feel of a spring animation is controlled by two parameters: tension and friction. Tension controls how fast the spring pulls toward the target — higher tension means faster, snappier motion. Friction controls how quickly the oscillations dampen out — lower friction means more bouncing.
The default tension is 40 and friction is 7. For a quick, responsive feel try tension 100, friction 10. For a slow, wobbly effect try tension 20, friction 3. Experiment to find the right feel for your UI.
Animated.spring(scale, {
toValue: 1,
tension: 100, // higher = snappier
friction: 10, // higher = less bouncy
useNativeDriver: true,
}).start();
// Wobbly alternative:
Animated.spring(scale, {
toValue: 1,
tension: 20,
friction: 3,
useNativeDriver: true,
}).start();Spring with Stiffness, Mass, and Damping
React Native also supports a more physics-accurate spring model using stiffness, mass, and damping. These correspond to physical properties of a spring system — stiffness is the spring constant, mass is the object weight, and damping is the drag coefficient.
This model is compatible with iOS UIKit spring animations and Framer Motion on the web, making it easier to match animations designed in prototyping tools. Use either the tension/friction model or the stiffness/mass/damping model — not both at once.
Animated.spring(translateY, {
toValue: 0,
stiffness: 120,
mass: 1,
damping: 14,
useNativeDriver: true,
}).start();Building a Spring Button Press Effect
A common spring animation pattern is scaling a button down slightly on press and back to full size on release, giving satisfying tactile feedback. Use Pressable with onPressIn and onPressOut to trigger spring animations on the scale value.
The quick spring-down on press and spring-back on release makes buttons feel physical and responsive. This is more satisfying than a simple opacity change and is widely used in polished mobile apps.
const scale = useRef(new Animated.Value(1)).current;
const onPressIn = () => {
Animated.spring(scale, { toValue: 0.9, useNativeDriver: true }).start();
};
const onPressOut = () => {
Animated.spring(scale, { toValue: 1, useNativeDriver: true }).start();
};
return (
<Pressable onPressIn={onPressIn} onPressOut={onPressOut}>
<Animated.View style={{ transform: [{ scale }] }}>
<Text>Press Me</Text>
</Animated.View>
</Pressable>
);What Is Animated.decay?
Animated.decay simulates momentum: it starts a value moving at a given velocity and gradually slows it down over time, as if friction were acting on it. There is no target value — the animation runs until momentum runs out.
Decay is the natural complement to swipe gestures. When a user flicks a card or list, the release velocity from the gesture feeds directly into a decay animation, making the element continue moving and decelerate naturally — exactly how mobile apps behaved before digital UI.
// velocity is obtained from a gesture handler's onGestureEvent
Animated.decay(position, {
velocity: 0.8, // initial velocity (pixels per millisecond)
deceleration: 0.997, // how quickly momentum fades (0-1)
useNativeDriver: true,
}).start();Decay After a Swipe Gesture
The typical decay pattern: track the finger position during a pan gesture, and when the finger lifts pass the final velocity from the gesture to Animated.decay. The deceleration value (default 0.997) controls how quickly the item slows — closer to 1 means longer glide, closer to 0 means quick stop.
After decay finishes, you typically snap the item to a final state using a spring animation if needed (e.g., snapping a card back to center or to a dismissed position).
// In a PanResponder onPanResponderRelease:
onPanResponderRelease: (evt, gestureState) => {
Animated.decay(position, {
velocity: gestureState.vx, // velocity at finger lift
deceleration: 0.997,
useNativeDriver: true,
}).start(({ finished }) => {
if (finished) {
// optionally snap to final position
}
});
}Comparing Spring, Decay, and Timing
Understanding when to use each animation type is key to natural-feeling UI:
- Animated.timing — predictable, fixed duration. Best for UI feedback like opacity changes and progress bars where exact timing matters.
- Animated.spring — elastic, overshoots target. Best for responsive interactive elements like buttons, cards, and modal entrances.
- Animated.decay — momentum-based, no fixed end. Best for continuing motion after gesture releases like swipes and flicks.
Using velocity from User Interaction
Springs also have a velocity parameter that sets the initial velocity of the spring, making them connect naturally to gesture motion. When a user drags a card and releases, you can start a spring with the gesture's velocity to continue the motion smoothly.
This creates a seamless handoff between gesture and animation — the card feels like it was thrown by the user's hand rather than teleported to its resting position.
// After a pan gesture releases:
onPanResponderRelease: (evt, { vx, vy }) => {
Animated.spring(position, {
toValue: { x: 0, y: 0 }, // snap back to center
velocity: { x: vx, y: vy },
tension: 50,
friction: 8,
useNativeDriver: true,
}).start();
}Spring with Animated.ValueXY
Animated.ValueXY is a convenience wrapper that holds a pair of Animated.Values for x and y coordinates. It simplifies 2D animations like dragging cards. Spring and decay both work with ValueXY, and it has helper methods like getTranslateTransform() to produce the transform array automatically.
ValueXY reduces boilerplate when you need to animate an element's position in 2D space, as you don't need to manage two separate Animated.Values manually.
const position = useRef(new Animated.ValueXY({ x: 0, y: -200 })).current;
useEffect(() => {
Animated.spring(position, {
toValue: { x: 0, y: 0 },
useNativeDriver: true,
}).start();
}, []);
return (
<Animated.View style={position.getTranslateTransform()}>
<Text>Falls into place</Text>
</Animated.View>
);Resetting Animated Values
You can reset an Animated.Value to its initial state by calling .setValue(initialValue). This is useful before re-running an animation — for example, resetting a scale to 0 before running another pop-in spring, or resetting position before replaying an entry animation.
Always reset synchronously before starting the animation to avoid a flash. Call setValue inside the same event handler or useEffect, immediately followed by Animated.spring(...).start().
function replay() {
// Reset to start position
scale.setValue(0);
// Then spring to final position
Animated.spring(scale, {
toValue: 1,
tension: 80,
friction: 8,
useNativeDriver: true,
}).start();
}Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: Animated.spring creates physics-based bouncy motion tuned with tension and friction, Animated.decay simulates momentum-based deceleration from a starting velocity, and each animation type suits different interaction patterns — spring for tap feedback, decay for gesture release. Next up we explore composing multiple animations in parallel and sequence.
คำถามที่พบบ่อย
บทเรียน “แอนิเมชันแบบสปริงและการลดความเร็ว” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “แอนิเมชันแบบสปริงและการลดความเร็ว” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Native Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “แอนิเมชันแบบสปริงและการลดความเร็ว”
ใช้ Animated.spring เพื่อสร้างการเคลื่อนไหวตามหลักฟิสิกส์ที่เด้งได้ ปรับพารามิเตอร์ tension และ friction และใช้ Animated.decay เพื่อสร้างเอฟเฟกต์การเลื่อนตามแรงเฉื่อย คุณปฏิบัติ React Native Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Native Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Native Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “แอนิเมชันแบบสปริงและการลดความเร็ว” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน React Native Academy นี้ได้ไหม
ได้ บทเรียน React Native Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- Animated.Value และ Animated.View
- แอนิเมชันแบบสปริงและการลดความเร็ว
- การทำหลายคุณสมบัติให้เคลื่อนไหวแบบขนานและแบบลำดับ
- ใช้ useNativeDriver สำหรับแอนิเมชัน 60fps