Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Einführung in die Verwendung von CSS3 3D-Planetenrotation und Browser-Rendering-Prinzipien

Detaillierte Einführung in die Verwendung von CSS3 3D-Planetenrotation und Browser-Rendering-Prinzipien

高洛峰
高洛峰Original
2017-03-19 16:44:191704Durchsuche

Ich habe mich kürzlich mit Web-Animation beschäftigt, also werde ich meinen Lernprozess aufzeichnen und ihn mit allen teilen.

CSS3 3D-Planetenrotations-Demoseite, bitte klicken Sie auf: Demo. (Es wird empfohlen, Chrome zum Öffnen zu verwenden)

Der vollständige Code dieses Artikels sowie weitere CSS3-Effekte sind auf meinem Github zu sehen, und ich hoffe, Sie können ihm einen Stern geben.

Nun, einige Leute können die Demo möglicherweise nicht öffnen oder die Seite ist durcheinander. Hier sind einige Darstellungen: (Die Bilder sind etwas groß, bitte warten Sie geduldig)

CSS3 3D-Planetenbewegungseffekt Bild

CSS3 3D 行星运转动画,太阳系动画

Habe zufällig einen weiteren Screenshot gemacht:

CSS3 3D 行星运转动画,太阳系动画

Dringend empfehlen, dass Sie klicken auf der Demo-Seite, um es zu erleben. Der Charme von CSS3 3D, was Bilder zeigen können, ist schließlich begrenzt.

Dann wird der Produktionsprozess dieser CSS3-3D-Planetenbewegungsanimation nicht im Detail beschrieben. Der Schwerpunkt dieses Artikels liegt auf der Einführung von Webanimationen und der Leistungsoptimierung. Ausführliche Informationen zu CSS3 3D finden Sie im vorherigen Blog: [CSS3 Advanced] Coole 3D-Rotationsperspektive. Einfache Idee:

1. Verwenden Sie die im vorherigen Artikel erstellte 3D-Fotowand und modifizieren Sie sie

2. Viele Methoden wurden für die Herstellung jeder Kugel entwickelt und schließlich verwendet Bei diesem Kompromiss ist jede Kugel selbst eine CSS3-3D-Form. Dann kann die Verwendung von Sass zum Schreiben von CSS während des Produktionsprozesses einen Großteil des mühsamen Prozesses zum Schreiben von CSS-Animationen reduzieren.

3 In der Demo wurde Javascript zum Schreiben einer Mausverfolgung verwendet Listening-Ereignis, entfernen Sie dieses Ereignis und die gesamte Planetenbewegungsanimation selbst werden in reinem CSS implementiert.

Das Folgende wird im Mittelpunkt dieses Artikels stehen. Aus der Perspektive der Leistungsoptimierung werden wir über die Prinzipien des Browser-Renderings und der Browser-Neuanordnung, der Optimierung der Animationsleistungserkennung usw. sprechen:

Browser Das Prinzip des Renderns und Anzeigens und seine Auswirkungen auf Webanimationen

Der Untertitel ist etwas groß. Wir wissen, dass die Kerne (Rendering-Engines) verschiedener Browser unterschiedlich sind, beispielsweise bei den gängigsten Der Chrome-Browser ist jetzt der Blink-Kernel (verwendet in Chrome (Version 28 und höher), Opera (Version 15 und höher) und Yandex-Browser), Firefox ist Gecko und IE ist Trident. Der Browser-Kernel ist für die Interpretation von Webseiten verantwortlich Syntax und deren Interpretation Beim Rendern (Anzeigen) von Webseiten sind die Arbeitsprinzipien verschiedener Browserkerne nicht vollständig konsistent.

Was wir im Folgenden also hauptsächlich besprechen werden, ist das Rendering-Prinzip unter dem Chrome-Browser. Da es viele überprüfbare Informationen zum Chrome-Kernel-Rendering gibt, wagen wir keine Schlussfolgerungen über Browser mit anderen Kerneln. Daher bezieht sich die folgende Diskussion standardmäßig auf den Chrome-Browser.

Zuerst möchte ich einige Schlussfolgerungen ziehen:

Verwenden Sie transfürm3d api anstelle von transform api, um den Start von zu erzwingen GPU-Beschleunigung

Hier sprechen wir über GPU-Beschleunigung. Warum kann die GPU die 3D-Transformation beschleunigen? All dies muss mit dem zugrunde liegenden Rendering des Browsers beginnen. Der Prozess des Renderns und Anzeigens von Webseiten im Browser ist ein Muss in Interviews. Er kann grob unterteilt werden in:

1 HTML (HTML-Parser)

2. DOM-Baum erstellen

3. Render-Baum erstellen (Malerei)

Einen sehr gefunden klassisches Bild:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍 Dieser Rendering-Prozess ist Grundwissen, also gehen Sie weiter tiefer.

Wenn die Seite geladen und analysiert wird, stellt sie eine sehr vertraute Struktur im Browser dar: DOM (

Dokument

Objekt Modell, Dokumentobjekt Modell). Wenn der Browser eine Seite rendert, verwendet er viele Zwischendarstellungen, die den Entwicklern nicht zugänglich sind. Die wichtigste Struktur ist die Ebene. Diese Ebene steht im Mittelpunkt dieses Artikels:

In Chrome gibt es verschiedene Arten von Ebenen: RenderLayer (verantwortlich für den DOM-Unterbaum), GraphicsLayer (verantwortlich für den Unterbaum von RenderLayer). Als nächstes besprechen wir die GraphicsLayer-Ebene.

GraphicsLayer-Ebene wird als Textur auf die GPU hochgeladen.

Die Textur ist hier sehr wichtig.

Was ist Textur?

Textur bezieht sich hier auf einen GPU-Begriff: Stellen Sie sich das als ein Bitmap-Bild vor, das vom Hauptspeicher (z. B. RAM) in den Bildspeicher (z. B. VRAM in der GPU) verschoben wird. Sobald es auf die GPU verschoben wurde, können Sie es einer Netzgeometrie zuordnen und Texturen in Chrome verwenden, um große Teile des Seiteninhalts von der GPU zu entfernen. Es ist einfach, verschiedene Positionen (Position) und Transformationen anzupassen, indem Texturen auf ein sehr einfaches rechteckiges Raster angewendet werden, so funktioniert 3D-CSS.

Es ist schwer zu verstehen, wenn wir uns das oben erwähnte Beispiel von GraphicsLayer ansehen. In den Entwicklertools treffen wir die folgende Auswahl, um die Option „Ebenenränder anzeigen“ aufzurufen:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

Auf einer sehr einfachen Seite können wir das wie unten gezeigt sehen, diese Seite nur eine Schicht. Das blaue Raster stellt Kacheln als Einheiten einer Ebene dar (nicht als Ebenen). Chrome kann sie als Teil einer großen Ebene auf die GPU hochladen:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

Erstellung der Ebene des Elements selbst

Da die obige Seite sehr einfach ist, wird keine Ebene erstellt, aber in einer sehr komplexen Seite können wir beispielsweise eine 3D-CSS-Eigenschaft für das Element festlegen, um es zu transformieren können wir sehen, wie es aussieht, wenn ein Element eine eigene Ebene hat.

Achten Sie auf den orangefarbenen Rahmen, der die Ebenen in dieser Ansicht umreißt:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

Wann wird die Erstellung einer Ebene ausgelöst?

Die im Diagramm oben vom gelben Rand umschlossene Ebene ist GraphicsLayer, was für unsere Webanimation sehr wichtig ist. Normalerweise zeichnet Chrome den Inhalt einer Ebene, bevor er ihn als Textur (Farbe) auf die GPU hochlädt ) in eine Bitmap. Wenn sich der Inhalt nicht ändert, muss die Ebene nicht neu gezeichnet werden.

Die Bedeutung davon besteht darin, dass die für das Neuzeichnen aufgewendete Zeit für andere Dinge genutzt werden kann, beispielsweise für die Ausführung von JavaScript. Wenn das Zeichnen lange dauert, führt dies auch zu Animationsfehlern und Verzögerungen.

Wann löst ein Element die Erstellung einer Ebene aus? Derzeit werden Ebenen erstellt, wenn eine der folgenden Bedingungen erfüllt ist:

  • 3D- oder Perspektivtransformation (Perspektive, Transformation) CSS-Eigenschaften

  • Verwenden Sie das 39000f942b2545a5315c57fa3276f220-Element

  • mit beschleunigter Videodekodierung oder einen beschleunigten 2D-Kontext mit dem 3856173a0eceb679792f65a38e1fcb00

  • Hybrid-Plug-ins (z. B. Flash)

  • Erstellen Sie CSS-Animationen mit Ihrer eigenen Deckkraft oder verwenden Sie ein animiertes Transformationselement

  • Elemente mit beschleunigtem CSS Filter

  • Elemente haben einen untergeordneten Knoten, der eine zusammengesetzte Ebene enthält (mit anderen Worten, ein Element hat eine untergeordnetes Element, das sich in einer eigenen Ebene befindet)

  • Das Element hat einen Z-Index niedriger und enthält ein Geschwisterelement in der zusammengesetzten Ebene (mit anderen Worten). , das Element befindet sich im zusammengesetzten Rendering auf der Ebene)

Neuzeichnen der Ebene

Bei statischen Webseiten wird die Ebene nach dem Zeichnen nicht geändert Beim ersten Mal, aber bei der Webanimation ändern sich die DOM-Elemente der Seite ständig. Wenn sich der Inhalt der Ebene während des Transformationsprozesses ändert, wird die Ebene neu gezeichnet.

Die leistungsstarken Chrome-Entwicklertools bieten Tools, mit denen wir sehen können, welche Inhalte neu gezeichnet wurden, wenn die animierte Seite ausgeführt wird:

In der alten Version In Chrome gibt es eine Option zum Anzeigen von Farbrechtecken. Sie können sehen, welche Ebenen der Seite neu gezeichnet und mit einem roten Rand markiert wurden.

Aber die neue Version von Chrome scheint diese Option entfernt zu haben. Die aktuelle Option ist Paint Flashing aktivieren, die auch zur Identifizierung der dynamischen Änderungen der Website verwendet wird und mit einem grünen Rand gekennzeichnet ist.

Wenn Sie sich das Diagramm oben ansehen, können Sie sehen, dass es auf der Seite mehrere grüne Kästchen gibt, die darauf hinweisen, dass eine Neuzeichnung stattgefunden hat. Beachten Sie, dass Chrome nicht immer die gesamte Ebene neu zeichnet, sondern versucht, die ungültigen Teile des DOM intelligent neu zu zeichnen.

Logischerweise sollte bei so vielen Animationen auf der Seite sehr häufig neu gezeichnet werden. In meiner Planetenanimation im Bild oben sehe ich jedoch nur ein paar grüne Kästchen zum Neuzeichnen Die Optimierung besteht darin, dass die Seite zwangsläufig neu gezeichnet werden muss, wenn die gesamte Animationsseite nur eine Ebene hat Die erstellte Ebene wird separat erstellt, z. B. Drehen. Zu diesem Zeitpunkt wirkt sich die Rotationstransformation der Ebene nicht auf andere Ebenen aus, sodass die Ebene nicht unbedingt neu gezeichnet werden muss. (Persönliche Meinungen, bitte korrigieren).

Das Verständnis des Neuzeichnens von Ebenen ist entscheidend für die Optimierung der Leistung von Webanimationen.

Was verursacht eine Ungültigmachung und eine erzwungene Neuzeichnung? Diese Frage lässt sich nur schwer erschöpfend beantworten, da es eine Vielzahl von Situationen gibt, die zu einem Grenzversagen führen. Die häufigste Situation besteht darin, das DOM zu ändern oder durch Manipulation von CSS-Stilen einen Reflow zu verursachen.

Der beste Weg, die Grundursache für Repaints und Reflows zu finden, besteht darin, die Zeitleiste der Entwicklertools zu verwenden und das Paint-Flashing-Tool zu aktivieren und dann zu versuchen, die Stelle zu finden, an der das DOM kurz vor dem Repaint/ geändert wurde. Reflow.

Zusammenfassung

Wie zeigt der Browser also die DOM-Elemente bis zur endgültigen Animation an?

  • Der Browser analysiert den HTML-Code, ruft das DOM ab und teilt es in mehrere Ebenen (GraphicsLayer) auf.

  • Berechnen Sie die Stilergebnisse für die Knoten von jede Ebene (Stil neu berechnen – Stil-Neuberechnung)

  • Grafiken und Positionen für jeden Knoten generieren (Layout – Reflow und Relayout)

  • Jeden Knoten konvertieren Knoten werden gezeichnet und in die Ebenen-Bitmap gefüllt (Paint Setup und Paint–Redraw)

  • Die Ebene wird als Textur (Textur) auf die GPU hochgeladen

  • Anpassen mehrerer Ebenen an die Seite, um das endgültige Bildschirmbild zu generieren (zusammengesetzte Ebenen – Ebenenreorganisation)

Ein großer Teil der Kosten für Webanimationen liegt im Neuzeichnen von Ebenen , mit Ebenen als Das zugrunde liegende Verbundmodell hat einen tiefgreifenden Einfluss auf die Rendering-Leistung. Wenn kein Zeichnen erforderlich ist, ist der Overhead durch zusammengesetzte Vorgänge vernachlässigbar. Wenn Sie also versuchen, Probleme mit der Renderleistung zu beheben, besteht das erste Ziel darin, das Neuzeichnen von Ebenen zu vermeiden. Dies bietet dann eine Richtung für die Optimierung der Animationsleistung und reduziert das Neuzeichnen und Umfließen von Elementen.

Reflow und Repaint

Hier müssen wir zunächst zwischen zwei Konzepten unterscheiden, Reflow und Reflow.

Reflow

Wenn ein Teil (oder der gesamte) des Renderbaums aufgrund von Änderungen in der Größe, im Layout, beim Ausblenden usw. der Elemente neu erstellt werden muss. Dies nennt man Reflow, also Relayout.

Jede Seite muss mindestens einmal umgebrochen werden, und zwar beim ersten Laden der Seite. Während des Reflows macht der Browser den betroffenen Teil des Rendering-Baums ungültig und rekonstruiert diesen Teil des Rendering-Baums. Nach Abschluss des Reflows zeichnet der Browser den betroffenen Teil auf dem Bildschirm neu.

Neu streichen

Wenn einige Elemente im Renderbaum ihre Attribute aktualisieren müssen und diese Attribute nur das Aussehen und den Stil der Elemente beeinflussen, aber keinen Einfluss auf das Layout haben, wie z. B. Hintergrundfarbe . Man nennt es Neuzeichnen.

Es ist erwähnenswert, dass Reflow definitiv ein Neuzeichnen verursacht, ein Neuzeichnen jedoch nicht unbedingt ein Reflow verursacht.

Offensichtlich ist Reflow teurer. Einfach ausgedrückt tritt Reflow auf, wenn der Betrieb eines Elements dazu führt, dass das Element seine Größe oder Position ändert.

Wenn Reflow ausgelöst wird:

  • Größe des Fensters ändern

  • Ändern der Schriftart)

  • Hinzufügen oder Entfernen eines Stylesheets (Hinzufügen oder Entfernen eines Stylesheets)

  • Inhaltsänderungen, z. B. wenn der Benutzer Inhaltsänderungen eingibt, z. B. ein Benutzer Eingeben von Text in

  • ein Eingabefeld)

  • Aktivieren Sie die CSS--Pseudoklasse , z. B. :hover (Aktivierung von CSS-Pseudo-Klassenen wie :hover (im IE die Aktivierung der Pseudoklasse) Klasse eines Geschwisters))

  • Manipulation der Klassenattribut

  • Ein Skript, das die DOM-Eigenschaften manipuliert

  • OffsetBreite und OffsetHöhe berechnen (Berechnen von offsetWidth und offsetHeight)

  • Stil festlegen Der Wert des Attributs (Festlegen einer Eigenschaft des Stilattributs)

Also für die Seite Unser Ziel ist es, das Umfließen und Neuzeichnen der Seite zu minimieren. Eine einfache Kastanie:

// 下面这种方式将会导致回流reflow两次
var newWidth = ap.offsetWidth + 10; // Read
ap.style.width = newWidth + 'px'; // Write
var newHeight = ap.offsetHeight + 10; // Read
ap.style.height = newHeight + 'px'; // Write

// 下面这种方式更好,只会回流reflow一次
var newWidth = ap.offsetWidth + 10; // Read
var newHeight = ap.offsetHeight + 10; // Read
ap.style.width = newWidth + 'px'; // Write
ap.style.height = newHeight + 'px'; // Write


Da die obigen vier Sätze die OffsetHeight-Operation beinhalten, zwingen sie den Browser, zweimal umzufließen, während die folgenden vier Sätze die Offset-Operation kombinieren, sodass ein Seitenumbruch reduziert wird.

Reflow und Neuzeichnen zu reduzieren bedeutet tatsächlich, die Vorgänge im Rendering-Baum zu reduzieren (mehrere DOM- und Stiländerungen zusammenzuführen), die Anforderungen für einige Stilinformationen zu reduzieren und die Optimierungsstrategie des Browsers voll auszunutzen.

FlushWarteschlange

Tatsächlich verfügt der Browser selbst über eine Optimierungsstrategie. Wenn jeder Satz von Javascript im DOM ausgeführt wird, wird dies der Fall sein Wenn dies der Fall ist, ist der Browser möglicherweise nicht in der Lage, damit umzugehen. Daher optimieren viele Browser diese Vorgänge. Wenn die Vorgänge in der Warteschlange eine bestimmte Anzahl oder ein bestimmtes Zeitintervall erreichen, wird der Browser in die Warteschlange gestellt gespült und eine Charge verarbeitet. Dadurch werden mehrere Reflows und Neuzeichnungen zu einem Reflow und Neuzeichnungsvorgang.

Aber es gibt Ausnahmen, denn manchmal müssen wir bestimmte Stilinformationen wie folgt genau erhalten:


  • Offset Top, offsetLeft, offsetWidth, offsetHeight



  • scrollTop/Left / Breite/Höhe



  • ClientOben/Links/Breite/Höhe



  • Breite, Höhe



  • hat getComputedStyle() oder den aktuellenStil des IE


Um die genauesten Informationen zurückzugeben, muss der Browser zu diesem Zeitpunkt sofort einen Reflow durchführen und neu zeichnen, um sicherzustellen, dass die uns übermittelten Informationen korrekt sind, sodass die Flush-Warteschlange möglicherweise im Voraus ausgeführt wird.

display:none und visibility:hidden

können beide Knoten auf der Seite ausblenden. Der Unterschied besteht darin, dass

  • display:none ausgeblendete Elemente keinen Platz belegen. Seine Breite, Höhe und andere Attributwerte gehen „verloren“

  • visibility:hidden Der verborgene Elementbereich ist weiterhin vorhanden. Es verfügt weiterhin über Attributwerte wie Höhe und Breite

Aus Sicht der Leistung, also in Bezug auf Reflow und Neuzeichnen,

  • display :none löst Reflow aus

  • visibility:hidden löst nur Repaint aus, da keine Positionsänderungen gefunden werden

sie Bei der Optimierung Sichtbarkeit: Ausgeblendet wird besser angezeigt, da wir dadurch die bereits definierte Anzeigehierarchie im Dokument nicht ändern.

Auswirkung auf untergeordnete Elemente:

  • display:none Sobald display:none auf das übergeordnete Knotenelement angewendet wird, sind der übergeordnete Knoten und seine untergeordneten Knotenelemente alle unsichtbar. und unabhängig davon können seine Nachkommen nicht angezeigt werden, egal wie der Anzeigewert eingestellt ist;

  • visibility:hidden Sobald Visibility:hidden auf das übergeordnete Knotenelement angewendet wird, werden dies auch alle seine Nachkommen tun unsichtbar sein. Allerdings gibt es versteckte „Misserfolge“. Wenn „visible:visible“ auf das untergeordnete Element angewendet wird, wird das untergeordnete Element erneut angezeigt.

Erkennung und Optimierung der Animationsleistung

Leistungsverbrauchende Stile

Verschiedene Stile haben einen unterschiedlichen Leistungsverbrauch, zum Beispiel Box- Shadow ist aus Rendering-Sicht sehr leistungsintensiv, da die Ausführung ihres Zeichencodes im Vergleich zu anderen Stilen zu lange dauert. Das bedeutet, dass es zu Leistungsproblemen kommt, wenn ein leistungsintensiver Stil häufig neu gezeichnet werden muss. Zweitens müssen Sie wissen, dass nichts konstant ist. Ein Stil, der heute schlecht funktioniert, kann morgen optimiert werden, und es gibt Unterschiede zwischen den Browsern.

Der Schlüssel liegt also darin, Ihre Entwicklungstools zu nutzen, um Leistungsengpässe zu identifizieren und dann Möglichkeiten zu finden, die Arbeitslast des Browsers zu reduzieren.

Glücklicherweise bietet der Chrome-Browser viele leistungsstarke Funktionen, die es uns ermöglichen, unsere Animationsleistung zu erkennen. Zusätzlich zu den oben genannten können wir auch die FPS-Informationen der Seite anzeigen, indem wir die FPS-Anzeige unten überprüfen GPU-Nutzung:

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

Verwenden Sie Will-Change, um die Rendering-Leistung wie Seitenscrollen, Animationen usw. zu verbessern.

In der offiziellen Dokumentation heißt es , dies ist noch eine experimentelle Funktion, daher können sich die Syntax und das Verhalten dieser Funktion in zukünftigen Versionen des Browsers ändern.

使用CSS3 3D行星运转以及浏览器渲染原理详细介绍

使用方法示例:(具体每个取值的意义,去翻翻文档)

will-change: auto
will-change: scroll-position
will-change: contents
will-change: transform        // Example of <custom-ident>
will-change: opacity          // Example of <custom-ident>
will-change: left, top        // Example of two <animateable-feature>

will-change: unset
will-change: initial
will-change: inherit

// 示例
.example{
    will-change: transform;
}

will-change 为 web 开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。 这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。

值得注意的是,用好这个属性并不是很容易:


  • 不要将 will-change 应用到太多元素上:浏览器已经尽力尝试去优化一切可以优化的东西了。有一些更强力的优化,如果与 will-change 结合在一起的话,有可能会消耗很多机器资源,如果过度使用的话,可能导致页面响应缓慢或者消耗非常多的资源。



  • 有节制地使用:通常,当元素恢复到初始状态时,浏览器会丢弃掉之前做的优化工作。但是如果直接在样式表中显式声明了 will-change 属性,则表示目标元素可能会经常变化,浏览器会将优化工作保存得比之前更久。所以最佳实践是当元素变化之前和之后通过脚本来切换 will-change 的值。



  • 不要过早应用 will-change 优化:如果你的页面在性能方面没什么问题,则不要添加 will-change 属性来榨取一丁点的速度。 will-change 的设计初衷是作为最后的优化手段,用来尝试解决现有的性能问题。它不应该被用来预防性能问题。过度使用 will-change 会导致大量的内存占用,并会导致更复杂的渲染过程,因为浏览器会试图准备可能存在的变化过程。这会导致更严重的性能问题。



  • 给它足够的工作时间:这个属性是用来让页面开发者告知浏览器哪些属性可能会变化的。然后浏览器可以选择在变化发生前提前去做一些优化工作。所以给浏览器一点时间去真正做这些优化工作是非常重要的。使用时需要尝试去找到一些方法提前一定时间获知元素可能发生的变化,然后为它加上 will-change 属性。


使用 transform3d api 代替 transform api,强制开始 GPU 加速

GPU 能够加速 Web 动画,这个上文已经反复提到了。

3D transform 会启用GPU加速,例如 translate3D, scaleZ 之类,当然我们的页面可能并没有 3D 变换,但是不代表我们不能启用 GPU 加速,在非 3D 变换的页面也使用 3D transform 来操作,算是一种 hack 加速法。我们实际上不需要z轴的变化,但是还是假模假样地声明了,去欺骗浏览器。

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in die Verwendung von CSS3 3D-Planetenrotation und Browser-Rendering-Prinzipien. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn