Easing:モバイルアニメーションのスムージング関数

著者: IT Sectr 公開日: 2026-03-02 読了時間: 8 分
Easing(スムージング関数)は、アニメーションパラメータの時間変化率を決定する数学的な曲線です。線形の等加速度運動の代わりに、イージングは物理的な振る舞いを模倣します。オブジェクトは加速(ease-in)、減速(ease-out)、またはその両方(ease-in-out)を行うことができます。iOSでは、イージングはCAMediaTimingFunctionクラス(Core Animation)とSwiftUIモディファイア(Animation.easeInOut)を通じて実装されています。Androidでは、PathInterpolatorとTimeInterpolatorを通じて実装されています。Apple Developer Documentationによると、適切に選択されたイージングカーブは、実際の時間を変更せずに知覚されるアニメーション時間を20~35%短縮します。IT Sectrでは、ease-in-out曲線(0.42、0.0、0.58、1.0)をすべてのモバイルプロジェクトの企業標準として標準化しました。

重要なポイント

  • Easing — 物理的な動き(加速、減速、または組み合わせ)を模倣するアニメーション速度関数。
  • CAMediaTimingFunction — 5つの定義済み曲線とカスタム3次ベジェを持つiOS Core Animationクラス。
  • SwiftUI Animation — 宣言的イージングのための.easeIn、.easeOut、.easeInOut、.spring、.timingCurveモディファイア。
  • PathInterpolator — 2つの制御点を持つ3次ベジェ曲線によるAndroidでのイージング相当。
  • 3次ベジェ — iOS、Android、Webに共通するイージングカーブ指定の汎用形式。

Easingとは?

Easing(スムージング関数)は、線形時間t ∈ [0,1]を非線形のアニメーション値にマッピングする数学関数f(t)です。アニメーションが500ミリ秒でオブジェクトの位置をAからBに変更する場合、イージングは各時点でオブジェクトがこれらの点間をどのように移動するかを決定します。線形イージング(f(t)=t)は一定速度を意味し、オブジェクトは機械的に動きます。非線形イージングは自然に感じられます。オブジェクトは加速(ease-in)、減速(ease-out)、またはスムーズな開始と終了(ease-in-out)を行います。

イージング関数は3次ベジェ曲線で記述され、X軸は正規化された時間、Y軸は正規化された進行度です。2つの制御点(P1、P2)が曲線の形状を定義します。標準曲線はCSS仕様で固定されています:ease(0.25、0.1、0.25、1.0)、ease-in(0.42、0.0、1.0、1.0)、ease-out(0.0、0.0、0.58、1.0)、ease-in-out(0.42、0.0、0.58、1.0)。これらの同じ値がiOSのCAMediaTimingFunctionとAndroidのPathInterpolatorで使用されています。Material Design Motion Guidelinesによると、イージングカーブはコンテキストに適合する必要があります。出現にはease-out(高速開始)、消失にはease-in(高速終了)です。

iOSのEasing:CAMediaTimingFunction

iOSでは、イージングは主にCore AnimationのCAMediaTimingFunctionクラスを通じて機能します。これは3次ベジェ曲線を2つの制御点(c1x、c1y、c2x、c2y)として受け入れ、CAAnimation(CABasicAnimation、CAKeyframeAnimation)に適用されます。CAMediaTimingFunctionは5つの定義済み関数をサポートしています:linear、easeIn、easeOut、easeInEaseOut、default(easeInEaseOutと同等)。

CAMediaTimingFunctionはCALayerレベルで動作し、アニメーションは別のレンダリングサーバープロセスで実行されるため、複雑な変換でも60fpsを保証します。UIViewプロパティ(frame、alpha、transform)のアニメーションには、UIKitはoptionsパラメータ.curveEaseInOutを持つUIView.animateを使用し、内部で対応する曲線のCAMediaTimingFunctionも作成します。iOS 17以降では、カスタムベジェ用のUIViewAnimationCurve.customとBlockParametersが追加され、カスタムCAAnimationを作成する必要がなくなりました。CAMediaTimingFunctionはUIKit DynamicsやUIScrollViewの減速(UIScrollViewDecelerationRate)にも使用されています。

SwiftUIのEasing

SwiftUIでは、イージングはAnimation構造体を通じて.easeIn、.easeOut、.easeInOut、.spring、.interpolatingSpringモディファイアで設定されます。アニメーションが手続き的(beginAnimations/commitAnimations)なUIKitとは異なり、SwiftUIは宣言的アプローチを採用しています。アニメーションは変更される状態プロパティであり、フレームワークが遷移のアニメーション方法を決定します。

.timingCurve(c0x、c0y、c1x、c1y)モディファイアは3次ベジェ制御点を直接受け入れ、CAMediaTimingFunctionの完全な類似物です。SwiftUI Animationは定義済み曲線を静的プロパティとしてサポートしています。Animation.easeInOutはease-in-out(0.42、0.0、0.58、1.0)と同等です。スプリングアニメーションにはAnimation.spring(response:dampingFraction:blendDuration)が使用され、dampingFraction < 1で減衰付きのバネ効果を生み出します。WWDC 2023でAppleはAnimation.keyframesを発表しました。これは各キーフレームでカスタムイージングを使用したフレーム単位のアニメーションで、軌道を完全に制御できます。

AndroidのEasing:PathInterpolator

Androidでは、イージングはPathInterpolator(API 21+)を通じて実装されています。これは3次ベジェ曲線を持つPathオブジェクトを受け入れるクラスです。制御点はPath.cubicTo(x1、y1、x2、y2、x3、y3)で指定され、(x1、y1)が最初の制御点、(x2、y2)が2番目、(x3、y3)が終了点(常に1、1)です。カスタム曲線が必要な場合はPathInterpolatorが必須です。標準的なシナリオでは、AccelerateDecelerateInterpolator(ease-in-out)、AccelerateInterpolator(ease-in)、DecelerateInterpolator(ease-out)が利用可能です。

Jetpack Composeでは、イージングはandroidx.compose.animationパッケージのEasingオブジェクトを通じて設定されます。FastOutSlowInEasing、LinearOutSlowInEasing、FastOutLinearInEasing、およびCubicBezierEasingによるカスタムEasingが利用可能です。Compose Easingはanimate*AsState、AnimatedVisibility、AnimatedContentで適用されます。Viewシステムとの主な違いは、ComposeはKotlin側でイージングを補間する(RenderNodeではない)ことで、カスタムアニメーションの柔軟性が高まりますが、120Hzディスプレイでの最適化が必要です。

コード例

iOS:CABasicAnimationを使用したCAMediaTimingFunction

カスタムease-in-out曲線を使用した基本的なレイヤー位置アニメーション。CAMediaTimingFunctionは、動きのスムーズな開始と終了を定義する3次ベジェ制御点を受け入れます。

swift
import UIKit

func animateLayerPosition() {
    let animation = CABasicAnimation(keyPath: "position")
    animation.fromValue = CGPoint(x: 0, y: 0)
    animation.toValue = CGPoint(x: 300, y: 400)
    animation.duration = 0.8

    let easing = CAMediaTimingFunction(
        controlPoints: 0.42, 0.0, 0.58, 1.0
    )
    animation.timingFunction = easing
    animation.fillMode = .forwards
    animation.isRemovedOnCompletion = false

    layer.add(animation, forKey: "positionAnimation")
}

制御点(0.42、0.0、0.58、1.0)は標準のease-in-out曲線を定義します。SwiftUIはAnimation.easeInOutに同じ点を使用します。ease-inには(0.42、0.0、1.0、1.0)を、ease-outには(0.0、0.0、0.58、1.0)を使用します。Core Animationはレンダリングサーバーで60/120fpsでアニメーションを実行します。

SwiftUI:timingCurveを使用したEasing

カスタム曲線とスプリング効果を使用したSwiftUIの宣言的アニメーション。アニケーションモディファイアはisAnimatedの変更にバインドされます。

swift
import SwiftUI

struct EasingExampleView: View {
    @State private var isAnimated = false

    var body: some View {
        VStack {
            Circle()
                .fill(Color.blue)
                .frame(width: 60, height: 60)
                .offset(x: isAnimated ? 100 : 0, y: 0)
                .animation(
                    .timingCurve(0.42, 0.0, 0.58, 1.0, duration: 0.6),
                    value: isAnimated
                )

            Button("Toggle") {
                isAnimated.toggle()
            }
        }
    }
}

.timingCurve(c0x、c0y、c1x、c1y、duration)モディファイアは、SwiftUIでカスタムイージングアニメーションを作成します。valueパラメータはアニメーションを特定の状態にバインドします。isAnimatedが変更されると、SwiftUIが自動的に曲線を適用します。スプリングアニメーションには、timingCurveの代わりに.spring(response:0.4、dampingFraction:0.6)を使用します。

Android:カスタムEasingを使用したPathInterpolator

PathInterpolatorによるAndroidでのease-in-out相当。制御点(0.42、0.0、0.58、1.0)はiOSと同じ曲線を定義します。

kotlin
import android.animation.ObjectAnimator
import android.graphics.Path
import android.view.animation.PathInterpolator
import android.view.View

fun View.fadeInWithEase() {
    val path = Path().apply {
        cubicTo(0.42f, 0.0f, 0.58f, 1.0f, 1.0f, 1.0f)
    }
    val interpolator = PathInterpolator(path)

    ObjectAnimator.ofFloat(this, "alpha", 0f, 1f).apply {
        duration = 500
        interpolator = interpolator
        start()
    }
}

制御点(0.42、0.0、0.58、1.0)を持つPathInterpolatorは、iOSのCAMediaTimingFunction ease-in-outと同じです。クロスプラットフォームプロジェクトでは、同じ制御点を使用することで、視覚的に同一のアニメーション動作が保証されます。Material Designは、Android固有のインターフェースの代替としてFastOutSlowInInterpolator(0.4、0.0、0.2、1.0)を推奨しています。

Jetpack Compose:CubicBezierEasingを使用したEasing

Composeでは、同じ制御点を持つCubicBezierEasingを通じてイージングが設定されます。結果は、透明度とオフセットを伴うスムーズな要素の出現です。

kotlin
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*

@Composable
fun EasingComposable() {
    var visible by remember { mutableStateOf(false) }
    val easing = CubicBezierEasing(0.42f, 0.0f, 0.58f, 1.0f)

    val alpha by animateFloatAsState(
        targetValue = if (visible) 1f else 0f,
        animationSpec = tween(durationMillis = 500, easing = easing)
    )

    Column {
        Button(onClick = { visible = !visible }) {
            Text("Toggle")
        }

        Box(
            modifier = Modifier
                .size(100.dp)
                .graphicsLayer(alpha = alpha)
                .background(MaterialTheme.colorScheme.primary)
        )
    }
}

ComposeのCubicBezierEasingは同じ4つの制御点パラメータを受け入れます。animateFloatAsStateは指定された曲線でalpha値を自動的に補間します。比較すると、ComposeのFastOutSlowInEasingは(0.4、0.0、0.2、1.0)と同等で、標準のMaterial Design 3曲線です。CubicBezierEasingによるカスタム曲線は、ブランドアニメーションを完全に制御できます。

よくある質問

EasingとInterpolatorの違いは?

EasingはiOS(CAMediaTimingFunction)、Web(CSS ease-in-out)、デザインで使用されるスムージング関数の一般的な概念です。InterpolatorはAndroid(TimeInterpolator)におけるこの概念の実装です。本質的には同じものであり、アニメーション速度の数学的曲線です。違いは名前とプラットフォームAPIのみです。クロスプラットフォームプロジェクトでは、easingという用語が汎用的に使用されます。

iOSではどのようなイージング関数が利用できますか?

iOSは5つの定義済み関数(linear、easeIn、easeOut、easeInEaseOut、custom(3次ベジェ))を持つCAMediaTimingFunctionを提供します。SwiftUIでは、Animation.easeIn、Animation.easeOut、Animation.easeInOut、Animation.spring、Animation.interpolatingSpringが利用可能です。カスタム曲線には、Animation.timingCurve(c0x、c0y、c1x、c1y、duration:)を使用します。

iOSとAndroidで同じイージング関数を使用できますか?

はい、同じ3次ベジェ曲線を設定すれば可能です。iOSのCAMediaTimingFunctionとAndroidのPathInterpolatorは3次ベジェ制御点(x1、y1、x2、y2)を受け入れます。例えば、ease-in-out(0.42、0.0、0.58、1.0)曲線は両方のプラットフォームで同一の動作を提供します。Material Designはクロスプラットフォームアニメーションにこのアプローチを使用しています。

アプリケーションに適したイージング曲線を選択するには?

Material Design Motion Guidelinesを使用します。要素の出現にはease-out(高速開始、スムーズな終了)、消失にはease-in(高速終了)、画面間の移動にはease-in-outを使用します。インタラクティブな要素(ボタン、カード)にはスプリングアニメーションを使用します。linearは不自然に見えるため避けてください。

イージングアニメーションがカクカクするのはなぜですか?

カクつき(ジャンク)は、アニメーションが60fpsに達しない場合に発生します。確認してください:iOSでCAMediaTimingFunction(タイマーではない)を使用していますか?AndroidでPathInterpolator(Handler.postではない)を使用していますか?メインスレッドでの重い計算、複雑なレイヤー階層、大きなdrawableがフレーム落ちの原因になります。iOSでは、複雑なレイヤーにはshouldRasterizeを使用したCore Animationを、AndroidではハードウェアアクセラレーションとGPUレンダリングを使用します。

まとめ

  • Easingは、時間の経過に伴う非線形パラメータ変化によって動きを自然にするアニメーション速度関数です。
  • iOSのCAMediaTimingFunctionとSwiftUIのAnimation.timingCurveは、2つの制御点を持つ3次ベジェ曲線を通じてイージングを実装します。
  • AndroidのPathInterpolatorとComposeのCubicBezierEasingは、カスタムスムージング曲線のための完全なiOS類似物です。
  • クロスプラットフォームのイージング曲線は同じ制御点で定義され、アニメーション統一の基盤となります。
  • Material Design 3は、出現にはfast-out-slow-in、消失にはlinear-out-slow-inを推奨しています。
  • SwiftUI(Animation.spring)とCompose(spring())のスプリングアニメーションは、dampingFractionで物理的なバネ効果を生み出します。
  • 線形イージングはインターフェースアニメーションには推奨されません。不自然で機械的に見えます。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください