- 
							
							SwiftUIアニメーションの詳細SwiftUIの有能なアニメーション機能がどのように印象的な視覚効果を生み出すかを学びましょう。SwiftUIがどのようにViewを再レンダリングし、何をアニメーションさせるかを決定し、値を補間し、直近のトランザクションのコンテキストを伝達するかを学びましょう。 関連する章- 1:03 - Anatomy of an update
- 6:40 - Animatable
- 11:36 - Animation
- 20:00 - Transaction
 リソース関連ビデオWWDC23
- 
							このビデオを検索
- 
							- 
										
										2:14 - Pet Avatar - Unanimated struct Avatar: View { var pet: Pet @State private var selected: Bool = false var body: some View { Image(pet.type) .scaleEffect(selected ? 1.5 : 1.0) .onTapGesture { selected.toggle() } } }
- 
										
										4:13 - Pet Avatar - Animated struct Avatar: View { var pet: Pet @State private var selected: Bool = false var body: some View { Image(pet.type) .scaleEffect(selected ? 1.5 : 1.0) .onTapGesture { withAnimation { selected.toggle() } } } }
- 
										
										11:49 - Pet Avatar - Explicit Animation struct Avatar: View { var pet: Pet @State private var selected: Bool = false var body: some View { Image(pet.type) .scaleEffect(selected ? 1.5 : 1.0) .onTapGesture { withAnimation(.bouncy) { selected.toggle() } } } }
- 
										
										12:48 - UnitCurve Model let curve = UnitCurve( startControlPoint: UnitPoint(x: 0.25, y: 0.1), endControlPoint: UnitPoint(x: 0.25, y: 1)) curve.value(at: 0.25) curve.velocity(at: 0.25)
- 
										
										13:56 - Spring Model let spring = Spring(duration: 1.0, bounce: 0) spring.value(target: 1, time: 0.25) spring.velocity(target: 1, time: 0.25)
- 
										
										17:25 - MyLinearAnimation struct MyLinearAnimation: CustomAnimation { var duration: TimeInterval func animate<V: VectorArithmetic>( value: V, time: TimeInterval, context: inout AnimationContext<V> ) -> V? { if time <= duration { value.scaled(by: time / duration) } else { nil // animation has finished } } }
- 
										
										19:50 - MyLinearAnimation with Velocity struct MyLinearAnimation: CustomAnimation { var duration: TimeInterval func animate<V: VectorArithmetic>( value: V, time: TimeInterval, context: inout AnimationContext<V> ) -> V? { if time <= duration { value.scaled(by: time / duration) } else { nil // animation has finished } } func velocity<V: VectorArithmetic>( value: V, time: TimeInterval, context: AnimationContext<V> ) -> V? { value.scaled(by: 1.0 / duration) } }
- 
										
										22:44 - Pet Avatar - Animation Modifier struct Avatar: View { var pet: Pet @Binding var selected: Bool var body: some View { Image(pet.type) .scaleEffect(selected ? 1.5 : 1.0) .animation(.bouncy, value: selected) .onTapGesture { selected.toggle() } } }
- 
										
										23:44 - Pet Avatar - Multiple Animation Modifiers struct Avatar: View { var pet: Pet @Binding var selected: Bool var body: some View { Image(pet.type) .shadow(radius: selected ? 12 : 8) .animation(.smooth, value: selected) .scaleEffect(selected ? 1.5 : 1.0) .animation(.bouncy, value: selected) .onTapGesture { selected.toggle() } } }
- 
										
										25:20 - Generic Avatar - Scoped Animation Modifiers struct Avatar<Content: View>: View { var content: Content @Binding var selected: Bool var body: some View { content .animation(.smooth) { $0.shadow(radius: selected ? 12 : 8) } .animation(.bouncy) { $0.scaleEffect(selected ? 1.5 : 1.0) } .onTapGesture { selected.toggle() } } }
- 
										
										28:45 - Pet Avatar - Transaction Modifier struct Avatar: View { var pet: Pet @Binding var selected: Bool var body: some View { Image(pet.type) .scaleEffect(selected ? 1.5 : 1.0) .transaction(value: selected) { $0.animation = $0.avatarTapped ? .bouncy : .smooth } .onTapGesture { withTransaction(\.avatarTapped, true) { selected.toggle() } } } } private struct AvatarTappedKey: TransactionKey { static let defaultValue = false } extension Transaction { var avatarTapped: Bool { get { self[AvatarTappedKey.self] } set { self[AvatarTappedKey.self] = newValue } } }
- 
										
										28:58 - Generic Avatar - Scoped Transaction Modifier struct Avatar<Content: View>: View { var content: Content @Binding var selected: Bool var body: some View { content .transaction { $0.animation = $0.avatarTapped ? .bouncy : .smooth } body: { $0.scaleEffect(selected ? 1.5 : 1.0) } .onTapGesture { withTransaction(\.avatarTapped, true) { selected.toggle() } } } } private struct AvatarTappedKey: TransactionKey { static let defaultValue = false } extension Transaction { var avatarTapped: Bool { get { self[AvatarTappedKey.self] } set { self[AvatarTappedKey.self] = newValue } } }
 
-