UIKit Dynamics คือเฟรมเวิร์กแอนิเมชันทางกายภาพใน iOS (UIKit) ที่ช่วยให้ Views สามารถโต้ตอบตามกฎฟิสิกส์จริง: แรงโน้มถ่วง การชน ความยืดหยุ่น และแรงดึงดูด บทความนี้อธิบายส่วนประกอบของ UIDynamicAnimator ประเภทของพฤติกรรม (behavior) และสถานการณ์การใช้งานจริง
ประเด็นสำคัญ
UIKit Dynamics คือเฟรมเวิร์กการจำลองฟิสิกส์ที่ Apple นำเสนอใน iOS 7 (2013) แตกต่างจาก UIView.animate (การเปลี่ยนภาพเชิงเส้น) และ Core Animation (แอนิเมชันเลเยอร์) UIKit Dynamics จำลองปฏิสัมพันธ์ทางกายภาพจริง: แรงโน้มถ่วง การชน แรง ความยืดหยุ่น และแรงเสียดทาน นักพัฒนาเพิ่มพฤติกรรมไปยัง UIDynamicAnimator และระบบจะคำนวณฟิสิกส์โดยอัตโนมัติสำหรับแต่ละเฟรม
เฟรมเวิร์กทำงานที่ 60/120 FPS และใช้เอ็นจินฟิสิกส์ในตัวที่อิงจากการจำลองวัตถุแข็งเกร็ง (rigid body simulation) UIKit Dynamics ไม่ต้องการความรู้ด้านฟิสิกส์หรือคณิตศาสตร์ — เพแยงใช้พฤติกรรมสำเร็จรูปและกำหนดค่าพารามิเตอร์
ตามข้อมูลของ Apple UIKit Dynamics เหมาะสำหรับเอฟเฟกต์ UI (แอนิเมชันกองการ์ด การสั่นไหวของไอคอน ฟิสิกส์อินเทอร์เฟซ) แต่ไม่ได้มีไว้สำหรับเกม — สำหรับเกมให้ใช้ SceneKit หรือ SpriteKit
UIDynamicAnimator คือคลาสหลักของ UIKit Dynamics มันเริ่มต้นด้วย reference view (โดยปกติคือ view ของคอนโทรลเลอร์) และจัดการพฤติกรรมที่ทำงานอยู่ทั้งหมด แต่ละเฟรม UIDynamicAnimator จะคำนวณตำแหน่ง ความเร็ว และความเร่งขององค์ประกอบทั้งหมดที่เพิ่มตามกฎฟิสิกส์
เมธอด addBehavior เพิ่มหนึ่งพฤติกรรม (หรือ UIDynamicBehavior ที่ซับซ้อน) removeBehavior ลบออก ตัวแอนิเมเตอร์จะหยุดชั่วคราวโดยอัตโนมัติเมื่อวัตถุทั้งหมดถึงสถานะพัก (ดำเนินการต่อโดยไม่มีการชนและแรง) เมธอดตัวแทน — UIDynamicAnimatorDelegate — แจ้งเตือนเกี่ยวกับการหยุดชั่วคราวและการเริ่มจำลองอีกครั้ง
วัตถุใด ๆ ที่เข้าร่วมในฟิสิกส์ต้องใช้โปรโตคอล UIDynamicItem UIView และ UICollectionViewLayoutAttributes ใช้งานอยู่แล้ว โปรโตคอลต้องการคุณสมบัติ: bounds, center, transform หากวัตถุเป็นแบบกำหนดเอง — ให้ใช้โปรโตคอลด้วยตนเอง
UIKit Dynamics ประกอบด้วยพฤติกรรมในตัวเจ็ดประเภท แต่ละประเภทจำลองเอฟเฟกต์ทางกายภาพเฉพาะ สามารถรวมพฤติกรรมได้: ตัวอย่างเช่น แรงโน้มถ่วง + การชน + ความยืดหยุ่น สร้างเอฟเฟกต์ของวัตถุที่ตกลงและกระดอน
| Behavior | เอฟเฟกต์ทางกายภาพ | พารามิเตอร์สำคัญ |
|---|---|---|
| UIGravityBehavior | แรงโน้มถ่วง (เวกเตอร์แรง) | gravityDirection (dx, dy), magnitude |
| UICollisionBehavior | การชนของวัตถุและขอบเขต | collisionMode, translucence, collisionDelegate |
| UIAttachmentBehavior | การเชื่อมต่อ (สปริง/สายเคเบิล) | anchorPoint, length, damping, frequency |
| UISnapBehavior | การดูดไปยังจุดด้วยการหน่วง | snapPoint, damping (0-1) |
| UIPushBehavior | การผลัก/แรงกระตุ้น (ต่อเนื่องหรือทันที) | pushDirection, magnitude, mode |
| UIDynamicItemBehavior | คุณสมบัติทางกายภาพของวัตถุ | elasticity, friction, density, resistance |
| UIFieldBehavior | สนามแรง (กระแสน้ำวน, แม่เหล็ก, รัศมี) | position, strength, falloff, region |
สำหรับฟิสิกส์วัตถุที่สมจริง ต้องใช้หลายพฤติกรรมพร้อมกัน ตัวอย่างเช่น สำหรับการ์ดที่ตกลง: UIGravityBehavior (แรงโน้มถ่วง), UICollisionBehavior (การชนกับพื้น), UIDynamicItemBehavior (ความยืดหยุ่น: 0.4 สำหรับการกระดอน) พฤติกรรมทั้งหมดถูกเพิ่มไปยัง UIDynamicAnimator ตัวเดียว
โค้ด Swift สำหรับ UIKit Dynamics สร้าง UIDynamicAnimator และเพิ่มพฤติกรรม ตัวอย่างด้านล่างสาธิตแรงโน้มถ่วงกับหลายวัตถุ การชน และคุณสมบัติทางกายภาพที่กำหนดเอง
import UIKit
class PhysicsViewController: UIViewController {
var animator: UIDynamicAnimator!
override func viewDidLoad() {
super.viewDidLoad()
// 1. สร้างแอนิเมเตอร์ด้วย reference view
animator = UIDynamicAnimator(referenceView: view)
// 2. สร้างวัตถุที่ตกลงมา
let redView = UIView(frame: CGRect(x: 100, y: 50, width: 60, height: 60))
redView.backgroundColor = .systemRed
redView.layer.cornerRadius = 8
view.addSubview(redView)
let blueView = UIView(frame: CGRect(x: 200, y: 30, width: 60, height: 60))
blueView.backgroundColor = .systemBlue
blueView.layer.cornerRadius = 8
view.addSubview(blueView)
// 3. แรงโน้มถ่วง
let gravity = UIGravityBehavior(items: [redView, blueView])
gravity.gravityDirection = CGVector(dx: 0, dy: 1)
gravity.magnitude = 0.8
animator.addBehavior(gravity)
// 4. การชน
let collision = UICollisionBehavior(items: [redView, blueView])
collision.translatesReferenceBoundsIntoBoundary = true
collision.collisionDelegate = self
animator.addBehavior(collision)
// 5. คุณสมบัติทางกายภาพ
let itemBehavior = UIDynamicItemBehavior(items: [redView, blueView])
itemBehavior.elasticity = 0.6
itemBehavior.friction = 0.3
itemBehavior.density = 1.0
animator.addBehavior(itemBehavior)
// 6. พฤติกรรม Snap เมื่อแตะ
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
view.addGestureRecognizer(tap)
}
@objc
func handleTap(_ gesture: UITapGestureRecognizer) {
let point = gesture.location(in: view)
// พฤติกรรม Snap สำหรับแต่ละวัตถุ
for subview in view.subviews where subview is UIView {
animator.removeAllBehaviors()
let snap = UISnapBehavior(item: subview, snapTo: point)
snap.damping = 0.5
animator.addBehavior(snap)
}
}
}
extension PhysicsViewController: UICollisionBehaviorDelegate {
func collisionBehavior(_ behavior: UICollisionBehavior,
beganContactFor item1: UIDynamicItem,
with item2: UIDynamicItem,
at point: CGPoint) {
print("การชนที่: (จุด)")
}
}ตัวอย่างสร้างสอง Views ด้วยแรงโน้มถ่วง การชน และคุณสมบัติทางกายภาพ UISnapBehavior เมื่อแตะจะดูดวัตถุไปยังจุดสัมผัสด้วยการหน่วง 0.5 UICollisionBehaviorDelegate ติดตามการเริ่มต้นของการชนสำหรับเอฟเฟกต์เสียงและภาพ
UIKit Dynamics ใช้ในแอปพลิเคชัน iOS สำหรับฟิสิกส์อินเทอร์เฟซที่ไม่ใช่เกม สถานการณ์ยอดนิยม: แอนิเมชันกองการ์ด (UISnapBehavior สำหรับดูดไปยังศูนย์กลาง), การเขย่าหน้าจอเมื่อเกิดข้อผิดพลาด (UIDynamicItemBehavior + UIPushBehavior), เอฟเฟกต์ "ดาวตก" ในออนบอร์ดิง (gravity + collision + field behavior)
สำหรับประสิทธิภาพ UIKit Dynamics แนะนำไม่เกิน 15-20 วัตถุพร้อมกันที่มีฟิสิกส์ แต่ละวัตถุต้องการการคำนวณการชนและแรงในทุกเฟรม หากเกินขีดจำกัด ให้ใช้ CALayer แทน UIView — Core Animation จัดการเลเยอร์ได้อย่างมีประสิทธิภาพมากขึ้น
คำถามที่พบบ่อย
UIKit Dynamics จำลองปฏิสัมพันธ์ทางกายภาพ (แรงโน้มถ่วง การชน แรง) โดยอิงจากการจำลองวัตถุแข็งเกร็ง Core Animation ทำให้คุณสมบัติของ CALayer (position, opacity, transform) เคลื่อนไหวตามเส้นโค้งเวลาที่กำหนด Dynamics เหมาะสำหรับฟิสิกส์เชิงโต้ตอบ Core Animation สำหรับการเปลี่ยนภาพที่กำหนดไว้ล่วงหน้า
ไม่มีการสนับสนุนโดยตรงสำหรับ UIKit Dynamics ใน SwiftUI สำหรับเอฟเฟกต์ทางกายภาพ ให้ใช้ UIKitView + UIDynamicAnimator ภายใน UIViewRepresentable หรือแอนิเมชันที่กำหนดเองผ่าน Animation.spring() และ withAnimation() ใน SwiftUI
เรียก animator.removeAllBehaviors() — ซึ่งจะลบพฤติกรรมทางกายภาพที่ทำงานอยู่ทั้งหมด ตัวแอนิเมเตอร์จะหยุดชั่วคราวโดยอัตโนมัติเมื่อวัตถุทั้งหมดถึงสถานะพัก สำหรับการหยุดชั่วคราว ให้ใช้คุณสมบัติ animator.isPaused หรือลบพฤติกรรมแต่ละรายการ
Apple แนะนำไม่เกิน 15-20 วัตถุ ที่มีฟิสิกส์เต็มรูปแบบ (แรงโน้มถ่วง + การชน + แรง) สำหรับแอนิเมชันจำนวนมาก ให้ใช้ UIFieldBehavior — มันคำนวณแรงจากศูนย์กลางโดยไม่ต้องชนแบบคู่ ซึ่งลดภาระของ CPU
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม