Eine kurze Diskussion über Lösungen zum Stören von CSS3-Animationen

Eine kurze Diskussion über Lösungen zum Stören von CSS3-Animationen

Warum steckt es fest?

Es gibt eine Prämisse, die erwähnt werden muss. Front-End-Entwickler wissen alle, dass der Browser in einem einzigen Thread ausgeführt wird. Wir müssen jedoch die folgenden Konzepte klären: Einzelthread, Hauptthread und Synthesethread.

Obwohl der Browser JS in einem einzigen Thread ausführt (beachten Sie, dass es sich um Ausführung handelt und nicht darum, dass der Browser nur einen Thread hat, sondern dass er ausgeführt wird), verfügt der Browser tatsächlich über zwei wichtige Ausführungsthreads, die zusammenarbeiten, um eine Webseite darzustellen: den Hauptthread und den Synthesethread.

Im Allgemeinen ist der Hauptthread für Folgendes verantwortlich: Ausführen von JavaScript, Berechnen der CSS-Stile von HTML-Elementen, Layout der Seite, Zeichnen von Elementen in eine oder mehrere Bitmaps und Übergeben dieser Bitmaps an den Synthesethread.

Dementsprechend ist der Kompositionsthread für Folgendes verantwortlich: Zeichnen der Bitmap auf dem Bildschirm über die GPU; Benachrichtigen des Hauptthreads, dass die Bitmap des sichtbaren oder bald sichtbaren Teils der Seite aktualisiert werden soll; Berechnen, welcher Teil der Seite sichtbar ist; Berechnen, welcher Teil beim Scrollen der Seite sichtbar wird; und Verschieben von Elementen der entsprechenden Position in den sichtbaren Bereich, wenn Sie durch die Seite scrollen.

Warum also friert die Animation ein?

Der Grund dafür ist, dass die Planung des Hauptthreads und des Synthesethreads nicht sinnvoll ist.

Lassen Sie uns die Gründe für eine unangemessene Terminplanung im Detail besprechen:

Wenn Höhe, Breite, Rand und Polsterung als Übergangswerte verwendet werden, hat der Hauptthread des Browsers eine hohe Arbeitslast. Wenn beispielsweise von Rand links: -20px bis Rand links: 0 gerendert wird, muss der Hauptthread die Stile von Rand links: -19px, Rand links: -18px bis hin zu Rand links: 0 berechnen. Darüber hinaus muss der Syntheseprozess jedes Mal, wenn der Hauptthread den Stil berechnet, ihn auf die GPU zeichnen und dann auf dem Bildschirm rendern. Insgesamt werden 20 Hauptthread-Renderings und 20 Synthesethread-Renderings durchgeführt, 20+20 Mal, also insgesamt 40 Berechnungen.

Der Rendering-Prozess des Hauptthreads kann sich auf den Prozess des Browser-Renderings von Webseiten beziehen:

  • Erstellen eines Document Object Model (DOM) mit HTML
  • Erstellen des CSS-Objektmodells (CSSOM) mit CSS
  • Ausführen von Skripten basierend auf DOM und CSSOM
  • DOM und CSSOM zu einem Renderbaum zusammenführen
  • Verwenden Sie den Renderbaum, um alle Elemente anzuordnen
  • Alle Elemente bemalen

Das heißt, der Hauptthread muss jedes Mal die Berechnungen der vier Phasen „Skripte“, „Renderbaum“, „Layout“ und „Malen“ ausführen.

Und wenn „transform“ verwendet wird, z. B. „transform:translate(-20px,0)“ zu „transform:translate(0,0), muss der Haupt-Thread nur einmal „transform:translate(-20px,0)“ zu „transform:translate(0,0)“ ausführen und dann konvertiert der Synthese-Thread –20px einmal in 0px, sodass die Gesamtberechnung 1+20 beträgt.

Manche Leute sagen vielleicht, dass dies nur eine 19-fache Verbesserung sei. Welche wirkliche Leistungsverbesserung ist das denn?

Gehen Sie von jeweils 10 ms aus.

Dies reduziert den Zeitaufwand um ca. 190ms.

Manche Leute sagen vielleicht, das ist Mist, nur 190 ms, das spielt keine Rolle.

Was also, wenn margin-left von -200px bis 0 ist, 10ms auf einmal, 10ms

199 ≈ 2 s.

Manche Leute werden sagen, das ist Müll, es sind nur 2 Sekunden, das spielt keine Rolle.

Haben Sie Single-Threading vergessen?

2 s = 6 s, was eine Leistungsverbesserung von 6 s bedeutet.

Da es sich bei den Daten um Vermutungen handelt, wird ihre Echtheit vorerst nicht berücksichtigt.

Um die Überzeugungskraft dieses Artikels zu erhöhen, werde ich meine These anhand eines Beispiels untermauern. Schauen wir es uns gemeinsam an.

Im Frontend wird Animation verwendet, um den Animationsübergang der Startseite auf der H5-Seite zu implementieren. Dies ist ein sehr einfacher Effekt. Ein Avatar für den Kundendienst wird auf die Startseite geladen, zuerst vergrößert, bleibt 700 ms lang und wird dann nach oben verkleinert. Der Code lautet wie folgt:

<!DOCTYPE html>
<html>
<head lang="de">
  <meta charset="utf-8">
  <meta name="viewport" content="width=Gerätebreite,Anfangsmaßstab=1.0,Maximaler Maßstab=1.0,Benutzerskalierbar=1" >
  <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
  <title>Animation zum Laden der Homepage</title>
  <Kopf>
    <Stil>
      .willkommen-main{
        Anzeige: keine;        
        Polsterung unten: 40px;      
      }
      .top-info{        
        Breite: 100 %;        
        Position: absolut;        
        links: 0;        
        oben: 93px;      
      }
      .wec-img{
        Breite: 175px;        
        Höhe: 175px;        
        Position: relativ;        
        Polsterung: 23px;        
        Box-Größe: Rahmenbox;        
        Rand: 0 automatisch;      
       }
      .wec-img:vor{        
        Inhalt: '';        
        Position: absolut;        
        links: 0;        
        oben: 0;        
        Breite: 100 %;        
        Höhe: 100%;        
        Hintergrund: URL("./images/kf-welcome-loading.jpg");        
        Hintergrundgröße: 100 %;      
       }
      .wec-img .img-con{
        Breite: 100 %;        
        Höhe: 100%;        
        Randradius: 50 %;        
        /*Boxgröße: Rahmenbox;*/
        Hintergrund: url("./images/kf_1.jpg");        
        Hintergrundgröße: 100 %;        
        Polsterung: 1px;      
      }
      .wec-img .img-con img{
        Breite: 100 %;        
        Höhe: 100%;        
        Randradius: 50 %;      
      }
      .geladen .wec-img{
        -webkit-transform-origin: oben in der Mitte;      
      }        
      .wird geladen.willkommen-main{
        Anzeige: Block;
      }
      .wird geladen.wec-img{
        -webkit-animation:fadeIn .3s erleichtert beides;
      }
      .wird geladen.wec-img:vorher{
        -webkit-animation:drehen .6s .2s linear beides;      
      }
      .geladen .top-info{
        -webkit-animation:mainpadding 1s 0s erleichtert beides;      
      }
      .geladen .wec-img{
        -webkit-animation:imgSmall 1s 0s erleichtert beides; }
      @-webkit-keyframes mainpadding{
        0%{-webkit-transform:translateY(0)  
      }
        100 % {-webkit-transform:translateY(-87px)   
        }
      }      
      @-webkit-keyframes imgSmall{
        0 %{
          Breite: 175px;          
          Höhe: 175px;          
          Polsterung: 23px;        
        }
        100 %{          
          Breite: 60px;          
          Höhe: 60px;          
          Polsterung: 0;        
        }
      }      
      @-webkit-keyframes fadeIn{
        0 % {Deckkraft: 0; -webkit-transform:scale(.3)}
        100 % {Deckkraft: 1; -webkit-transform:scale(1)}
      }      
      @-webkit-keyframes drehen{
        0 % {Deckkraft: 0;-webkit-transform:rotate(0 Grad);}
        50 % {Deckkraft: 1; -webkit-transform:rotate(180deg);}
        100 % {Deckkraft: 0;-webkit-transform:rotate(360 Grad);}
      }     
      </Stil>
    <Text>
      <div Klasse="Willkommen-Haupt">
        <div Klasse="Top-Info">
          <div class="wec-img"><p class="img-con"><img src="" alt=""></p></div>
        </div>
      </div>
      <Skript>
        $('.welcome-main').addClass('wird geladen');
        setzeTimeout(Funktion(){
          $('.hi.fst').removeClass('wird geladen');
          $('.welcome-main').addClass('geladen');
        },700);
      </Skript>
    </body>
  </html>

Der Test verlief auf Chrome in Ordnung, aber bei der Übermittlung des Tests an die Qualitätssicherung wurde festgestellt, dass es bei einigen Modellen, etwa bei Huawei (System 4.2) und OPPO (System 5.1), zu Verzögerungen kam.

Ich war verwirrt, also verwies ich auf den Artikel „Detailliertes Verständnis der Browser-Leistungsprobleme von CSS-Animationen und -Übergängen“ und änderte das Animationselement in der Bildskalierung wie folgt in eine Transformation

@-webkit-keyframes imgSmall{
 0 %{
   -webkit-transform:Skala(1);
 }
 100 %{
   -webkit-transform:Skala(.465);
 }
}

Tatsächlich war das Verzögerungsproblem gelöst.

Der Artikel „Detailliertes Verständnis der Browser-Leistungsprobleme von CSS-Animationen und -Übergängen“ erklärt, dass moderne Browser normalerweise über zwei wichtige Ausführungsthreads verfügen, die zusammenarbeiten, um eine Webseite zu rendern: den Hauptthread und den Synthesethread.

Im Allgemeinen ist der Hauptthread für Folgendes verantwortlich: Ausführen von JavaScript, Berechnen der CSS-Stile von HTML-Elementen, Layout der Seite, Zeichnen von Elementen in eine oder mehrere Bitmaps und Übergeben dieser Bitmaps an den Synthesethread.

Dementsprechend ist der Kompositionsthread für Folgendes verantwortlich: Zeichnen der Bitmap auf dem Bildschirm über die GPU; Benachrichtigen des Hauptthreads, dass die Bitmap des sichtbaren oder bald sichtbaren Teils der Seite aktualisiert werden soll; Berechnen, welcher Teil der Seite sichtbar ist; Berechnen, welcher Teil beim Scrollen der Seite sichtbar wird; und Verschieben von Elementen der entsprechenden Position in den sichtbaren Bereich, wenn Sie durch die Seite scrollen.

Angenommen, wir möchten die Höhe eines Elements von 100 Pixel auf 200 Pixel ändern, und zwar wie folgt:

div {
  Höhe: 100px;
  Übergang: Höhe 1s linear;
}
  
div:hover {
  Höhe: 200px;
}

Der Hauptthread und der Synthesethread führen entsprechende Vorgänge gemäß dem folgenden Flussdiagramm aus. Beachten Sie, dass Vorgänge im orangefarbenen Feld zeitaufwändig sein können, während Vorgänge im blauen Feld schneller sind.

Und verwenden Sie transform:scale, um Folgendes zu erreichen

div {
  transformieren: Skalierung (0,5);
  Übergang: 1 s lineare Transformation;
}
  
div:hover {
  transformieren: Skalierung (1,0);
}

Der Ablauf ist wie folgt:

Das heißt, mithilfe der Transformation muss der Browser die Bitmap des Elements nur einmal generieren und sie beim Start der Animation zur Verarbeitung an die GPU übermitteln. Danach muss der Browser keine Layout-, Zeichen- oder Bitmap-Übermittlungsvorgänge mehr durchführen. Somit kann der Browser die GPU voll ausnutzen, um das Bitmap schnell an verschiedenen Positionen zu zeichnen und Drehungen oder Skalierungen durchzuführen.

Um diese Theorie anhand einer Größenordnung zu bestätigen, öffnete ich die Timeline von Chrome, um die Seite FPS anzuzeigen

Unter anderem beträgt die FPS beim Umschaltvorgang nur 44, wenn Höhe als Animationselement verwendet wird. Wir wissen, dass 60 Bilder pro Sekunde die für das menschliche Auge am besten geeignete Interaktion sind. Wenn sie unter 60 liegen, kann das menschliche Auge dies deutlich spüren, weshalb es zu einem Einfrieren kommt.

Der Zeitaufwand für das Rendern und Malen beträgt:

Schauen wir uns die Verwendung von transform:scale an

Die FPS erreichten 66 und die Render- und Malzeit wurde um das Dreifache reduziert.

Bisher war das Problem gelöst. Ein paar Tage später sah ich einen Artikel darüber, wie man das „Stottern“ von Chrome-Animationen lösen kann. Ich fand heraus, dass ich die Animationen auch optimieren konnte, indem ich die Hardwarebeschleunigung einschaltete, also versuchte ich es erneut.

webkit-transform: übersetzen3d(0,0,0);
-moz-transform: übersetzen3d(0,0,0);
-ms-transform: übersetzen3d(0,0,0);
-o-transform: übersetzen3d(0,0,0);
transformieren: übersetzen3d(0,0,0);

Etwas Erstaunliches ist passiert, die FPS erreichten 72:

Zusammenfassung der Lösungen für CSS3-Animationsstaus

Versuchen Sie, die Transformation als Animation zu verwenden und vermeiden Sie die Verwendung von Höhe, Breite, Rand, Polsterung usw.

Bei höheren Anforderungen können Sie die GPU-Hardwarebeschleunigung im Browser aktivieren.

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird.

<<:  Implementierung eines MySQL-Gemeinschaftsindex (zusammengesetzter Index)

>>:  Vorgänge der Kommunikation zwischen Docker-Containern und der externen Netzwerkkommunikation

Artikel empfehlen

Semantik, Schreiben und bewährte Methoden für Link A

Die Semantik, der Schreibstil und die Best Practi...

Verschiedene korrekte Haltungen zur Verwendung von Umgebungsvariablen in Webpack

Inhaltsverzeichnis Schreiben Sie vor Geschäftscod...

JavaScript implementiert die H5-Goldmünzenfunktion (Beispielcode)

Heute habe ich eine Aktivität für einen roten Ums...

Entdecken Sie die Wahrheit hinter dem Neuladevorgang in Nginx

Der heutige Artikel stellt hauptsächlich den Neul...

Vue-Konfigurationsdetails für mehrere Seiten

Inhaltsverzeichnis 1. Der Unterschied zwischen me...

Detaillierte Erklärung der JavaScript-Array-Deduplizierung

Inhaltsverzeichnis 1. Array-Deduplizierung 2. Ded...

Anbieterpräfix: Warum brauchen wir ein Browser-Engine-Präfix?

Was ist das Lieferantenpräfix? Anbieterpräfix – B...

Ausführliche Erläuterung der MySQL-Isolationsebene und des Sperrmechanismus

Inhaltsverzeichnis Kurzbeschreibung: 1. Vier Merk...

Tomcat Server Erste Schritte Super ausführliches Tutorial

Inhaltsverzeichnis 1. Einige Konzepte von Tomcat ...

Lösung für das Jitter-Problem beim CSS3-Transformationsübergang

transform: scale(); Skalierung verursacht Jitter ...

Codebeispiele für die Sicherung mehrerer MySQL-Datenbanken

In diesem Artikel werden hauptsächlich Codebeispi...