首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 緩動函數實作系列(一):N 次方緩動 - 從物理運動到程式碼

     編輯:關於.NET

緩動概念:緩入與緩出

現實物體啟動/停止皆有加減速過程。對應數學曲線:

  • Ease In (緩入):速度從 0 增加,曲線凹向下(如 $y=t^2$)。緩入曲線
  • Ease Out (緩出):速度從最大減至 0,曲線凹向上(如 $y=1-(1-t)^2$)。緩出曲線

物理推導:位移與時間關係

勻加速運動:$v = at$, $s = \frac{1}{2}at^2$。總位移 $S = \frac{1}{2}aT^2$。任意時刻 $t$ 位移比例:

$$\frac{s}{S} = \frac{t^2}{T^2} = \left(\frac{t}{T}\right)^2$$

推廣至 N 次方:$\left(\frac{t}{T}\right)^N$。指數越大,曲線越陡峭,加速度越大。WPF 中 $t/T$ 對應 `animationClock.CurrentProgress.Value` (0~1),$S$ 對應 `To - From`。

物理公式推導

完整實作碼:支援可調指數的 N 次方緩動

using System;
using System.Windows;
using System.Windows.Media.Animation;

namespace EaseMoveDemo
{
    public class EaseMoveAnimation : DoubleAnimationBase
    {
        public static readonly DependencyProperty FromProperty =
            DependencyProperty.Register("From", typeof(double?), typeof(EaseMoveAnimation), new PropertyMetadata(null));
        public static readonly DependencyProperty ToProperty =
            DependencyProperty.Register("To", typeof(double?), typeof(EaseMoveAnimation), new PropertyMetadata(null));
        public static readonly DependencyProperty PowerProperty =
            DependencyProperty.Register("Power", typeof(double?), typeof(EaseMoveAnimation), new PropertyMetadata(null));

        public double? From { get => (double?)GetValue(FromProperty); set => SetValue(FromProperty, value); }
        public double? To { get => (double?)GetValue(ToProperty); set => SetValue(ToProperty, value); }

        /// 冪指數,值越大曲線越陡峭,加速度越大。建議 2~5。
        public double? Power { get => (double?)GetValue(PowerProperty); set => SetValue(PowerProperty, value); }

        protected override double GetCurrentValueCore(
            double defaultOriginValue, 
            double defaultDestinationValue, 
            AnimationClock animationClock)
        {
            double from = (this.From == null ? defaultDestinationValue : (double)this.From);
            double to = (this.To == null ? defaultOriginValue : (double)this.To);
            double delta = to - from;
            double power = this.Power == null ? 2 : (double)this.Power;

            // 加速 (Ease In)
            return delta * Math.Pow(animationClock.CurrentProgress.Value, power) + from;

            // 減速 (Ease Out) - 取倒數指數
            // return delta * Math.Pow(animationClock.CurrentProgress.Value, 1/power) + from;

            // 先加速後減速 (Ease InOut)
            // if (animationClock.CurrentProgress.Value < 0.5)
            //     return delta / 2 * Math.Pow(animationClock.CurrentProgress.Value * 2, power) + from;
            // return delta / 2 * (2 - Math.Pow((1 - animationClock.CurrentProgress.Value) * 2, power)) + from;
        }

        protected override Freezable CreateInstanceCore() => new EaseMoveAnimation();
    }
}

使用範例

<local:EaseMoveAnimation From="0" To="300" Duration="0:0:2" Power="3" />

結語

N 次方緩動以基本物理運動為基礎,透過單一參數 `Power` 控制曲線劇烈程度,實作簡單且效果直觀。它是自訂緩動函數系列的基石,後續文章將擴展至正弦、指數、圓弧等更豐富的曲線族群。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved