FMXAttachTAnimation (Delphi)

From RAD Studio Code Examples
Jump to: navigation, search

Description

This example demonstrates how the AnimationType and Interpolation properties affect the rate at which the value of a property changes under their control. This is illustrated by controlling the X and Y of a TRectangle with TFloatAnimation instances.

The Interpolation properties on the TFloatAnimation objects are set to Linear, making the change of X and Y constant over time. The Interpolation and AnimationType properties of the TFloatAnimation instance can be set in the Object Inspector to any TInterpolationType and any TAnimationType.

Drawing of the path is done using the DrawLine method of the form's Canvas. Points are collected and drawn using a TPointF array in the animation's OnProcess event handler and then redrawn in the form's OnPaint event handler.

The TFloatAnimation instances have to be created as children of the TRectangle. Many of the TFloatAnimation properties can be set at design time.

To replicate this example, create a Multi-Device Application - Delphi and add the following components to the form:

Rename the buttons to MoveRect and ReturnRect. Using the Object Inspector, add event handlers for the Form1.OnCreate, MoveRect.OnClick, ReturnRect.OnClick, FloatAnimation1.OnProcess, and Form1.OnPaint events. Fill in with the sample code below.

The form should look like the following image.

Inital form.png

After clicking the MoveRect button, the rectangle moves according to the selected options, drawing a line from its upper-left corner.

A linear animation:

Linear animation.png

An elastic animation, with the rectangle moved:

Elasticinterpolation.png

Code

implementation

{$R *.fmx}

uses
  TypInfo; // Uses old style RTTI for simplicity

var
  saveX, saveY: Single;
  oldPos: TPointF;
  posArray: array [0 .. 3000] of TPointF;
  next: Integer;

procedure TForm1.FloatAnimation1Process(Sender: TObject);
var
  newPos: TPointF;
begin
  newPos.X := Rectangle1.Position.X;
  newPos.Y := Rectangle1.Position.Y;
  if ((oldPos.X <> newPos.X) OR (oldPos.Y <> newPos.Y)) then
  begin
    next := next + 1;
    posArray[next] := newPos;
    oldPos := newPos;
    Invalidate;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  s: string;
begin
  //  Populate the ComboBox items with possible values for Interpolation
  for i := Integer(Low(TInterpolationType)) to Integer(High(TInterpolationType)) do
  begin
    s := GetEnumName(TypeInfo(TInterpolationType), i);
    ComboBox1.ListBox.Items.AddObject(s, TObject(i));
  end;
  ComboBox1.ItemIndex := 0;

  // Populate the ComboBox items with possible values for AnimationType
  for i := Integer(Low(TAnimationType)) to Integer(High(TAnimationType)) do
  begin
    s := GetEnumName(TypeInfo(TAnimationType), i);
    ComboBox2.ListBox.Items.AddObject(s, TObject(i));
  end;
  ComboBox2.ItemIndex := 0;

  saveX := Rectangle1.Position.X;
  saveY := Rectangle1.Position.Y;
  oldPos.X := Rectangle1.Position.X;
  oldPos.Y := Rectangle1.Position.Y;
  next := 0;
  posArray[next] := oldPos;

  Self.Fill.Color := claSilver;

  // Attach the FloatAnimations to the Rectangle's position
  FloatAnimation1.Parent := Rectangle1;
  FloatAnimation1.PropertyName := 'Position.X';
  FloatAnimation1.StopValue := Rectangle1.Position.X + 200;
  FloatAnimation1.Duration := 5;
  FloatAnimation1.AnimationType := TAnimationType.atIn;
  FloatAnimation1.Interpolation := TInterpolationType.Linear;
  FloatAnimation1.StartFromCurrent := True;

  FloatAnimation2.Parent := Rectangle1;
  FloatAnimation2.PropertyName := 'Position.Y';
  FloatAnimation2.StopValue := Rectangle1.Position.Y - 200;
  FloatAnimation2.Duration := 5;
  FloatAnimation2.AnimationType := TAnimationType.atIn;
  FloatAnimation2.Interpolation := TInterpolationType.Linear;
  FloatAnimation2.StartFromCurrent := True;
end;

procedure TForm1.ReturnRectClick(Sender: TObject);
begin
  // Returns the rectangle to the starting position
  Rectangle1.Position.X := saveX;
  Rectangle1.Position.Y := saveY;
  oldPos.X := saveX;
  oldPos.Y := saveY;
  MoveRect.Enabled := true;
  ReturnRect.Enabled := false;
end;

procedure TForm1.MoveRectClick(Sender: TObject);
var
  AniType: TAnimationType;
  InterpType: TInterpolationType;
begin
  AniType := TAnimationType(Integer(ComboBox2.ListBox.Items.Objects[ComboBox2.ItemIndex]));
  FloatAnimation2.AnimationType := AniType;
  InterpType := TInterpolationType(Integer(ComboBox1.ListBox.Items.Objects[ComboBox1.ItemIndex]));
  FloatAnimation2.Interpolation := InterpType;
  FloatAnimation1.Start;
  FloatAnimation2.Start;
  MoveRect.Enabled := false;
  ReturnRect.Enabled :=true;
end;

procedure TForm1.FormPaint(Sender: TObject; const Canvas: TCanvas;
  const ARect: TRectF);
var
  i: Integer;
begin
  Canvas.BeginScene;
  Canvas.StrokeThickness := 4;
  Canvas.Fill.Color := claBlack;
  Canvas.FillEllipse(RectF(FloatAnimation1.StopValue - 2,
    FloatAnimation2.StopValue - 2, FloatAnimation1.StopValue + 2,
    FloatAnimation2.StopValue + 2), 100);
  Canvas.FillEllipse(RectF(saveX - 2, saveY - 2, saveX + 2, saveY + 2), 100);
  Canvas.FillEllipse(RectF(Rectangle1.Position.X - 2, Rectangle1.Position.Y - 2,
    Rectangle1.Position.X + 2, Rectangle1.Position.Y + 2), 100);
  for i := 0 to next - 1 do
  begin
    if ((posArray[i].X <> FloatAnimation1.StopValue) and
      (posArray[i].Y <> FloatAnimation2.StopValue)) then
    begin
      Canvas.DrawLine(posArray[i], posArray[i + 1], 1.0);
    end;
  end;
  Canvas.EndScene;
end;

end.

Uses

See Also