UIKit Dynamics はiOS(UIKit)の物理アニメーションフレームワークで、Viewが現実の物理法則(重力、衝突、弾性、引力)に従って相互作用できるようにします。この記事では、UIDynamicAnimatorのコンポーネント、ビヘイビアの種類、実用的な使用シナリオについて説明します。
重要なポイント
UIKit Dynamics は、AppleがiOS 7(2013)で導入した物理シミュレーションフレームワークです。UIView.animate(線形遷移)やCore Animation(レイヤーアニメーション)とは異なり、UIKit Dynamicsは重力、衝突、力、弾性、摩擦などの実際の物理的相互作用をシミュレートします。開発者はUIDynamicAnimatorにビヘイビアを追加し、システムが各フレームの物理演算を自動的に計算します。
このフレームワークは60/120 FPSで動作し、剛体シミュレーションに基づく組み込み物理エンジンを使用します。UIKit Dynamicsは物理学や数学の知識を必要としません — 既製のビヘイビアを適用してパラメータを設定するだけです。
Appleによると、UIKit DynamicsはUI効果(カードスタックアニメーション、アイコンの揺れ、インターフェース物理)に適していますが、ゲームを目的としていません — ゲームにはSceneKitまたはSpriteKitを使用してください。
UIDynamicAnimator はUIKit Dynamicsの中心的なクラスです。reference view(通常はコントローラーのview)で初期化され、すべてのアクティブなビヘイビアを管理します。各フレームでUIDynamicAnimatorは、物理法則に従って追加されたすべての要素の位置、速度、加速度を再計算します。
addBehaviorメソッドは1つのビヘイビア(または複雑なUIDynamicBehavior)を追加し、removeBehaviorはそれを削除します。アニメーターは、すべてのオブジェクトが静止状態に達すると自動的に一時停止します(衝突や力のない継続)。デリゲートメソッド — UIDynamicAnimatorDelegate — はシミュレーションの一時停止と再開を通知します。
物理演算に参加するオブジェクトは、UIDynamicItemプロトコルを実装する必要があります。UIViewとUICollectionViewLayoutAttributesはすでに実装しています。プロトコルには、bounds、center、transformのプロパティが必要です。オブジェクトがカスタムの場合は、手動でプロトコルを実装してください。
UIKit Dynamics には7つの組み込みビヘイビアタイプが含まれており、それぞれが特定の物理効果をモデル化します。ビヘイビアは組み合わせることができます:例えば、重力 + 衝突 + 弾性は、落下して跳ね返るオブジェクトの効果を生み出します。
| 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)。すべてのビヘイビアは1つのUIDynamicAnimatorに追加されます。
UIKit DynamicsのSwiftコードは、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("衝突位置: (ポイント)")
}
}この例では、重力、衝突、物理プロパティを持つ2つのViewを作成します。タップ時のUISnapBehaviorは、0.5の減衰でオブジェクトをタッチポイントにスナップします。UICollisionBehaviorDelegateは、サウンドと視覚効果のために衝突の開始を追跡します。
UIKit Dynamics は、iOSアプリケーションで非ゲーム系のインターフェース物理に使用されます。一般的なシナリオ:カードスタックアニメーション(中央へのスナップにUISnapBehavior)、エラー時の画面シェイク(UIDynamicItemBehavior + UIPushBehavior)、オンボーディングでの「流れ星」効果(gravity + collision + field behavior)。
パフォーマンス面では、UIKit Dynamicsは物理演算を持つオブジェクトを同時に15〜20個以下にすることを推奨しています。各オブジェクトは毎フレーム衝突と力の計算を必要とします。制限を超えた場合は、UIViewの代わりにCALayerを使用してください — Core Animationはレイヤーをより効率的に処理します。
よくある質問
UIKit Dynamics は剛体シミュレーションに基づいて物理的相互作用(重力、衝突、力)をモデル化します。Core Animation は指定された時間曲線に沿ってCALayerのプロパティ(position、opacity、transform)をアニメーション化します。Dynamicsはインタラクティブな物理に適しており、Core Animationは事前定義された遷移に適しています。
SwiftUIにUIKit Dynamicsの直接サポートはありません。物理効果を得るには、UIViewRepresentable内でUIKitView + UIDynamicAnimatorを使用するか、SwiftUIのAnimation.spring()やwithAnimation()を使用してカスタムアニメーションを作成してください。
animator.removeAllBehaviors() を呼び出します — これによりすべてのアクティブな物理ビヘイビアが削除されます。アニメーターはすべてのオブジェクトが静止すると自動的に一時停止します。一時的な停止には、animator.isPausedプロパティを使用するか、個別のビヘイビアを削除してください。
Appleは完全な物理演算(重力 + 衝突 + 力)を持つオブジェクトを15〜20個以下にすることを推奨しています。大量のアニメーションにはUIFieldBehaviorを使用してください — これはペアワイズ衝突なしで力を集中的に計算し、CPU負荷を軽減します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。