Les interpolations et fonctions d'easing avec Lazarus VIII - Effet d'élastique, aller-retour et rebonds,
Un billet de Gilles Vasseur

Le , par gvasseur58

0PARTAGES

Les fonctions avec effet d'élastique, aller-retour ou rebond produisent les effets d'easing les plus spectaculaires. Ce sont aussi elles qui font appel à des constantes énigmatiques, mais qui trouvent leur origine dans des calculs complexes très peu (voire pas) documentés : il faudra par conséquent accepter ses constantes parfois modulables et se réjouir de leur effet !

Les fonctions à effet d'élastique

Bien sûr, les fonctions de la catégorie Elastic sont plutôt complexes. Elles s'appuient à la fois sur le caractère amplificateur des puissances de 2 et sur les cycles créés par la fonction sinus :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
function TMainForm.EaseInElastic(AStart, AChange, AStep: Single): Single; 
// *** INELASTIC *** 
begin 
  if AStep = 0 then 
    Result := AStart 
  else 
  begin 
    AStep := AStep / fDuration; 
    if AStep = 1 then 
      Result := AChange + AStart 
    else 
    begin 
      AStep := AStep - 1; 
      Result := - (AChange * Power(2, 10 * AStep) * sin((AStep * fDuration 
        - (fDuration * 0.3 / 4)) * 2 * Pi / (fDuration * 0.3))) + AStart; 
    end; 
  end; 
end; 
  
function TMainForm.EaseOutElastic(AStart, AChange, AStep: Single): Single; 
// *** OUTELASTIC *** 
begin 
  if AStep = 0 then 
    Result := AStart 
  else 
  begin 
    AStep := AStep / fDuration; 
    if AStep = 1 then 
      Result := AChange + AStart 
    else 
      Result := AChange * Power(2, - 10 * AStep) * sin((AStep * fDuration - 
        (fDuration * 0.3 / 4)) * 2 * Pi / (fDuration * 0.3)) + AChange + AStart; 
   end; 
end; 
  
function TMainForm.EaseInOutElastic(AStart, AChange, AStep: Single): Single; 
// *** INOUTELASTIC *** 
begin 
  if AStep = 0 then 
    Result := AStart 
  else 
  begin 
    AStep := AStep / fDuration * 2; 
    if AStep = 2 then 
      Result := AChange + AStart 
    else 
    begin 
      // 0.45 = 0.3*1.5  0.1125 = 0.45 / 4 
      if AStep < 1 then 
      begin 
        AStep := AStep - 1; 
        Result := - (AChange * Power(2, 10 * AStep) * sin((AStep * fDuration - 
          fDuration * 0.1125) * 2 * Pi / (fDuration * 0.45))) / 2 + AStart; 
      end 
      else 
      begin 
        AStep := AStep - 1; 
        Result :=  AChange * Power(2, - 10 * AStep) * sin((AStep * fDuration - 
          fDuration * 0.1125) * 2 * Pi / (fDuration * 0.45)) / 2 + AChange + AStart; 
      end; 
    end; 
  end; 
end; 
  
function TMainForm.EaseOutInElastic(AStart, AChange, AStep: Single): Single; 
// *** OUTINELASTIC *** 
begin 
  if AStep < fDuration / 2 then 
    Result := EaseOutElastic(AStart, AChange / 2, AStep * 2) 
  else 
    Result := EaseInElastic(AStart + AChange / 2, AChange / 2, AStep * 2 - fDuration); 
end;

Les fonctions avec aller-retour

Les fonctions relatives à la catégorie Back complexifient encore les calculs. Nous les implémenterons en prenant une valeur correspondant à un rebond de 10%, mais d'autres valeurs indiquées dans le code sont utilisables : comme nous l'avons annoncé, ces nombres mystérieux cachent en fait des calculs plutôt fastidieux qui permettent de calculer l'amplitude des allers-retours.

Voici l'implémentation adoptée :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function TMainForm.EaseInBack(AStart, AChange, AStep: Single): Single; 
// *** INBACK *** 
begin 
  // 1.70158 = 10% 2.592389 = 20% 3.394051 = 30% 4.15574465 = 40% 
  Result := AChange * Power(AStep / fDuration, 2) * (2.70158 * 
    AStep / fDuration - 1.70158) + AStart; 
