keyframes

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

keyframes

Beitrag von Mathias »

Einer eine Idee, wie man dies mit pas2js lösen könnte ?

https://www.w3schools.com/cssref/tryit. ... _keyframes

width, height, etc., kann man über

Code: Alles auswählen

mydiv := document.createElement('div');
mydiv1['type']
mitgeben.

Aber wie kann ich

Code: Alles auswählen

  animation: mymove 5s infinite;
bewerkstelligen ?
Vor allem das mymove.

Das keyframe selbst, wird ähnlichem diesem hier sein ?
https://wiki.freepascal.org/pas2js#Crea ... w_function
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: keyframes

Beitrag von Warf »

Die Animation ist keine Direkte Eigenschaft des DOM objektes (also des DIV), sondern ist eine CSS eigenschaft. Dafür gibt es zwei Wege. Der einfachste ist über die "Style" Property:

Code: Alles auswählen

mydiv['style'] := 'animation: mymove 5s infinite;'
Das ist schlicht und ergreifend der CSS Text den du in die CSS Definition schreiben würdest.

Das ist aber manchmal ein bisschen unübersichtlich weil du CSS mit code vermischst, deshalb kannst du das ganze auch in eine CSS Klasse auslagern:
Dafür musst du zunächst eine CSS Klasse definieren, mit der Eigenschaft:

Code: Alles auswählen

.MyClass {
    animation: mymove 5s infinite;
}
Danach musst du die Klasse zu den klassen des DOM objektes hinzufügen:

Code: Alles auswählen

mydiv['class'] := 'MyClass';
Wenn dein DOM objekt bereits schon eine Klasse hat musst du deine einfach dranhängen:

Code: Alles auswählen

mydiv['class'] := mydiv['class'] + ' ' + 'MyClass';

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: keyframes

Beitrag von Mathias »

Danke erst mal für die Infos.

Das was du in style reinschreibst, ist einleuchtend.

Und wie muss ich das handhaben, was in keyframes steht.
Auch das mymove muss irgendwo rein.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 338
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon (Windows wenn notwendig), Lazarus 3.0 FPC 3.3.1

Re: keyframes

Beitrag von Niesi »

Mathias hat geschrieben:
Do 25. Jan 2024, 17:30
Einer eine Idee, wie man dies mit pas2js lösen könnte ?

https://www.w3schools.com/cssref/tryit. ... _keyframes

width, height, etc., kann man über

Code: Alles auswählen

mydiv := document.createElement('div');
mydiv1['type']
mitgeben.

Aber wie kann ich

Code: Alles auswählen

  animation: mymove 5s infinite;
bewerkstelligen ?
Vor allem das mymove.

Das keyframe selbst, wird ähnlichem diesem hier sein ?
https://wiki.freepascal.org/pas2js#Crea ... w_function
Ich weiß nicht, ob ich Dich wirklich richtig verstanden habe - wenn Du bewegte Objekte ins web bringen möchtest, dann mach das doch mit Pas2JS ...

(Ist ein Gimmick von mir, für eine chinesische Schülerin erstellt und dann für meinen Sohn mit Pas2JS als WebApp compiliert.)


https://haraldnieswandt.de/gimmick/
Dateianhänge
WebGUIAppGimmick.7z
(65.51 KiB) 50-mal heruntergeladen
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: keyframes

Beitrag von Warf »

Mathias hat geschrieben:
Do 25. Jan 2024, 22:54
Und wie muss ich das handhaben, was in keyframes steht.
Auch das mymove muss irgendwo rein.
Das sind CSS animationen die musst du in einer CSS Datei (oder in einem Style Tag) im HTML definieren:

Code: Alles auswählen

<style> 
@keyframes mymove {
  from {top: 0px;}
  to {top: 200px;}
}
</style>
Das erstellt eine neue Animation mit namen "mymove", die du dann über die style Eigenschaft des DOM objektes benutzen kannst.
Niesi hat geschrieben:
Fr 26. Jan 2024, 07:40
Ich weiß nicht, ob ich Dich wirklich richtig verstanden habe - wenn Du bewegte Objekte ins web bringen möchtest, dann mach das doch mit Pas2JS ...
Der Vorteil an CSS ist, das es zum einen weniger Aufwand ist als die Bewegung selbst zu programmieren, zum anderen ist es Teil der Browser Rendering Engine statt des JavaScript Interpreters, und damit zum einen effizienter, und nicht Abbhängig von der sonstigen JS Workload. D.h. du kannst damit sehr viele Animationen machen während parallel noch JavaScript berechnungen laufen ohne in performance Probleme zu laufen.

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: keyframes

Beitrag von Mathias »

Folgender Code bewegt ein Rechteck und färbt es ein.

Code: Alles auswählen

<!DOCTYPE html>
<html>
<head>
<div>
<style> 
@keyframes blamove {
  from {top: 0px;background-color: red;}
  to {top: 200px;background-color: green;  }
}
div {
  width: 100px;
  height: 100px;
  position: relative;
  animation: blamove 5s infinite;
}
</style>
</head>
</div>
</html>
Das sind CSS animationen die musst du in einer CSS Datei (oder in einem Style Tag) im HTML definieren:
Nun habe ich es so versucht, aber es bleibt alles weiss.

Code: Alles auswählen

  mydiv := document.createElement('div');
  TJSHTMLElement( mydiv).style.cssText:='div {  width: 100px;  height: 100px;  position: relative;  animation: blamove 5s infinite;}@keyframes blamove {  from {top: 0px;background-color: red;}  to {top: 200px;background-color: green;  }}';

  document.body.appendChild(mydiv);

  Writeln('xxx'); // Zum Test
Auch über style geht es wie erwartet nicht.

Das ich alles in einem Schlauch habe, an dem liegt es kaum.
Ansonsten würde es in diesem Test-Fenster auch nicht gehen. https://www.w3schools.com/cssref/tryit. ... _keyframes
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: keyframes

Beitrag von Warf »

Du hast da ein kleines Missverständniss bezüglich wie CSS funktionert.

Jedes DOM Objekt wie dein DIV hat eine Reihe an Style attributen, wie width, height, position und background-color, das sind die sachen die du über Style setzen kannst:

Code: Alles auswählen

TJSHTMLElement(mydiv).style.cssText := 'width:200px; height:200px'
Das setzt die beiden Attribute width und height auf 200 pixel.

Das ist aber nicht der einzige weg wie das Objekt an Styles kommt, daneben gibt es noch 3 weitere Möglichkeiten, Vererbung, Klassen/IDs und Tageinstellungen. Vererbung ist relativ einfach, wenn du z.B. den Font für ein div setzt gilt der Font auch für alle unterliegenden Objekte, und ist für hier nicht relevant.

Interessant sind Klassen/IDs und Tags, denn die können über CSS Definiert werden. Beispiel:

Code: Alles auswählen

<style>
#MyDiv {
  width:200px;
  height:200px;
}

.MyClass {
  width:100px;
  height:100px;
}
</style>

<div id="MyDiv"></div>
<div class="MyClass"></div>
Das # in CSS definiert eigenschaften die für das Element mit dieser ID gelten sollen, der . definiert Eigenschaften für alle Elemente die diese Klasse haben. Der Unterschied ist, es gibt immer genau ein Element mit einer bestimmten ID, aber mehrere Elemente können die Selbe Klasse haben, und ein Element kann mehrere Klassen haben:

Code: Alles auswählen

<style>
.Red {
  background-color: red;
}

.Green {
  background-color: green;
}

.Square {
  width: 200px;
  height: 200px;
}
</style>

<div class="Red Square"></div>
<div class="Green Square"></div>
Eine Klasse bzw. ID ist also so zu sagen nur die "Voreinstellung" von den Style Attributen die ein Element mit dieser Klasse oder ID erhalten soll.
Neben klassen und IDs gibts auch noch tag einstellungen:

Code: Alles auswählen

<style>
div {
  width: 200px;
  height: 200px;
  background-color: red;
}
</style>

<div></div>
<div></div>
Da hier jetzt kein . oder # vor dem namen ist, wird diese CSS Regel auf alle DOM elemente mit dem tag "div" angewendet.

Um also das Beispiel aus W3C zu nehmen:

Code: Alles auswählen

div {
  width: 100px;
  height: 100px;
  background: red;
  position: relative;
  animation: mymove 5s infinite;
}
Sagt jedes DIV im dokument soll diese größe, farbe und animation durchführen. Das Funktioniert in dem Minimalbeispiel, weil es nur ein div gibt. Wenn du ein bestimmtes element setzen willst, dann solltest du keine tag basierten Regeln benutzen.

Zu guter letzt, man kann Regeln in CSS kombinieren:

Code: Alles auswählen

<style>
.MyClass div {
  width: 200px;
  height: 200px;
  background-color: red;
}
</style>

<div></div>
<div class="MyClass"><div></div></div>/code]
Hier wird die Regel auf alle "div" elemente angewendet die Kinder von einem MyClass Element sind. Das heist, das erste div in diesem beispiel ist nicht davon betroffen, beim zweiten Div allerdings das interne, da das das Kind eines MyClass divs ist.

[hr]

Jetzt zu deinem Problem:
[code]TJSHTMLElement( mydiv).style.cssText:='div {  width: 100px;  height: 100px;  position: relative;  animation: blamove 5s infinite;} [...]';
Das funktioniert nicht, weil du hier nicht style Eigenschaften setzt, sondern du definierst CSS regeln für DIVs. Solche regeln sind global und müssen in einem style Tag definiert werden.

Was du stattdessen machen solltest ist, du solltest die CSS regeln in einem Seperaten Style Block (oder besser einer CSS Datei) definieren, und dann dem element einfach nur noch die Klasse zuweisen. Ich gebe dir hier jetzt ein Beispiel in Javascript weil ich kein Pas2JS zur hand habe, das konzept ist aber das gleiche:

Code: Alles auswählen

<!DOCTYPE html>
<html>
  <head>
    <script src="test.js"></script>
    <style>
      .AnimatedClass {
        width: 100px;
        height: 100px;
        background: red;
        position: relative;
        animation: mymove 5s infinite;
      }

      @keyframes mymove {
        from {top: 0px;}
        to {top: 200px;}
      }
    </style>
  </head>
  <body onload="siteLoaded()">
  </body>
</html>
Mit dem folgenden Javascript code:

Code: Alles auswählen

function siteLoaded() {
  // Erstelle neues div element
  let newDiv = document.createElement("div");
  // Setze die klasse auf AnimatedClass (definiert in CSS style)
  newDiv.className = "AnimatedClass";
  // Füge div zu website hinzu
  document.body.appendChild(newDiv);
}

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: keyframes

Beitrag von Mathias »

Ein Schritt bin ich weiter gekommen, ohne das ich in die HTML oder in eine CSS-Datei eingreifen muss.
Mein Ziel ist es, möglichst alles auf der Pascal-Ebene zu lösen.

Code: Alles auswählen

  type
    TNewJSHTMLElement = class(TJSHTMLElement)
      procedure animate(contextAttributes : TJSObject);varargs external name 'animate';
    end;
var
  mydiv: TJSElement;
begin
  mydiv := document.createElement('div');
  mydiv['style'] := 'width: 300px;  height: 200px;';
  document.body.appendChild(mydiv);

  TNewJSHTMLElement(mydiv).animate(
    new([
      'background', TJSArray._of('black', 'red', 'black'),
      'width', TJSArray._of('100px', '300px', '100px')]),
    10000);
Ich sehe schon es führen viele Wege nach Rom.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: keyframes

Beitrag von Warf »

Mathias hat geschrieben:
Sa 27. Jan 2024, 09:07
Ein Schritt bin ich weiter gekommen, ohne das ich in die HTML oder in eine CSS-Datei eingreifen muss.
Mein Ziel ist es, möglichst alles auf der Pascal-Ebene zu lösen.
Das kannst du zwar machen, damit machst du aber den selben Fehler den JavaScript entwickler vor 10 Jahren gemacht haben, da damit die Seiten extrem langsam laden, ineffizient und fehleranfällig sind und sich auch nicht cachen lassen.
Reine HTML Websites laden in wenigen MS, effektiv nur durch die Netzwerkverbindung limitiert. Wenn man versucht das selbe mit JavaScript aufzubauen kann man z.T. im Sekundenbereich landen bis alles geladen ist. Wir reden hier also von einem Faktor 100-1000

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: keyframes

Beitrag von Mathias »

Wir reden hier also von einem Faktor 100-1000
Ups, mach das so viel aus!
Auf dem PC wird man dies kaum merken, aber auf einem lahmen Android-Gerät wird man es sicher extrem merken.

Verstehe ich es richtig, wen man voll auf Speed ist.

Alles statische per HTML und CSS-Dateien bauen.
Und Javascript erst nehmen, wen sich etwas zur Laufzeit ändert.

Somit wird das TW- Widgetset sicher auch recht lahm sein ?

Somit muss man sich echt fragen, was ist einem wichtiger komfortables Programmieren oder eine schnelle Seite.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: keyframes

Beitrag von Warf »

Genau, Browser sind extrem schnell darin Statische HTML Seiten zu Zeichnen, da HTML bereits angefangen werden kann zu zeichnen bevor die ganze Seite geladen ist und somit ist die Zeit zum Zeichnen meist nicht länger als die Ladezeit des Netzwerks.
Während wenn du alles Dynamisch erstellst, muss erst einmal das ganze Javascript runtergeladen werden, und dann Stück für Stück ausgeführt werden. Gleichzeitig ist der JavaScript interpreter zwar sehr schnell (für eine Scriptsprache), aber nicht im Ansatz so optimiert wie der native rendering Code des Browsers.

Die Erfahrung haben JavaScript Entwickler so um 2016-2018 rum gemacht, als alle Websites aus OnePage Angular/React Anwendungen bestanden hat, und man das zwar Lösen kann (indem z.B. Teile des JavaScript Codes zum bauen der Website auf dem Server ausgeführt werden, und dann das gebaute HTML rübergesendet wird), ist es doch oftmals einfacher einfach die Website mit HTML zu bauen, und dann nur da wo es nötig ist für die Laufzeit JavaScript einzubauen.

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: keyframes

Beitrag von Mathias »

Ich glaube es fast nicht, aber einfacher geht es kaum noch, was meine erste Frage anbelangt.
Ich habe herausgefunden, das man mit element,.innerHTML der komplette Inhalt eines HTML-Blockes schreiben kann.

Code: Alles auswählen

  document.body.innerHTML :=
    '<div>' +
    '  <style>' +
    '    div {' +
    '      width: 100px;' +
    '      height: 100px;' +
    '      background: red;' +
    '      position: relative;' +
    '      animation: mymove 5s infinite;' +
    '    }' +
    '' +
    '    @keyframes mymove {' +
    '      from {top: 0px;}' +
    '      to {top: 200px;}' +
    '    }' +
    '  </style>' +
    '</div>';  
Genau, Browser sind extrem schnell darin Statische HTML Seiten zu Zeichnen, da HTML bereits angefangen werden kann zu zeichnen bevor die ganze Seite geladen ist und somit ist die Zeit zum Zeichnen meist nicht länger als die Ladezeit des Netzwerks.
Wie sieht es da mit meiner jetzt entdeckten Lösung aus, ist dies immer noch viel lahmer als bei dem direkten Reinschreiben in die HTML ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: keyframes

Beitrag von Warf »

Es wird immernoch langsamer sein als wenn du das HTML direkt über deinen Webserver Auslieferst, da jetzt nach wie vor zu erst das JavaScript geladen werden muss, bevor das HTML durch das JavaScript erzeugt wird, allerdings sollte das HTML durch InnerHTML zu erzeugen schneller sein als mit JavaScript jeden Tag einzeln zu erstellen.

Das Problem hierbei ist, Pas2JS generiert dir JavaScript dateien mit Zehntausenden zeilen Code. Die müssen ganz runtergeladen werden bevor das JavaScript ausgeführt wird. Wenn du allerdings eine HTML Seite statisch hast und dann das JavaScript als seperate Datei einlädst, dann kann die HTML Datei schon fertig heruntergeladen, geparsed und gerendert werden bevor die JavaScript Datei vollständig runtergeladen wurde. Somit ist deine Website schon voll da und sichtbar, ohne das auf alles andere gewartet werden muss.

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: keyframes

Beitrag von Mathias »

Das Problem hierbei ist, Pas2JS generiert dir JavaScript dateien mit Zehntausenden zeilen Code.
Da muss ich dir leider recht geben, gerade spärlich wird da nicht umgegangen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 834
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: keyframes

Beitrag von PascalDragon »

Mathias hat geschrieben:
So 28. Jan 2024, 19:15
Das Problem hierbei ist, Pas2JS generiert dir JavaScript dateien mit Zehntausenden zeilen Code.
Da muss ich dir leider recht geben, gerade spärlich wird da nicht umgegangen.
Das ist der Preis, den man zahlen muss, um die gewohnte FPC/Delphi RTL nutzen zu können 🤷‍♀️
FPC Compiler Entwickler

Antworten