I'm considering to put a loading animation and a progress arc in a single object (like WhatsApp when loading a record), so I thought it was better to use TArc and TFloatAnimation, since I can control the StartAngle and EndAngle of the stroke. I'm trying to make the Google loading spinner logic but I'm very confused, it looks like there is a FloatAnimation with "linear" interpolation property that controls one of the angles and another one that looks to have a exponential or sinusoidal interpolation that start/end very fast and I can't see it, anyone had already tried to reproduce it? Thanks.
-
3I actually just recently did something similar, and encapsulated it inside of a Firemonkey control... https://pastebin.com/MUFyQNDu Not the same thing exactly, this is more of a progress indicator (value / max), but it can help you get moving in the right direction. – Jerry Dodge Oct 05 '17 at 19:23
-
@Jerry Dodge Thank you Jerry. So far I've been playing with two FloatAnimation's (StartAngle and EndAngle) properties trying to reach this spinner. – Maurício Lima Oct 05 '17 at 19:43
1 Answers
Requirement to make this:
I find that you calling it a spinner is wrong. It's a spring in a harmonic motion plus a rotation effect.
This is the effect if you don't know it
You could read about it in Wikipedia (Warning it's written in French)
Now to solve this problem you need to define an array which will hold the values of the potential energy required to compress and stretch the spring.
PotentialEnergy: array[0..10] of Single;
The animation you are seeing is this
the spring stretching then getting compressed again. And in order to make it rotate we will define a rotation speed
RotationSpeed : Single;
and the finale animation would look like this
This is final implementation of this animation:
var
Form6: TForm6;
Increment: Integer;
PotentialEnergy: array[0..10] of Single;
ReverseMotion : Boolean;
RotationSpeed : Single;
implementation
{$R *.fmx}
procedure SetArray(var aData: array of Single; const aSource: array of Single);
var
I: Integer;
begin
for I := Low(aSource) to High(aSource) do
begin
aData[I] := aSource[I];
end;
end;
procedure TForm6.Button1Click(Sender: TObject);
begin
SetArray(PotentialEnergy, [5, 64, 48, 32, 24, 16, 14, 10, 8, 7]);
Increment := -1;
ReverseMotion := False;
arc1.StartAngle := 0;
arc1.EndAngle := 1;
RotationSpeed := strtoint(edit1.text); // Degrees per 0.1 second
timer1.Enabled := True;
end;
procedure TForm6.Timer1Timer(Sender: TObject);
begin
if not ReverseMotion then
begin
Inc(Increment);
arc1.EndAngle := arc1.EndAngle + PotentialEnergy[Increment];
arc1.StartAngle := arc1.StartAngle + RotationSpeed;
end
else
begin
Inc(Increment);
arc1.StartAngle := arc1.StartAngle + PotentialEnergy[Increment] + RotationSpeed;
arc1.EndAngle := arc1.EndAngle - PotentialEnergy[Increment];
end;
if (Increment > 10)then
begin
ReverseMotion := not ReverseMotion;
Increment := -1;
end;
end;
Also you could create animation like these
Update: after some synchronization(don't ask me how)
I found the could be exact replica of that google animation
Steps:
- set the timer to 30 ms.
- set the rotation speed to 5.
- set the height and width of the
TArc
to 102. - set potential energy to this
[23, 40, 39, 31, 23, 18, 15, 13, 11, 9, 7, 6, 5, 4, 4]
.
and the result is this (the google animation on the right)

- 2,550
- 2
- 18
- 36
-
Awesome! I wasn't able to realize it for three days. I just have one doubt, how I would change the values of Potential Energy to fit well on a 16 ms TTimer? It seems very fast. – Maurício Lima Oct 09 '17 at 01:26
-
-
Using a 16ms TTimer so you can achieve 60 fps animation without the EndAngle animation being so fast. I think it's better to increase the array values from 10 to 20 or more and build a graph, but I don't know how to calculate when the sum of the values must be near 360, so the animation will be very genuine. – Maurício Lima Oct 09 '17 at 02:41
-
I made this array: `[3, 7, 15, 26, 37, 48, 36, 31, 25, 21, 16, 14, 11, 9, 8, 7, 6, 5, 4, 3,3, 2, 2, 2, 1, 1, 1,1]);` And change the `TTimer` line to: `if (Increment > 28)then` And set a speed of `8`. Thats the closest I could reach. Thank you Nasreddine! – Maurício Lima Oct 09 '17 at 02:57
-
I'm glad that you are trying to modify this to get something that is better for you. The result above are based on the dissection of the GIF using not allowed to share software. – Nasreddine Galfout Oct 09 '17 at 21:26