end; 
  
function TMainForm.EaseOutBack(AStart, AChange, AStep: Single): Single; 
// *** OUTBACK *** 
begin 
  Result := AChange * (Power(AStep / fDuration - 1, 2) * 
    (2.70158 * (AStep / fDuration - 1) + 1.70158) + 1) + AStart; 
end; 
  
function TMainForm.EaseInOutBack(AStart, AChange, AStep: Single): Single; 
// *** INOUTBACK *** 
begin 
  // 2.5949095 = 1.70158 * 1.525 
  AStep := AStep / fDuration * 2; 
  if AStep < 1 then 
    Result := AChange / 2 * Power(AStep, 2) * (3.594905 * AStep - 2.594905) 
      + AStart 
  else 
    Result := AChange / 2 * (Power(AStep - 2, 2) * (3.594905 * (AStep - 2) 
      + 2.594905) + 2) + AStart; 
end; 
  
function TMainForm.EaseOutInBack(AStart, AChange, AStep: Single): Single; 
// *** OUTINBACK *** 
begin 
  if AStep < fDuration / 2 then 
    Result := EaseOutBack(AStart, AChange / 2, AStep * 2) 
  else 
    Result := EaseInBack(AStart + AChange / 2, AChange / 2, AStep * 2 - fDuration); 
end;

Les fonctions avec rebond


Enfin, les fonctions relatives à la catégorie Bounce sont les plus longs. Il faut en effet calculer chaque étape afin d'obtenir les résultats les plus proches possibles de rebonds qui paraissent naturels.

Voici l'implémentation adoptée :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
function TMainForm.EaseInOutBounce(AStart, AChange, AStep: Single): Single; 
// *** INOUTBOUNCE *** 
begin 
  if AStep < fDuration / 2 then 
    Result := EaseInBounce(0, AChange, AStep * 2) / 2 + AStart 
  else 
    Result := EaseOutBounce(0, AChange, AStep * 2 - fDuration) / 2 + AChange / 2 
      + AStart; 
end; 
  
function TMainForm.EaseOutInBounce(AStart, AChange, AStep: Single): Single; 
// *** OUTINBOUNCE *** 
begin 
  if AStep < fDuration / 2 then 
    Result := EaseOutBounce(AStart, AChange / 2, AStep * 2) 
  else 
    Result := EaseInBounce(AStart + AChange / 2, AChange / 2, AStep * 2 - fDuration); 
end; 
  
function TMainForm.EaseInBounce(AStart, AChange, AStep: Single): Single; 
// *** INBOUNCE *** 
begin 
  Result := AChange - EaseOutBounce(0, AChange, fDuration - AStep) + AStart; 
end; 
  
function TMainForm.EaseOutBounce(AStart, AChange, AStep: Single): Single; 
// *** OUTBOUNCE *** 
begin 
  AStep := AStep / fDuration; 
  if AStep < 1 / 2.75 then 
    Result := AChange * 7.5625 * Power(AStep, 2) + AStart 
  else 
  if AStep < 2 / 2.75 then 
  begin 
    AStep := AStep - 1.5 / 2.75; 
    Result := AChange * (7.5625 * Power(AStep, 2) + 0.75) + AStart; 
  end 
  else 
  if AStep < 2.5 / 2.75 then 
  begin 
    AStep := AStep - 2.25 / 2.75; 
    Result := AChange * (7.5625 * Power(AStep, 2) + 0.9375) + AStart; 
  end 
  else 
  begin 
    AStep := AStep - 2.625 / 2.75; 
    Result := AChange * (7.5625 * Power(AStep, 2) + 0.984375) + AStart; 
  end; 
end;

Vous aurez remarqué que ces dernières fonctions sont fondées sur la fonction EaseOutBounce, celle qui introduit les valeurs "magiques".

Dans le prochain épisode, nous mettrons au point l'application de test. A très bientôt !

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de circular17
Membre confirmé https://www.developpez.com
Le 03/02/2019 à 15:39
L'élastique c'est fantastique
Contacter le responsable de la rubrique Accueil

Partenaire : Hébergement Web