7

我正在尝试在TChromeTabs中实现标签的流畅移动。我可以在这里看到缓动公式,但我不是数学家,也不知道如何将其转换为代码。到目前为止,我的尝试无济于事。

是否有可用的缓动功能的 Delphi 实现?

4

1 回答 1

6

我在网上找到了几个有用的示例,并使用这些算法编写了我自己的 Delphi Easing 函数。他们来了:

...

type
  TChromeTabsEaseType = (
    ttlinearTween,
    tteaseInQuad,
    tteaseOutQuad,
    tteaseInOutQuad,
    tteaseInCubic,
    tteaseOutCubic,
    tteaseInOutCubic,
    tteaseInQuart,
    tteaseOutQuart,
    tteaseInOutQuart,
    tteaseInQuint,
    tteaseOutQuint,
    tteaseInOutQuint,
    tteaseInSine,
    tteaseOutSine,
    tteaseInOutSine,
    tteaseInExpo,
    tteaseOutExpo,
    tteaseInOutExpo,
    tteaseInCirc,
    tteaseOutCirc,
    tteaseInOutCirc
  );

    function CalculateEase(CurrentTime, StartValue, ChangeInValue, Duration: Real; EaseType: TChromeTabsEaseType): Real; overload;
    function CalculateEase(StartPos, EndPos, PositionPct: Real; EaseType: TChromeTabsEaseType): Real; overload;

implementation

    function CalculateEase(CurrentTime, StartValue, ChangeInValue, Duration: Real; EaseType: TChromeTabsEaseType): Real;
    begin
      case EaseType of
        ttLinearTween:
          begin
            Result := ChangeInValue * CurrentTime / Duration + StartValue;
          end;

        ttEaseInQuad:
          begin
            CurrentTime := CurrentTime / Duration;

              Result := ChangeInValue * CurrentTime * CurrentTime + StartValue;
          end;

        ttEaseOutQuad:
          begin
            CurrentTime := CurrentTime / Duration;

              Result := -ChangeInValue * CurrentTime * (CurrentTime-2) + StartValue;
          end;

        ttEaseInOutQuad:
          begin
            CurrentTime := CurrentTime / (Duration / 2);

            if CurrentTime < 1 then
              Result := ChangeInValue / 2 * CurrentTime * CurrentTime + StartValue
            else
            begin
              CurrentTime := CurrentTime - 1;
              Result := -ChangeInValue / 2 * (CurrentTime * (CurrentTime - 2) - 1) + StartValue;
            end;
          end;

        ttEaseInCubic:
          begin
            CurrentTime := CurrentTime / Duration;

            Result := ChangeInValue * CurrentTime * CurrentTime * CurrentTime + StartValue;
          end;

        ttEaseOutCubic:
          begin
            CurrentTime := (CurrentTime / Duration) - 1;

            Result := ChangeInValue * ( CurrentTime * CurrentTime * CurrentTime + 1) + StartValue;
          end;

        ttEaseInOutCubic:
          begin
            CurrentTime := CurrentTime / (Duration/2);

            if CurrentTime < 1 then
              Result := ChangeInValue / 2 * CurrentTime * CurrentTime * CurrentTime + StartValue
            else
            begin
              CurrentTime := CurrentTime - 2;

              Result := ChangeInValue / 2 * (CurrentTime * CurrentTime * CurrentTime + 2) + StartValue;
            end;
          end;

        ttEaseInQuart:
          begin
            CurrentTime := CurrentTime / Duration;

            Result := ChangeInValue * CurrentTime * CurrentTime * CurrentTime * CurrentTime + StartValue;
          end;

        ttEaseOutQuart:
          begin
            CurrentTime := (CurrentTime / Duration) - 1;

            Result := -ChangeInValue * (CurrentTime * CurrentTime * CurrentTime * CurrentTime - 1) + StartValue;
          end;

        ttEaseInOutQuart:
          begin
              CurrentTime := CurrentTime / (Duration / 2);

            if CurrentTime < 1 then
              Result := ChangeInValue / 2 * CurrentTime * CurrentTime * CurrentTime * CurrentTime + StartValue
            else
            begin
              CurrentTime := CurrentTime - 2;

              Result := -ChangeInValue / 2 * (CurrentTime * CurrentTime * CurrentTime * CurrentTime - 2) + StartValue;
            end;
          end;

        ttEaseInQuint:
          begin
            CurrentTime := CurrentTime / Duration;

            Result := ChangeInValue * CurrentTime * CurrentTime * CurrentTime * CurrentTime * CurrentTime + StartValue;
          end;

        ttEaseOutQuint:
          begin
            CurrentTime := (CurrentTime / Duration) - 1;

              Result := ChangeInValue * (CurrentTime * CurrentTime * CurrentTime * CurrentTime * CurrentTime + 1) + StartValue;
          end;

        ttEaseInOutQuint:
          begin
            CurrentTime := CurrentTime / (Duration / 2);
            if CurrentTime < 1 then
              Result := ChangeInValue / 2 * CurrentTime * CurrentTime * CurrentTime * CurrentTime * CurrentTime + StartValue
            else
            begin
              CurrentTime := CurrentTime - 2;

              Result := ChangeInValue / 2 * (CurrentTime * CurrentTime * CurrentTime * CurrentTime * CurrentTime + 2) + StartValue;
            end;
          end;

        ttEaseInSine:
          begin
              Result := -ChangeInValue * Cos(CurrentTime / Duration * (PI / 2)) + ChangeInValue + StartValue;
          end;

        ttEaseOutSine:
          begin
              Result := ChangeInValue * Sin(CurrentTime / Duration * (PI / 2)) + StartValue;
          end;

        ttEaseInOutSine:
          begin
            Result := -ChangeInValue / 2 * (Cos(PI * CurrentTime / Duration) - 1) + StartValue;
          end;

        ttEaseInExpo:
          begin
            Result := ChangeInValue * Power(2, 10 * (CurrentTime/Duration - 1) ) + StartValue;
          end;

        ttEaseOutExpo:
          begin
            Result := ChangeInValue * (-Power(2, -10 * CurrentTime / Duration ) + 1 ) + StartValue;
          end;

        ttEaseInOutExpo:
          begin
            CurrentTime := CurrentTime / (Duration/2);

            if CurrentTime < 1 then
              Result := ChangeInValue / 2 * Power(2, 10 * (CurrentTime - 1) ) + StartValue
            else
             begin
               CurrentTime := CurrentTime - 1;

                 Result := ChangeInValue / 2 * (-Power(2, -10 * CurrentTime) + 2 ) + StartValue;
             end;
          end;

        ttEaseInCirc:
          begin
            CurrentTime := CurrentTime / Duration;

              Result := -ChangeInValue * (Sqrt(1 - CurrentTime * CurrentTime) - 1) + StartValue;
          end;

        ttEaseOutCirc:
          begin
            CurrentTime := (CurrentTime / Duration) - 1;

            Result := ChangeInValue * Sqrt(1 - CurrentTime * CurrentTime) + StartValue;
          end;

        ttEaseInOutCirc:
          begin
            CurrentTime := CurrentTime / (Duration / 2);

            if CurrentTime < 1 then
              Result := -ChangeInValue / 2 * (Sqrt(1 - CurrentTime * CurrentTime) - 1) + StartValue
            else
            begin
                CurrentTime := CurrentTime - 2;

                Result := ChangeInValue / 2 * (Sqrt(1 - CurrentTime * CurrentTime) + 1) + StartValue;
            end;
          end;
      end;
    end;

    function CalculateEase(StartPos, EndPos, PositionPct: Real; EaseType: TChromeTabsEaseType): Real;
    var
      t, b, c, d: Real;
    begin
      c := EndPos - StartPos;
      d := 100;
      t := PositionPct;
      b := StartPos;

      Result := CalculateEase(t, b, c, d, EaseType);
    end;

    ...
于 2012-12-19T16:23:37.157 回答