アニメーション設定をコードで記述する際の書き方

解決


Moe  2023-09-25 11:01:04  No: 151131  IP: [192.*.*.*]

お世話になります。
Delphi11.3でFMXアプリケーションを作成しています。
TRectAngleにFloatAnimationを配置しまして、TRectAngleの上にマウスが乗った時点でTRectAngleの幅を広くするアニメーションはビジュアルにできました。
なのですが、TRectAngleが複数ありまして同じ設定を幾つも行うのは大変なので、動的に割当られないかと次のコードを書いてみました。

::::割愛致します:::
var
  ChildRect: array[0..CST_RECT_COUNT-1] of TRectAngle;
  WidthAni: array[0..CST_RECT_COUNT-1] of TFloatAnimation;

procedure TFrmMenu.FormCreate(Sender: TObject);
begin
  for var i := 0 to High(ChildRect) do
  begin
    ChildRect[i] := TRectAngle(FindComponent('RectBtn' + IntToStr(i)));
    WidthAni[i] := TFloatAnimation.Create(ChildRect[i]);
    WidthAni[i].Parent := ChildRect[i];
    WidthAni[i].AnimationType := TAnimationType.In;
    WidthAni[i].Duration := 0.1;
    WidthAni[i].PropertyName := 'Size.Width';
    WidthAni[i].StartValue := ChildRect[i].Width;
    WidthAni[i].StopValue := WidthAni[i].StartValue + 20;
    WidthAni[i].Trigger := 'IsMouseOver=true';
    WidthAni[i].TriggerInverse := 'IsMouseOver=false';
    WidthAni[i].Enabled := True;
  end;
end;

上記を実行してTRectAngleの上にマウスを乗せても無反応です。
ビジュアルに配置/設定すると上手く行くので、その差が何かを見てみたところ少しだけヒントが分かりました。
TRectAngleのSizeプロパティ(ここでは、さらにWidthですね)にFloatAnimationが関連していることに。。。合ってますかね(汗)。
恐らくこれが原因ではないかと思うのですが、これを記述する方法が分からず、すみませんがどなたか教えて頂けると助かります。

編集 削除
Moe  2023-09-25 13:19:41  No: 151132  IP: [192.*.*.*]

自己レスです。
TRectAngleのOnMouseMoveイベントで次の様に書くことでアニメーションできました。
TAnimator.AnimateFloat(RctMenu10, 'Width', 279, 0.1,
                          TAnimationType.&In, TInterpolationType.Linear);
何とか、解決方法は見つける事ができましたが、これ以外の方法がありましたら、引き続き情報お待ちしております。

編集 削除
KONNOYA  2023-09-26 03:34:48  No: 151133  IP: [192.*.*.*]

これ以外の方法ではありませんが、
そこは、OnMouseMoveイベントではなく、OnMouseEnterイベントに記述した方が良いと思います。

・OnMouseMoveイベントに記述した場合、コンポーネント上でマウスを移動させる度に、毎回イベントが走ってしまいます。
・OnMouseEnterイベントに記述した場合、コンポーネント上にマウスが乗った時、1度だけイベントが走ります。

Moeさんのコードでサンプルを作成してみました。


「FMXコード」

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, FMX.Ani;

type
  TForm1 = class(TForm)
    Rectangle1: TRectangle;
    Rectangle2: TRectangle;
    Rectangle3: TRectangle;
    procedure FormCreate(Sender: TObject);
    procedure RectangleMouseEnter(Sender: TObject);
    procedure RectangleMouseLeave(Sender: TObject);
  private
    { private 宣言 }
  public
    { public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

const
  LENGTH_DEF = 50;  // 通常の大きさ
  LENGTH_MAX = 70;  // 引き延ばした大きさ

procedure TForm1.FormCreate(Sender: TObject);
begin
  // ここはオブジェクトインスペクタで設定しても良い
  Rectangle1.OnMouseEnter := RectangleMouseEnter;
  Rectangle1.OnMouseLeave := RectangleMouseLeave;
  Rectangle2.OnMouseEnter := RectangleMouseEnter;
  Rectangle2.OnMouseLeave := RectangleMouseLeave;
  Rectangle3.OnMouseEnter := RectangleMouseEnter;
  Rectangle3.OnMouseLeave := RectangleMouseLeave;
end;

procedure TForm1.RectangleMouseEnter(Sender: TObject);
begin
  TAnimator.AnimateFloat(TRectangle(Sender), 'Width', LENGTH_MAX, 0.1, TAnimationType.In, TInterpolationType.Linear);
end;

procedure TForm1.RectangleMouseLeave(Sender: TObject);
begin
  TAnimator.AnimateFloat(TRectangle(Sender), 'Width', LENGTH_DEF, 0.1, TAnimationType.In, TInterpolationType.Linear);
end;

end.

アニメーションを終了させる値に、TRectangle(Sender).Width + 20 等と行わず、定数値で指定している理由は、
素早くマウスを動かすと、TRectangle の幅が徐々に変わって行ってしまうからです。

編集 削除
Moe  2023-09-26 10:09:38  No: 151134  IP: [192.*.*.*]

KONNOYAさん
ありがとうございます。
確かにOnMouseMoveよりもOnMouseEnterが良いですよね。
また、仰る通り横幅は固定に修正しないと、動かす度に増幅されて大変な事になりました(汗。
お蔭様で少し動きが良くなりました。

編集 削除
Moe  2023-09-27 02:51:30  No: 151136  IP: [192.*.*.*]

本件をクローズさせて頂きます。
ありがとうございました。

編集 削除