Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Farbanimation mit TCanvas (https://www.delphipraxis.net/185052-farbanimation-mit-tcanvas.html)

DerHaushaltsProfi 11. Mai 2015 16:42


Farbanimation mit TCanvas
 
Moin moin,

ich habe ein Rechteck in meine Canvas gezeichnet. Das Rechteck wurde in der Farbe clgreen "gebrusht". Nun möchte ich, wenn man auf einen Button drückt, dass das Rechteck seine Farbe ändert. Es soll von grün zu schwarz werden. Das ganze soll für den Nutzer des Programmes sichtbar sein und es soll ein "Farbverlauf" dargestellt sein. Mein Problem ist jetzt allerdings, dass ich nicht weiß wie man diesen Farbverlauf hin bekommt. Es soll nicht einfach von grün auf schwarz springen, es soll schon von grün über blau über gelb über rot zu schwarz werden (wie eine kleine Animation also). Wie kann man so etwas realisieren? Der Quelltext soll nicht aus brush.color := clgreen , brush.color := clblue brush.color := clyellow ..... bestehen. Es soll praktisch eine Funktion sein die dem Farbwert (z.B.) immer 5 dazu rechnet und er sich so, bis er bei schwarz ist, verändert. Ich hoffe ich habe mich (halbwegs :lol:) verständlich ausgedrückt.

FÜr Antworten bedanke ich mich schon mal im Vorraus

mfg

Popov 11. Mai 2015 17:05

AW: Delphi verändern
 
Nehmen wir mal als Vorlage eine alte FormGradient Funktion und ändern sie leicht ab, bekommen wir eine Funktion mit dem wir ein Mischungsverhältnis zweier Farben berechnen können:

Delphi-Quellcode:
function ColorMix(Color1, Color2: TColor; Index, Count: Word): TColor;
var
  R, G, B: Integer;
begin
  if Index > Count then
    Index := Count;

  R := Round(GetRValue(Color1) + ((GetRValue(Color2) - GetRValue(Color1)) *
    Index / Count));
  G := Round(GetGValue(Color1) + ((GetGValue(Color2) - GetGValue(Color1)) *
    Index / Count));
  B := Round(GetBValue(Color1) + ((GetBValue(Color2) - GetBValue(Color1)) *
    Index / Count));

  Result := RGB(R, G, B);
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  Count = 100;
var
  Index: Integer;
begin
  with Canvas do
  begin
    Pen.Width := 5;

    for Index := 0 to Count do
    begin
      Pen.Color := ColorMix(clGreen, clRed, Index, Count);
      Rectangle(100, 100, 500, 400);
      Sleep(20);
    end;
  end;
end;

stahli 11. Mai 2015 17:07

AW: Delphi verändern
 
Du müsstest wohl mal nach RGB suchen und Dich mit Farbfunktionen beschäftigen.
Dann könntest Du die Rot- Grün - und Blau-Anteile der Start- und Endfarbe ermitteln und diese schrittweise verändern.

Ich hatte mich mal mit Helligkeitsänderungen befasst, das ist aber lange her:
http://www.delphipraxis.net/88775-fa...eraendern.html

Ggf. kann Dir eine Bibliothek wie Graphic32 helfen.

Perlsau 11. Mai 2015 17:21

AW: Delphi Farbe verändern
 
Bereits der erste Treffer bei der Google-Suche nach Delphi+Canvas+Farbverlauf führt zu einem Tutorial beim Delphi-Treff, und das sogar in verständlichem Deutsch:

Die Prozedur DrawGradient ermöglicht es, einen linearen Farbverauf zu zeichnen. Der Farbverlauf erfolgt je nach Wahl des Parameters GradientOrientation Vertical oder Horizontal. Color1 und Color2 geben die Farben an, zwischen denen der Farbverlauf stattfinden soll. Der Parameter Rect gibt den Bereich an, in dem gezeichnet werden sollen. Die Koordinaten sind relativ zur oberen linken Ecke des übergebenen Canvas.

Jens01 11. Mai 2015 17:43

AW: Delphi verändern
 
Für Gradienten so alleinstehend ist diese Komponente "führend". Mit Graphics32 geht das auch gut, man muss so aber vorher tief reinarbeiten.

DeddyH 11. Mai 2015 17:46

AW: Delphi Farbe verändern
 
Ich glaube, es geht eher um so etwas wie in diesem Thread.

bcvs 11. Mai 2015 18:36

AW: Delphi verändern
 
Wenn ich das richtig verstanden habe, geht es hier nicht um einen Farbverlauf (Gradient) sondern um eine animierte Farbänderung. Das könnte man mit einem Timer machen, der das Rechteck mit leicht geänderter Farbe immer wieder neu malt, bis die Zielfarbe erreicht ist.

Für die Farbänderung könnten die Algorithmen aus der Gradient-Funktion hilfreich sein.

Perlsau 11. Mai 2015 19:20

AW: Delphi verändern
 
Ein Farbverlauf, der sich ständig ändern soll, muß aber dennoch erst einmal gezeichnet werden. Ist das Zeichnen des Farbverlaufs beendet, wird die Zeichnen-Methode mit entsprechend geänderten Parametern wiederholt. Zumindest habe ich das so verstanden, daß nicht die gesamte Zeichenfläche mit einer Farbe gefüllt werden soll, danach mit einer anderen Farbe usw., sondern daß sich ändernde Farbverläufe angezeigt werden sollen. Was ist denn ein Gradient anderes als ein Farbverlauf? Das, was du verstanden zu haben glaubst, wäre ja mit FillRect leicht umzusetzen.

DeddyH 11. Mai 2015 19:25

AW: Delphi verändern
 
Meiner Meinung nach hat es bcvs genau erfasst, siehe auch mein Link oben, alles schon dagewesen.

Captnemo 11. Mai 2015 19:59

AW: Delphi verändern
 
Der Threadtitel ist aber äußerst unglücklich gewählt.

Was ich aus dem TE-Beitrag noch nicht verstanden habe, soll er denn nun vollflächig zu den Farben überblenden, oder in einer laufenden Bewegung die Farben bis zu Zielfarbe runterlaufen? Das wären zwei völlig unterschiedliche Anforderungen.

Popov 11. Mai 2015 20:16

AW: Delphi verändern
 
Ich hab zuerst verstanden es geht um die Rechtecklinie.

Egal. Ich hab noch jetzt die alte DrawGradientH Funktion genommen und neue die ColorMix, hab alles in einen Timer gepackt. Fertig ist "The Incredible Delphi-Form Color Show".

Delphi-Quellcode:
procedure DrawGradientH(Canvas: TCanvas; Color1, Color2: TColor; Rect: TRect);
var
  X, R, G, B: Integer;
begin
  for X := Rect.Top to Rect.Bottom do begin
    R := Round(GetRValue(Color1) + ((GetRValue(Color2) - GetRValue(Color1)) *
      X / (Rect.Bottom - Rect.Top)));
    G := Round(GetGValue(Color1) + ((GetGValue(Color2) - GetGValue(Color1)) *
      X / (Rect.Bottom - Rect.Top)));
    B := Round(GetBValue(Color1) + ((GetBValue(Color2) - GetBValue(Color1)) *
      X / (Rect.Bottom - Rect.Top)));

    Canvas.Pen.Color := RGB(R, G, B);
    Canvas.Pen.Width := 1;
    Canvas.Pen.Style := psInsideFrame;

    Canvas.MoveTo(Rect.Left, X);
    Canvas.LineTo(Rect.Right, X);
  end;
end;

function ColorMix(Color1, Color2: TColor; Index, Count: Word): TColor;
var
  R, G, B: Integer;
begin
  if Index > Count then
    Index := Count;

  R := Round(GetRValue(Color1) + ((GetRValue(Color2) - GetRValue(Color1)) *
    Index / Count));
  G := Round(GetGValue(Color1) + ((GetGValue(Color2) - GetGValue(Color1)) *
    Index / Count));
  B := Round(GetBValue(Color1) + ((GetBValue(Color2) - GetBValue(Color1)) *
    Index / Count));

  Result := RGB(R, G, B);
end;

var
  Col1, Col2, Col3, Col4: TColor;

procedure TForm1.Timer1Timer(Sender: TObject);
const
  Count = 100;
begin
  with Sender as TTimer do
  begin
    Interval := 1;

    if Tag = 0 then
    begin
      Col2 := RGB(Random(256), Random(256), Random(256));
      Col4 := RGB(Random(256), Random(256), Random(256));
    end;

    DrawGradientH(Canvas, ColorMix(Col1, Col2, Tag, Count), ColorMix(Col3, Col4, Tag, Count), Canvas.ClipRect);

    Tag := Tag + 1;
    if Tag > Count then
    begin
      Tag := 0;
      Col1 := Col2;
      Col3 := Col4;
    end;
  end;
end;

bcvs 12. Mai 2015 07:42

AW: Delphi verändern
 
Zitat:

Zitat von Perlsau (Beitrag 1301119)
Das, was du verstanden zu haben glaubst, wäre ja mit FillRect leicht umzusetzen.

Ja genau, das wäre einfach. Der Haushaltsprofi müsste halt nochmal beschreiben, wass er genau will.

Perlsau 12. Mai 2015 08:20

AW: Delphi verändern
 
Zitat:

Zitat von bcvs (Beitrag 1301149)
Zitat:

Zitat von Perlsau (Beitrag 1301119)
Das, was du verstanden zu haben glaubst, wäre ja mit FillRect leicht umzusetzen.

Ja genau, das wäre einfach. Der Haushaltsprofi müsste halt nochmal beschreiben, wass er genau will.

... denn sonst stochern wir weiter im Nebel rum und stechen uns dabei noch aus Versehen gegenseitig :)

DerHaushaltsProfi 12. Mai 2015 15:18

AW: Delphi verändern
 
So da es einige Missverständnisse gibt werde ich es nochmal genau erklären :-D
So ich würde gerne einen Farbübergang (KEINEN Farbverlauf) von einer Farbe beginnend über andere Farben zu einer Zielfarbe. Wie es bei Verfärbungen halt üblich ist (z.B. in der Chemie). Eigentlich soll es in meinem Programm auch um Chemie Nachweise gehen. Und dafür brauche ich diese Verfärbung. Wenn ich einen Nachweis mache und die nachzuweisende Chemikalie mit einem Nachweismittel nachweise (und eine ver. bzw. entfärbung stattfindet) dann macht es ja nicht zack und aus einer blauen Lösung wird eine gelbe. Es wird erstmal hellblau dann hellgelb dann gelb. Ich hoffe, dass es nun etwas verständlicher ist :D. Ich habe also in meiner Canvas mittels Halbkreis und Rechteck ein reagenzglas gezeichnet und will nun immer nur den unteren Halbkreis neu einfärben. Ich hoffe das ist nun verständlich :)

mfg

Mavarik 12. Mai 2015 15:46

AW: Delphi verändern
 
Ändere doch bitte mal den Threadtitle...

himitsu 12. Mai 2015 16:02

AW: Delphi verändern
 
Du hast auch noch 35 Minuten Zeit dafür. (24 Stunden lang)

> Bearbeien > Erweitert


Bei Torry oder in der CodeLib gibt es Funktionen, denen man zwei Farben geben kann und die dann über einen dritten Parameter (Prozent) eine Mischfarbe rausrücken.
Ansonsten Mathematik > in RGB-Anteile zerlegen und dann jeden Anzeil berechnen und wieder zusammensetzen

bcvs 12. Mai 2015 16:26

AW: Delphi verändern
 
Zitat:

Zitat von DerHaushaltsProfi (Beitrag 1301225)
So ich würde gerne einen Farbübergang (KEINEN Farbverlauf) von einer Farbe beginnend über andere Farben zu einer Zielfarbe.


Dann mach das doch mit einem Timer:

geeignetes Timerintervall festlegen (vielleicht 10, musst du halt ausprobieren).

Im Timerevent setzt du die Farbe auf den nächsten Farbwert und malst du den Halbkreis komplett neu, solange bis die Zielfarbe erreicht ist. Du brauchst nur noch den Algorithmus für die Berechnung des nächsten Farbwertes. Vielleicht wirst du da bei den hier schon geposteten Codeschnipsel für Gradienten fündig.

DeddyH 12. Mai 2015 17:41

AW: Delphi verändern
 
In dem auf Seite 1 verlinkten Thread hatte ich eine Beispielanwendung gepostet (damals noch Delphi 7). Ist das ungefähr das, was dabei herauskommen soll?

Harry Stahl 12. Mai 2015 18:10

AW: Delphi verändern
 
Liste der Anhänge anzeigen (Anzahl: 3)
Du hast nicht dabei geschrieben, welche Delphi-Version Du verwendest. Wenn Du eine neuere Delphi-Version nutzt, kannst Du das auch mit FireMonkey lösen, für solche Sachen ist es nahezu ideal.

Ich habe anliegend mal ein Beispiel angefügt (erstellt in XE7), das ich hier in 5 Minuten zusammengeklickt habe. Mittels eine Farbanimation wechselt die "Flüssigkeit" (welche aus einer Kombination aus Rectangles und Elipsen besteht) von der Farbe Blau nach Gelb (in dem rechten Kolben).

Die Dauer des Übergangs kann man unter "Duration" einstellen (hier habe ich mal 2 Sekunden gewählt). Auch kann man festlegen, ob der Farbübergang Linear erfolgen soll oder z.B. exponential (unter "Interpolation").

Sollen hier noch andere Farbstufen dazwischen erscheinen, kann man statt der ColorAnimation eine GradientAnimation verwenden, wo man sich die Zwischenfarben einfach in dem Gradient-Dialog zusammen klicken kann.

Popov 12. Mai 2015 18:49

AW: Delphi verändern
 
Zitat:

Zitat von DerHaushaltsProfi (Beitrag 1301225)
So da es einige Missverständnisse gibt werde ich es nochmal genau erklären :-D

Mal davon abgesehen, dass im Beitrag #2 nicht die Füllfarbe, sondern die Rahmenfarbe innerhalb einer bestimmten Zeit von einer Farbe zu einer anderen wechselt, was stimmt mit dem Beispiel in #2 nicht?

DerHaushaltsProfi 12. Mai 2015 18:51

AW: Delphi verändern
 
Liste der Anhänge anzeigen (Anzahl: 1)
@Harry Stahl gaaaaanz so komplex muss es nun auch nicht sein ;D

also ich kann hier mal ein Bsp ran hängen wie ich mir das ungefähr vorgestellt habe. Nur bei mir ist es halt noch nicht ganz "ausgereift" das kann man bestimmt noch kürzen oder optimieren.

@Popov Ihr Quelltext ist (da ich noch Delphi Anfänger bin :D) echt kompliziert... Ich blicke da leider nicht ganz durch :/. Ich habe aber jetzt einige Tage frei und werde mal eine kleine Recherche betreiben und gucken ob mir Ihr Quelltext weiterhilft.

Trotzdem schon jetzt mal ein großes Danke an alle Helfer

mfg

Popov 12. Mai 2015 20:11

AW: Delphi verändern
 
Zitat:

Zitat von DerHaushaltsProfi (Beitrag 1301254)
@Popov Ihr Quelltext ist (da ich noch Delphi Anfänger bin :D) echt kompliziert...

Deswegen habe ich dir auch eine fertige ColorMix Funktion gepostet.

Das "Problem" mit der TColor Farbe ist nicht, dass die Farbe Rot den Wert 255 hat und die Farbe Blau den Wert 16711680 und man mit einer For-Schleife einfach nur den Wert von dem einen zum anderen erhöhen muss, um einen Wechsel von rot zu blau zu bekommen. Das klappt nicht. Bei der Farbe TColor, die aus 4 Bytes besteht, wobei was 1 Byte eine spezielle Bedeutung hat, stehen die anderen drei Bytes für die drei RGB-Farben rot, grün und blau. Ein Byte für rot, ein für Grün, usw. Ein Byte kann zwischen 0 und 255 256 Zustände annehmen. Somit ist 0 0% rot und 255 100% rot. Dazwischen gibt es 256 Abstufungen. Kombiniert man alle drei Farben mit 256 Abstufungen, ergibt das 256 * 256 * 256 = 16.777.216 mögliche Farben.

Um nun von einer Farbe zu anderen Zwischenschritte zu berechnen, muss man die TColor Farbe zuerst in die einzelnen RGB Farben zerlegen, die Zwischenschritte für jede einzelne Farbe berechnen, und dann alle drei wieder zu einer Zahl zusammenfügen. Der TColor Zahl.

Und das passiert in der ColorMix Funktion.

bcvs 12. Mai 2015 20:19

AW: Delphi verändern
 
In deinen Repeat until-Schleifen tut sich ja gar nichts.

statt
Delphi-Quellcode:
repeat
  a:=a+1;
until a>123;
kannst du auch gleich schreiben
Delphi-Quellcode:
a:=124
; mehr macht diese Schleife nicht. Du muss innterhalb jeder dieser Repeat-Schleifen nochmal
Delphi-Quellcode:
    Paintbox1.Canvas.Brush.Color:=rgb(a, b, c);
    Paintbox1.Canvas.Pie(60, 160, 100, 200, 60, 180, 100, 180);
    sleep(10);
machen und die äußere Repeat-Schleife weglassen. Dann werden die RGB-Werte getrennt voneinander nacheinander aminiert geändert. Ist das so gewollt? Andernfalls muss du den Beitrag von Popov berücksichtigen.

Ein Timer wäre eleganter, aber so geht's auch. Denk aber dran, dass das Reagenzglas nochmal mit der aktuellen Farbe im OnPaint das Paintbox gemalt werden muss, sonst ist es weg, wenn dein Fenster mal verkleiner und wiederhergestellt wird.

Noch ein par Tips:

- Quelltext ist Text, wie der Name schon sagt, also postet man den auch als Text und nicht als Screenshot.

- Wenn du schon Integer-Variablen für RGB-Werte hast, warum heißen die a,b,c und nicht r,g,b?

- Lass das With weg. Später schreibst du ja Paintbox1.Canvas.Brush.Color sowieso aus, dann kannst du dir das with doch sparen. Ohne with weiß man immer genau, was gemeint ist.

Harry Stahl 12. Mai 2015 20:22

AW: Delphi verändern
 
Zitat:

Zitat von DerHaushaltsProfi (Beitrag 1301254)
@Harry Stahl gaaaaanz so komplex muss es nun auch nicht sein ;D

Ich weiß nicht, ob Du mal in den Source reingesehen hast, insofern nur noch der Hinweis, dass der von mir erstellte Source-Code aus ganzen 4 Zeilen besteht:

Delphi-Quellcode:
procedure TForm11.Button1Click(Sender: TObject);
begin
  ColorAnimation1.Enabled := false;
  ColorAnimation1.Enabled := true;
end;

procedure TForm11.ColorAnimation1Process(Sender: TObject);
begin
  Ellipse1.Fill.Color := Rectangle2.Fill.Color;
  Ellipse4.Fill.Color := Rectangle2.Fill.Color;
end;
Das würde ich nicht unbedingt als komplex berzeichnen:wink:. Aber man kann das natürlich auch auf die "harte Tour" machen, zum Lernen ist das sicher nicht verkehrt.

Zu Deiner Vorstellung für die VCL-Lösung: Du solltest das Zeichnen der Grafik im OnPaint-Event der Paintbox vornehmen. Denn was Du derzeit malst, ist nur "flüchtig" (minimiere mal nach dem Klick auf den Button das Formular, Deine Zeichnung ist dann verschwunden).

Besser wäre es hier Variabeln anzulegen, diese in gewissen Zeitabständen zu aktualisieren und dann jeweils auch die Paintbox aktualisieren zu lassen.

Und zu TColor hat Dir Popov gerade die entscheidenden Hinweise gegeben.

Popov 12. Mai 2015 20:36

AW: Delphi verändern
 
Hier etwas ganz simples. Noch einfacher geht es nicht:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
const
  Farben: array[0..9] of TColor = ($00FF0000, $00E6001A, $00CC0033, $00B2004C,
    $00990066, $00800080, $00660099, $004C00B2, $003300CC, $001A00E6);
var
  i: Integer;
begin
  for i := 0 to 9 do
  begin
    Panel1.Color := Farben[i];
    Sleep(100);
    Application.ProcessMessages;
  end;
end;
Die Konstante Farben beinhaltet 10 Farben in einem Array. Die erste Farbe ist blau, die letzte ist rot. Die anderen Farben dazwischen sind Abstufungen. Dann nur noch die Farben in Reihe aufrufen.

Die Version verlangt am Anfang mehr Arbeit, da man die Farben erst von Hand berechnen muss, später ist es dafür ganz simpel.

DerHaushaltsProfi 13. Mai 2015 09:07

AW: Delphi verändern
 
Danke an alle für die vielen Versuche mir zu helfen!

Popov mir gefällt deine "ganz simple" Lösung echt gut ich werde die auch verwenden!

mfg

BadenPower 13. Mai 2015 10:36

AW: Delphi verändern
 
Zitat:

Zitat von DerHaushaltsProfi (Beitrag 1301329)
Popov mir gefällt deine "ganz simple" Lösung echt gut ich werde die auch verwenden!

Vor allem bietet diese Lösung mit dem Farb-Array eine bequeme Möglichkeit die Änderungen der Farbwerte so zu gestalten, wie sie beim chemischen Experiment auch tatsächlich vorkommen.

stahli 13. Mai 2015 10:39

AW: Delphi verändern
 
Wenn man es später aber evtl. für verschiedene Farben benötigt oder die Stufen feiner braucht, dann wird man es berechnen müssen.

BadenPower 13. Mai 2015 10:49

AW: Delphi verändern
 
Zitat:

Zitat von stahli (Beitrag 1301340)
Wenn man es später aber evtl. für verschiedene Farben benötigt oder die Stufen feiner braucht, dann wird man es berechnen müssen.

Dann musst Du aber auch für jede erdenkliche Kombination der mischbaren chemischen Elemente den entsprechenden Algo programmieren.

Denn Substanz A mit B gibt eine andere Farbübergangstabelle als A mit C oder B mit C oder B mit C und A.

stahli 13. Mai 2015 11:04

AW: Delphi verändern
 
Ok das macht Sinn.

Ich hatte es ursprünglich so verstanden, dass ein fließender Wechsel von Farbe A zu B gewünscht ist. Und das könnte man m.E. durch Zerlegung in Rot, Grün und Blau und prozentuale Annäherung zur Zielfarbe hin erreichen.

[EDIT]
Diesen fließenden Wechsel könnte man natürlich benutzen, um von einer Array-Farbe zur nächsten zu wechseln. Dann hätte man einen sehr fließenden optischen Farbwechsel und keine Farbsprünge.

himitsu 13. Mai 2015 11:39

AW: Delphi verändern
 
Zitat:

Zitat von stahli (Beitrag 1301345)
Diesen fließenden Wechsel könnte man natürlich benutzen, um von einer Array-Farbe zur nächsten zu wechseln. Dann hätte man einen sehr fließenden optischen Farbwechsel und keine Farbsprünge.

Farbverlaufberechnungsfunktionen gibt es Viele.
  • Einige die nur zwei Farben annehmen
  • und Andere nehmen auch ein Array und berechnen den Farbverlauf über mehrere Fixpunkte hinweg

SMO 13. Mai 2015 14:48

AW: Delphi verändern
 
Hat noch niemand Gammakorrektur angesprochen? Lineare Interpolation von RGB-Werten wie von Popovs "ColorMix" durchgeführt ist zwar weit verbreitet, aber streng genommen falsch.

Siehe dieses Video und diesen Artikel.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz