Ich versuche, das canvas
Element auf dieser Seite mithilfe des folgenden Snippets in ein png zu konvertieren ( zB in die JavaScript-Konsole eingeben):
Leider ist das PNG, das ich bekomme, völlig leer. Beachten Sie auch, dass der ursprüngliche Zeichenbereich nach der Größenänderung der Seite leer bleibt.
Warum wird canvas
leer? Wie kann ich dieses canvas
in ein png umwandeln?
Kevin Reids preserveDrawingBuffer
Vorschlag ist der richtige, aber es gibt (normalerweise) eine bessere Option. Der tl; dr ist der Code am Ende.
Es kann teuer sein, die endgültigen Pixel einer gerenderten Webseite zusammenzustellen und dies mit dem Rendering von WebGL-Inhalten noch besser zu koordinieren. Der übliche Ablauf ist:
Beachten Sie, dass sich dies von den meisten OpenGL-Anwendungen unterscheidet. In diesen werden gerenderte Inhalte in der Regel direkt angezeigt, anstatt mit einer Menge anderer Elemente auf einer Seite zusammengesetzt zu werden, von denen einige tatsächlich über dem WebGL-Inhalt liegen und mit diesem vermischt sind.
Die WebGL-Spezifikation wurde geändert, um den Zeichenpuffer nach Schritt 3 als im Wesentlichen leer zu behandeln. Der Code, den Sie in devtools ausführen, kommt nach Schritt 4, weshalb Sie einen leeren Puffer erhalten. Diese Änderung an der Spezifikation ermöglichte große Leistungsverbesserungen auf Plattformen, bei denen das Ausblenden nach Schritt 3 im Grunde das ist, was tatsächlich in der Hardware geschieht (wie in vielen mobilen GPUs). Wenn Sie möchten, dass nach dem dritten Schritt manchmal Kopien des WebGL-Inhalts erstellt werden, müsste der Browser immer vor Schritt 3 eine Kopie des Zeichenpuffers erstellen, wodurch die Bildfrequenz sinken würde steil auf einigen Plattformen.
Sie können genau das tun und den Browser zwingen, die Kopie zu erstellen und den Bildinhalt zugänglich zu halten, indem Sie preserveDrawingBuffer
auf true setzen. Aus der Spezifikation:
Dieses Standardverhalten kann durch Festlegen des preserveDrawingBuffer-Attributs des WebGLContextAttributes-Objekts geändert werden. Wenn dieses Flag wahr ist, soll der Inhalt des Zeichenpuffers beibehalten werden, bis der Autor sie löscht oder überschreibt. Wenn dieses Flag falsch ist, kann der Versuch, Vorgänge auszuführen, die diesen Kontext als Quellbild verwenden, nachdem die Renderfunktion zurückgegeben wurde, zu undefiniertem Verhalten führen. Dazu gehören readPixels oder toDataURL-Aufrufe oder die Verwendung dieses Kontexts als Quellbild des Aufrufs texImage2D oder drawImage eines anderen Kontexts.
In dem von Ihnen bereitgestellten Beispiel ändert der Code lediglich die Kontexterstellungszeile:
%Vor%Denken Sie daran, dass der langsamere Pfad in einigen Browsern und die Leistung darunter leiden werden, je nachdem, was und wie Sie rendern. Sie sollten in den meisten Desktop-Browsern, in denen die Kopie nicht wirklich gemacht werden muss, gut sein, und diese machen die überwiegende Mehrheit der WebGL-fähigen Browser aus ... aber nur für den Moment.
Allerdings gibt es eine andere Option (die im nächsten Abschnitt der Spezifikation etwas verwirrend erwähnt wird).
Im Wesentlichen erstellen Sie die Kopie selbst vor Schritt 2: nachdem alle Zeichenaufrufe beendet wurden, aber bevor Sie die Kontrolle über Ihren Code an den Browser zurückgeben. Dies ist der Fall, wenn der WebGL-Zeichnungspuffer noch intakt und zugänglich ist und Sie dann problemlos auf die Pixel zugreifen können. Sie verwenden die gleichen toDataUrl
oder readPixels
Aufrufe, die Sie sonst verwenden würden, es ist nur das Timing, das wichtig ist.
Hier bekommen Sie das Beste aus beiden Welten. Sie erhalten eine Kopie des Zeichenpuffers, aber Sie zahlen nicht für jeden Frame, auch nicht für diejenigen, in denen Sie keine Kopie benötigen (was die meisten sein können), wie Sie es mit preserveDrawingBuffer
auf gesetzt haben wahr.
Fügen Sie in dem von Ihnen angegebenen Beispiel Ihren Code an den unteren Rand von drawScene
und Sie sollten die Kopie der Leinwand direkt darunter sehen:
Hier sind einige Dinge zu versuchen. Ich weiß nicht, ob einer von diesen sollte notwendig sein, um diese Arbeit zu machen, aber sie könnten einen Unterschied machen.
preserveDrawingBuffer: true
zu den getContext
Attributen hinzu. Tags und Links javascript canvas webgl