AW: Panel geschmeidig ein- und ausblenden?
Es gibt übrigens auch noch die API Funktion AnimateWindow... Damit geht so etwas auch und sieht meistens auch besser aus als eigene Funktionen:
https://msdn.microsoft.com/de-de/lib...%3Dvs.85).aspx |
AW: Panel geschmeidig ein- und ausblenden?
Das ist nicht genau das was ich suche.
Manuell ist in meinem Fall definitiv besser. AnimateWindow macht nicht das was ich möchte. Zacherl Lösung ist wirklich sehr gut und sieht gut aus. Nur verstehe ich nicht die Logik wie man es umkehrt. Verstanden habe ich es zwar nicht, aber so läuft es fast. Er fährt von 20 (START) bis 200 (END). Umgekehrt funktioniert es nicht.
Delphi-Quellcode:
Vorzeitige Lösung
const
Duration = 3000; POS_START = 20; POS_END = 200; if Button1.Left = POS_START then begin while (D < Duration) do begin Button1.Left := POS_START + Round(POS_END * CalculateEasingCurve(D, Duration)); Application.ProcessMessages; D := GetTickCount - C; end; end else begin while (D < Duration) do begin Button1.Left := POS_END - Round(POS_END * CalculateEasingCurve(D, Duration)); Application.ProcessMessages; D := GetTickCount - C; end; end;
Delphi-Quellcode:
if Panel1.Width = POS_START then
begin iNegative := 1; iTmp := POS_START end else begin iNegative := -1; iTmp := POS_START + POS_END; end; while (D < Duration) do begin Panel1.Width := iTmp + (Round(POS_END * CalculateEasingCurve(D, Duration)) * iNegative); Application.ProcessMessages; D := GetTickCount - C; end; |
AW: Panel geschmeidig ein- und ausblenden?
Ich muss leider noch einmal nerven. Irgendwas stimmt hier leider noch nicht.
Es hat irgendwas mit der markierten Zeile zu tun
Delphi-Quellcode:
Das ist bei mir jetzt eine Prozedur. Control ist ein TWinControl. Wenn ich dort als Control ein Formular TForm (aktuell 350 Height) übergebe mit Minimum 220 (iMinHeight) und Maximum 350 (iMaxHeight), dann wird das Formular erst einmal komplett lang gezogen (Min + Max). Bei anderen Controls funktioniert das ohne Probleme und ohne dieses initiale Langziehen.
if Control.Height >= iMaxHeight then
begin iNegative := -1; iTmp := iMinHeight + iMaxHeight; // DIESE ZEILE end else // if Control.Height <= iMinHeight then begin iNegative := 1; iTmp := iMinHeight end; while (D < 3000) do begin Control.Height := iTmp + (Round(iMaxHeight * Easing(D, 3000)) * iNegative); Application.ProcessMessages; D := GetTickCount - C; end; Meine Grundfrage wäre also... wie sieht das da unten umgekehrt aus?
Delphi-Quellcode:
while (D < Duration) do
begin Button1.Left := POS_START + Round(POS_END * CalculateEasingCurve(D, DURATION)); Application.ProcessMessages; D := GetTickCount - C; end; |
AW: Panel geschmeidig ein- und ausblenden?
Müsste es vielleicht so sein?
Delphi-Quellcode:
Es würde dann die maximale Höhe eingestellt (wenn ich das richtig interpretiere).
iTmp := iMaxHeight
Sonst startest Du mit der maximalen+minimalen Höhe. |
AW: Panel geschmeidig ein- und ausblenden?
Ich habe dir hier mal ein Beispiel gebastelt. Einfach in einen Button packen (Form sollte initial ~500 hoch sein) und die Caption beobachten.
Delphi-Quellcode:
Edit: siehe Kommentar bei Height >= POS_END
function QuintEasing(TimePassed, Duration: DWord): Single;
var P: Double; begin P := TimePassed / (Duration / 2); if (P < 1) then begin Result := 1 / 2 * P * P * P * P * P; end else begin P := P - 2; Result := 1 / 2 * (P * P * P * P * P + 2); end; end; Button var C, D: Cardinal; const Duration = 3000; POS_START = 200; // Größe eingeklappt POS_END = 500; // Größe ausgeklappt begin C := GetTickCount; D := 0; if Height >= POS_END then begin // EDIT // Mit diesem Spagetti-Code funktioniert es auch. Aber das ist sicherlich alles mehr als falsch // POS_END := POS_END - POS_START - (POS_END - Height); // POS_START := Height; while (D < Duration) do begin Height := POS_START - Round(POS_END * QuintEasing(D, Duration)); Application.ProcessMessages; D := GetTickCount - C; end; Caption := '1. ' + Height.ToString; // Formular wird beim ersten Klick erst einmalig 700px hoch eingestellt (falsch) und fährt dann auf 200px runter (richtig) end else begin // POS_START := Height; // POS_END := POS_END - POS_START; // Diese beiden Zeilen reparieren dieses If-Statement. Oben verstehe ich die umgekehrte Logik aber nicht und finde keine Lösung. while (D < Duration) do begin Height := POS_START + Round(POS_END * QuintEasing(D, Duration)); Application.ProcessMessages; D := GetTickCount - C; end; Caption := '2. ' + Height.ToString; // Ein anschließender Klick hier stellt das Formular 700px hoch ein (falsch) end; |
AW: Panel geschmeidig ein- und ausblenden?
Die Funktion ermittelt nicht, welche Höhe beim Start vorliegt, sondern entscheidet nur, ob von groß nach klein oder von klein nach groß animiert wird.
Fixen kannst Du das ggf. so:
Delphi-Quellcode:
So entsteht allerdings am Anfang eine Verzögerung, da ja die getimeten Berechnungen trotzdem erfolgen.
while (D < Duration) do
begin H := POS_START + POS_END - Round(POS_END * QuintEasing(D, Duration)); if (H < Height) then Height := H; Application.ProcessMessages; D := GetTickCount - C; end; Um das zu Verhindern müsstest Du die Berechnungsdauer (Duration) verkürzen oder besser in die Berechnung die Starthöhe einbeziehen. |
AW: Panel geschmeidig ein- und ausblenden?
Was denkst du denn über meine Änderung oben? Ich poste es hier unten noch einmal sauber neu:
Delphi-Quellcode:
Button
var C, D: Cardinal; const Duration = 3000; POS_START = 200; // Größe eingeklappt POS_END = 500; // Größe ausgeklappt begin C := GetTickCount; D := 0; if Height >= POS_END then begin // > ÄNDERUNG POS_END := POS_END - POS_START - (POS_END - Height); POS_START := Height; // < ÄNDERUNG while (D < Duration) do begin Height := POS_START - Round(POS_END * QuintEasing(D, Duration)); Application.ProcessMessages; D := GetTickCount - C; end; Caption := '1. ' + Height.ToString; end else begin // > ÄNDERUNG POS_START := Height; POS_END := POS_END - POS_START; // < ÄNDERUNG while (D < Duration) do begin Height := POS_START + Round(POS_END * QuintEasing(D, Duration)); Application.ProcessMessages; D := GetTickCount - C; end; Caption := '2. ' + Height.ToString; end; |
AW: Panel geschmeidig ein- und ausblenden?
Hast Du versucht, das zu compilieren?
Das geht so nicht, da man Pos_End nichts zuweisen kann, da das eine Konstante ist. Ich hatte vorhin schonmal versucht, die Starthöhe zu berücksichtigen. Das ist mir aber nicht gelungen. Vielleicht Zacherl man noch einen Tipp geben. Ich denke aber, dass eine Kurvenfunktion dafür die bessere Lösung wäre. (Ich bin aber mathematisch leider eine Niete und tue mich schwer mit so etwas.) |
AW: Panel geschmeidig ein- und ausblenden?
Zitat:
Es funktioniert nun einwandfrei, egal bei welcher Starthöhe. Es geht wird immer auf Minimum und Maximum gesetzt. Dafür sieht das auch etwas anders aus jetzt
Delphi-Quellcode:
Funktioniert so bestens.
if Height >= iMaxHeight then
begin iNegative := -1; // > ÄNDERUNG iTmp := iMinHeight; iMaxHeight := iMaxHeight - iTmp - (iMaxHeight - Height); iTmp := Height; end else // if Height <= iMinHeight then begin iNegative := 1; // > ÄNDERUNG iTmp := Height; iMaxHeight := iMaxHeight - iTmp; end; while (D < 3000) do begin iTmpRes := iTmp + (Round(iMaxHeight * QuintEasing(D, 3000)) * iNegative); // mache was mit iTmpRes end; Zitat:
Berechnet habe ich da nix, da ich nicht weiß wie. Ich habe einfach alle Variablen genommen, zusammengemixt und geguckt wann das Resultat bei allen Szenarien richtig ist. |
AW: Panel geschmeidig ein- und ausblenden?
Tatsächlich enthält mein Beispielcode einen kleinen Flüchtigkeitsfehler
Delphi-Quellcode:
statt
<
Delphi-Quellcode:
in der Schleifenbedingung. Habe die Kurvenfunktionen mal etwas intuitiver gestaltet:
<=
Delphi-Quellcode:
Erklärung der Parameter:
function EaseInQuart(T, B, C, D: Integer): Integer;
var T2: Single; begin T2 := T / D; Result := Round(C * T2 * T2 * T2 * T2) + B; end; function EaseOutQuart(T, B, C, D: Integer): Integer; var T2: Single; begin T2 := T / D - 1; Result := Round(-C * (T2 * T2 * T2 * T2 - 1)) + B; end; function EaseInQuint(T, B, C, D: Integer): Integer; var T2: Single; begin T2 := T / D; Result := Round(C * T2 * T2 * T2 * T2 * T2) + B; end; function EaseOutQuint(T, B, C, D: Integer): Integer; var T2: Single; begin T2 := T / D - 1; Result := Round(C * (T2 * T2 * T2 * T2 * T2 + 1)) + B; end; function EaseOutBounce(T, B, C, D: Integer): Integer; var T2: Single; begin T2 := T / D; if (T2 < (1.0 / 2.75)) then begin Result := Round(C * (7.5625 * T2 * T2)) + B; end else if (T2 < (2.0 / 2.75)) then begin T2 := T2 - (1.5 / 2.75); Result := Round(C * (7.5625 * T2 * T2 + 0.75)) + B; end else if (T2 < (2.5 / 2.75)) then begin T2 := T2 - (2.25 / 2.75); Result := Round(C * (7.5625 * T2 * T2 + 0.9375)) + B; end else begin T2 := T2 - (2.625 / 2.75); Result := Round(C * (7.5625 * T2 * T2 + 0.984375)) + B; end; end; function EaseOutElastic(T, B, C, D: Integer): Integer; var S, P, A, T2: Double; begin if (T = 0) then begin Exit(B); end; T2 := T / D; if (T2 = 1) then begin Exit(B + C); end; P := D * 0.3; A := C; if (A < Abs(C)) then begin S := P / 4; end else begin S := P / (2 * PI) * ArcSin(C / A); end; Result := Round(A * Power(2, -10 * T2) * Sin((T2 * D - S) * (2 * PI) / P)) + C + B; end; procedure TForm1.Button3Click(Sender: TObject); const DURATION = 1000; POS_START = 8; POS_END = 520; var C, D: Cardinal; begin // Über einen Zeitraum von 1 Sekunde von Position 8 nach Position 320 verschieben C := GetTickCount; D := 0; while (D <= DURATION) do begin Button1.Left := EaseOutElastic(D, POS_START, POS_END - POS_START, DURATION); Application.ProcessMessages; D := GetTickCount - C; end; Button1.Left := POS_END; end; procedure TForm1.Button4Click(Sender: TObject); const DURATION = 1000; POS_START = 520; POS_END = 8; var C, D: Cardinal; begin // Über einen Zeitraum von 1 Sekunde von Position 320 nach Position 8 verschieben C := GetTickCount; D := 0; while (D <= DURATION) do begin Button1.Left := EaseOutElastic(D, POS_START, POS_END - POS_START, DURATION); Application.ProcessMessages; D := GetTickCount - C; end; Button1.Left := POS_END; end;
Delphi-Quellcode:
Als Bonus gibt es noch die
T = Vergangene Zeit
B = Startwert C = Änderung D = Dauer der Animation
Delphi-Quellcode:
und die
EaseOutBounce
Delphi-Quellcode:
Kurven, welche ich persönlich ganz schick finde.
EaseOutElastic
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz