FMXAttachTAnimation (Delphi)
Contents
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:
- A TRectangle--the animated object
- Two TButton objects
- Two TComboBox objects
- Two TFloatAnimation objects
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.
After clicking the MoveRect button, the rectangle moves according to the selected options, drawing a line from its upper-left corner.
A linear animation:
An elastic animation, with the rectangle moved:
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
- FMX.Ani.TFloatAnimation ( fr | de | ja )
- FMX.Controls.TControl.Position ( fr | de | ja )
- FMX.Ani.TAnimation.AnimationType ( fr | de | ja )
- FMX.Ani.TAnimation.Interpolation ( fr | de | ja )
- FMX.Types.TAnimationType ( fr | de | ja )
- FMX.Types.TInterpolationType ( fr | de | ja )
- FMX.Graphics.TCanvas.DrawLine ( fr | de | ja )
- FMX.Ani.TAnimation.OnProcess ( fr | de | ja )
- FMX.Ani.TAnimation.Enabled ( fr | de | ja )
- FMX.Ani.TAnimation.Pause ( fr | de | ja )