> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/ios/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/ios/swiftui/anim/animatable.md).

# Animatable

[SwiftUI](/ios/swiftui.md) ⟩ [animations](/ios/swiftui/anim.md) ⟩ [Animatable](/ios/swiftui/anim/animatable.md) ⟩

{% hint style="success" %}
*<mark style="color:purple;">Animatable</mark>* describes how to <mark style="color:yellow;">animate a view with respect to some change in the view's data</mark>.&#x20;

* [`animatableData`](https://developer.apple.com/documentation/swiftui/animatable/animatabledata-6nydg): <mark style="color:yellow;">required</mark> computed property \
  (with <mark style="color:yellow;">default implementation</mark> by <mark style="color:red;">doing nothing</mark>)
* [Shape](/ios/swiftui/shapes/shape.md) conforms to *<mark style="color:purple;">Animatable</mark>*

Use *<mark style="color:purple;">Animatable</mark>* when you are unable to achieve the animation you want with [animation(\_:)](https://swiftontap.com/View/animation\(_:\)) or [withAnimation(\_:\_:)](https://swiftontap.com/withAnimation\(_:_:\)).
{% endhint %}

```swift
// ⭐️ 一維的 `animatableData`
var animatableData: CGFloat {
    get { return sides }
    set { sides = newValue }    // ⭐️ set new animation value
}
```

```swift
// ⭐️ 二維的 `animatableData` (AnimatablePair)
var animatableData: AnimatablePair<CGFloat, CGFloat> {
    get { AnimatablePair(sides, scale) }
    set {                        // ⭐️ set new animation value
        sides = newValue.first
        scale = newValue.second
    }
}
```

👉 see: [Polygon](/ios/swiftui/shapes/shape/polygon.md)

{% hint style="danger" %}
[**animatableData**](https://developer.apple.com/documentation/swiftui/animatable/animatabledata-swift.property-6nydg) 並不是 [＠State](/ios/swiftui/view/state/value/state.md) 屬性，所以如果在 view 中使用類似：

```swift
Text("\(animatableData)")
```

這樣的寫法，並不會產生任何動畫❗️
{% endhint %}

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="info" %}
By conforming to [Animatable](https://swiftontap.com/Animatable), you are able to effectively **decouple** the **animation** of your view from the concept of <mark style="color:orange;">**duration**</mark>, as you give SwiftUI the ability to **interpolate** arbitrarily between two different values for [animatableData](https://swiftontap.com/Animatable/animatableData-7101d). This is also the reason why [AnimatableData](https://swiftontap.com/Animatable/AnimatableData) must conform to [VectorArithmetic](https://swiftontap.com/VectorArithmetic), which provides the runtime means to <mark style="color:orange;">**add**</mark>, <mark style="color:orange;">**subtract**</mark> and <mark style="color:orange;">**scale**</mark> the animated values as necessary to generate data points for <mark style="color:orange;">**each frame**</mark> of the animation over an arbitrary time interval.
{% endhint %}

{% hint style="success" %}

* To expose <mark style="color:orange;">**two properties**</mark> as **animatable**, wrap them in an [AnimatablePair](https://developer.apple.com/documentation/swiftui/animatablepair).&#x20;
* nest [AnimatablePairs](https://developer.apple.com/documentation/swiftui/animatablepair) inside each other to support <mark style="color:orange;">**any number**</mark> of properties.
  {% endhint %}

{% hint style="success" %}
To examine how SwiftUI **interpolates** between diﬀerent values during an **animation**, we can add <mark style="color:yellow;">log statements</mark> to the <mark style="color:red;">**setter**</mark> of [animatableData](https://developer.apple.com/documentation/swiftui/animatable/animatabledata-swift.property-6nydg) or the <mark style="color:red;">**body**</mark> method of the [animatable modiﬁer](/ios/swiftui/anim/animatable/animatable-modifiers.md).
{% endhint %}

{% hint style="info" %}
related protocol: \`Animatable\`

* \`AnimatablePair\<First, Second>\`: animate ove 2 parameters
  {% endhint %}

{% hint style="info" %}

* \`Animatable\`: \
  Angle, CGPoint, CGRect, CGSize, EdgeInsets, StrokeStyle, UnitPoint.&#x20;
* \`VectorArithmetic\`: \
  AnimatablePair, CGFloat, Double, EmptyAnimatableData, Float.
  {% endhint %}

{% hint style="info" %}

* When you use the <mark style="color:red;">**animation(\_:)**</mark> modifier on an <mark style="color:red;">**equatable**</mark> view, SwiftUI animates any changes to <mark style="color:red;">**animatable**</mark> properties of the view. A view’s **color**, **opacity**, **rotation**, **size**, and other properties are all animatable.&#x20;
* When the view <mark style="color:red;">**isn’t equatable**</mark>, you can use the <mark style="color:red;">**animation(\_:value:)**</mark> modifier to start animations when the **specified value changes**.
  {% endhint %}
  {% endtab %}

{% tab title="💈範例" %}

* [Polygon](/ios/swiftui/shapes/shape/polygon.md)
* [Vehicle](/ios/swiftui/shapes/shape/sports-car-in-sunset/vehicle.md) - tap to animate.
* [MGE ⟩ animation](/ios/swiftui/shapes/matched-geometry-effect/animation.md) - matched geometry effect.
  {% endtab %}

{% tab title="📜 協定" %}
![](https://1830103165-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5-JmwCZMKh_d7RfBaN%2F-MIddqEpjbhO15myOPEj%2F-MIde6Y5WyCqSBMj0SNd%2FAnimatable%20protocol.png?alt=media\&token=336ebcb8-8b17-40e8-b62b-f9533958767b)
{% endtab %}

{% tab title="📗 參考" %}

* [ ] SwiftUI Lab ⟩ Advanced SwiftUI Animations ⟩
  * [x] [Part 1: Paths](https://swiftui-lab.com/swiftui-animations-part1/)
  * [ ] [Part 2: GeometryEffect](https://swiftui-lab.com/swiftui-animations-part2/)
  * [ ] [Part 3: AnimatableModifier](https://swiftui-lab.com/swiftui-animations-part3/)
* [ ] QVIK ⟩ [Basics of SwiftUI Animation](https://qvik.com/news/basics-of-swiftui-animation/) #todo
* [ ] Hacking with Swift ⟩ [Customizing animations in SwiftUI](https://www.hackingwithswift.com/books/ios-swiftui/customizing-animations-in-swiftui)
* [ ] Zak ⟩ [Mastering transitions in SwiftUI](https://nerdyak.tech/development/2020/10/12/transitions-in-swiftui.html)
* [ ] Big Mountain Studio ⟩ [Trapezium - Part 3: Animating](https://www.bigmountainstudio.com/view/courses/shapes/327908-episode-1-the-trapezium-shape/2556099-trapezium-part-3-animating-mp4) - animating [Shape](/ios/swiftui/shapes/shape.md).
* [ ] [SwiftUI Animations Mastery (iOS 14)](https://www.bigmountainstudio.com/view/downloads/swiftui-animations)
  {% endtab %}

{% tab title="📘 手冊" %}

* SwiftOnTap ⟩ [Animatable](https://swiftontap.com/animatable) ⭐️
* SwiftUI Tutorials ⟩ [Animating Views & Transitions](https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions) ⟩
  * [Add Animations to Individual Views](https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions#Add-Animations-to-Individual-Views)
* [SwiftUI](https://developer.apple.com/documentation/swiftui) ⟩&#x20;
  * [Animations](https://developer.apple.com/documentation/swiftui/animations) ⟩&#x20;
    * [Animatable](https://developer.apple.com/documentation/swiftui/animatable) (<mark style="color:orange;">**protocol**</mark>)
      * [animatableData](https://developer.apple.com/documentation/swiftui/animatable/animatabledata-swift.property-6nydg) - conforms to [VectorArithmetic](https://developer.apple.com/documentation/swiftui/vectorarithmetic) (<mark style="color:orange;">**protocol**</mark>).
    * [AnimatablePair](https://developer.apple.com/documentation/swiftui/animatablepair) (<mark style="color:red;">**struct**</mark>)
  * [Drawing and Animation](https://developer.apple.com/documentation/swiftui/drawing-and-animation) ⟩
    * [Animation](https://developer.apple.com/documentation/swiftui/animation) (<mark style="color:red;">**struct**</mark>)
    * [withAnimation(*:*:)](https://developer.apple.com/documentation/swiftui/withanimation\(_:_:\))
  * View ⟩ [Graphics and Rendering](https://developer.apple.com/documentation/swiftui/view-graphics-and-rendering) ⟩
    * [.animation(\_:)](https://developer.apple.com/documentation/swiftui/view/animation\(_:\)-7mq1i) - applied to <mark style="color:red;">**equatable**</mark> view
    * [.animation(\_:value:)](https://developer.apple.com/documentation/swiftui/view/animation\(_:value:\)) - applied to <mark style="color:red;">**equatable**</mark> value (<mark style="color:red;">**non-equatable view**</mark>)
      {% endtab %}

{% tab title="👥 相關" %}

* [Shape](/ios/swiftui/shapes/shape.md) can be animated. (👉 [Mark](https://www.bigmountainstudio.com/view/courses/shapes/327908-episode-1-the-trapezium-shape/2556099-trapezium-part-3-animating-mp4))
* [shapes](/ios/swiftui/shapes.md)
* [Animatable Modifiers](/ios/swiftui/anim/animatable/animatable-modifiers.md) is animatable.
* [Animations ⟩ examples](/ios/swiftui/anim/examples.md) - use [animatableData](https://developer.apple.com/documentation/swiftui/animatable/animatabledata-swift.property-6nydg).
  {% endtab %}
  {% endtabs %}
