Ich möchte meine Grafiken in einen Puffer zeichnen und sie dann so wie sie sind auf die Leinwand kopieren, damit ich Animationen erstellen und Flackern vermeiden kann. Aber ich konnte diese Option nicht finden. Weiß jemand, wie ich das machen kann?
javascript
html
canvas
double-buffering
foreyez
quelle
quelle
explorercanvas
, aber das ist natürlich nicht HTML5 und ist eincanvas
Element, das lediglich von VML emuliert wird. Ich habe noch nie einen anderen Browser gesehen.Antworten:
Der folgende hilfreiche Link zeigt nicht nur Beispiele und Vorteile der doppelten Pufferung, sondern auch einige andere Leistungstipps für die Verwendung des HTML5-Canvas-Elements. Es enthält Links zu jsPerf-Tests, mit denen Testergebnisse über mehrere Browser hinweg in einer Browserscope-Datenbank zusammengefasst werden. Dies stellt sicher, dass die Leistungstipps überprüft werden.
http://www.html5rocks.com/de/tutorials/canvas/performance/
Der Einfachheit halber habe ich ein minimales Beispiel für eine effektive Doppelpufferung beigefügt, wie im Artikel beschrieben.
quelle
Eine sehr einfache Methode besteht darin, zwei Canvas-Elemente an derselben Bildschirmposition zu haben und die Sichtbarkeit für den Puffer festzulegen, den Sie anzeigen möchten. Zeichne auf das Versteckte und drehe es um, wenn du fertig bist.
Etwas Code:
CSS:
JS einblättern:
In diesem Code enthält das Array 'Buffers []' beide Canvas-Objekte. Wenn Sie also mit dem Zeichnen beginnen möchten, müssen Sie immer noch den Kontext abrufen:
quelle
<noscript>
und erstelle meine Canvas-Elemente gerne in Javascript. Normalerweise möchten Sie sowieso in Javascript nach Canvas-Unterstützung suchen. Warum sollten Sie also eine Canvas-Fallback-Nachricht in Ihren HTML-Code einfügen?Alle von mir getesteten Browser übernehmen diese Pufferung für Sie, indem sie die Zeichenfläche erst neu streichen, wenn der Code, der Ihren Frame zeichnet, vollständig ist. Siehe auch die WHATWG-Mailingliste: http://www.mail-archive.com/[email protected]/msg19969.html
quelle
Sie können es jederzeit tun
var canvas2 = document.createElement("canvas");
und überhaupt nicht an das DOM anhängen.Nur zu sagen, da ihr so besessen
display:none;
davon zu sein scheint, scheint mir sauberer zu sein und ahmt die Idee der doppelten Pufferung genauer nach als nur eine unbeholfen unsichtbare Leinwand.quelle
Mehr als zwei Jahre später:
Es ist nicht erforderlich, die doppelte Pufferung manuell zu implementieren. Herr Geary schrieb darüber in seinem Buch "HTML5 Canvas" .
Flimmergebrauch effektiv reduzieren
requestAnimationFrame()
!quelle
Josh fragte (vor einiger Zeit), wie der Browser weiß, "wann der Zeichenvorgang endet", um ein Flackern zu vermeiden. Ich hätte seinen Beitrag direkt kommentiert, aber mein Repräsentant ist nicht hoch genug. Auch das ist nur meine Meinung. Ich habe keine Fakten, um dies zu belegen, aber ich bin ziemlich zuversichtlich, und es kann für andere hilfreich sein, dies in Zukunft zu lesen.
Ich vermute, der Browser "weiß" nicht, wann Sie mit dem Zeichnen fertig sind. Aber genau wie bei den meisten Javascript ist der Browser im Wesentlichen gesperrt und kann / kann nicht auf seine Benutzeroberfläche aktualisieren / reagieren, solange Ihr Code ausgeführt wird, ohne die Kontrolle an den Browser abzugeben. Ich vermute, wenn Sie die Leinwand löschen und Ihren gesamten Rahmen zeichnen, ohne die Kontrolle an den Browser abzugeben, wird Ihre Leinwand erst dann gezeichnet, wenn Sie fertig sind.
Wenn Sie eine Situation einrichten, in der Ihr Rendering mehrere setTimeout / setInterval / requestAnimationFrame-Aufrufe umfasst, in der Sie die Zeichenfläche in einem Aufruf löschen und in den nächsten mehreren Aufrufen Elemente auf Ihrer Zeichenfläche zeichnen und den Zyklus (z. B.) alle 5 Aufrufe wiederholen, I. Ich würde wetten, dass Sie ein Flackern sehen würden, da die Leinwand nach jedem Anruf aktualisiert wird.
Trotzdem bin ich mir nicht sicher, ob ich dem vertrauen würde. Wir sind bereits an dem Punkt angelangt, an dem Javascript vor der Ausführung zu nativem Maschinencode kompiliert wird (zumindest macht das die V8-Engine von Chrome, soweit ich weiß). Es würde mich nicht wundern, wenn es nicht zu lange dauern würde, bis Browser ihr Javascript in einem von der Benutzeroberfläche getrennten Thread ausführen und den Zugriff auf Benutzeroberflächenelemente synchronisieren, sodass die Benutzeroberfläche während der Ausführung von Javascript, die nicht auf die Benutzeroberfläche zugreift, aktualisiert / reagiert werden kann. Wenn / falls dies passiert (und ich verstehe, dass es viele Hürden gibt, die überwunden werden müssten, z. B. Event-Handler, die starten, während Sie noch anderen Code ausführen), werden wir wahrscheinlich Flimmern auf Leinwand-Animationen sehen, die nicht verwendet werden eine Art Doppelpufferung.
Persönlich mag ich die Idee, dass zwei Leinwandelemente übereinander positioniert und abwechselnd auf jedem Rahmen gezeigt / gezeichnet werden. Ziemlich unauffällig und wahrscheinlich ziemlich einfach zu einer vorhandenen Anwendung mit ein paar Codezeilen hinzuzufügen.
quelle
Für die Ungläubigen gibt es hier einen flackernden Code. Beachten Sie, dass ich explizit lösche, um den vorherigen Kreis zu löschen.
quelle
In Webbrowsern flackert es nicht! Sie verwenden bereits dbl-Pufferung für ihr Rendern. Js Engine erstellt Ihr gesamtes Rendering, bevor es angezeigt wird. Außerdem können im Kontext nur Stapeltransformationsmatrixdaten und dergleichen gespeichert und wiederhergestellt werden, nicht der Canvas-Inhalt selbst. Sie brauchen oder wollen also keine Doppelpufferung!
quelle
Anstatt Ihre eigenen zu rollen, werden Sie wahrscheinlich die beste Kilometerleistung erzielen, indem Sie eine vorhandene Bibliothek zum Erstellen einer sauberen und flimmerfreien JavaScript-Animation verwenden:
Hier ist eine beliebte: http://processingjs.org
quelle
Sie benötigen 2 Zeichenfläche: (Beachten Sie den CSS-Z-Index und die Position: absolut)
Sie können feststellen, dass die erste Leinwand sichtbar und die zweite versteckt ist. Die Idee ist, auf die versteckte Leinwand zu zeichnen. Danach werden wir die sichtbare verstecken und die versteckte Leinwand sichtbar machen. wenn es versteckt ist 'klare versteckte Leinwand
quelle
Opera 9.10 ist sehr langsam und zeigt den Zeichenvorgang. Wenn Sie möchten, dass ein Browser keine doppelte Pufferung verwendet, probieren Sie Opera 9.10 aus.
Einige Leute schlugen vor, dass Browser irgendwie bestimmen, wann der Zeichenprozess endet, aber können Sie erklären, wie das funktionieren kann? Ich habe in Firefox, Chrome oder IE9 kein offensichtliches Flackern bemerkt, selbst wenn die Zeichnung langsam ist. Es scheint also, dass sie das tun, aber wie dies erreicht wird, ist mir ein Rätsel. Wie würde der Browser jemals wissen, dass die Anzeige aktualisiert wird, bevor weitere Zeichenanweisungen ausgeführt werden sollen? Denken Sie, dass sie es nur zeitlich festlegen, wenn ein Intervall von mehr als 5 ms vergeht, ohne dass eine Zeichenanweisung für die Leinwand ausgeführt wird, wird davon ausgegangen, dass Puffer sicher ausgetauscht werden können?
quelle
In den meisten Situationen müssen Sie dies nicht tun, der Browser implementiert dies für Sie. Aber nicht immer nützlich!
Sie müssen dies noch implementieren, wenn Ihre Zeichnung sehr kompliziert ist. Der größte Teil der Bildschirmaktualisierungsrate liegt bei etwa 60 Hz, dh die Bildschirmaktualisierungen erfolgen pro 16 ms. Die Aktualisierungsrate des Browsers kann sich dieser Zahl annähern. Wenn Ihre Form 100 ms benötigt, um fertiggestellt zu werden, sehen Sie eine unvollständige Form. In dieser Situation können Sie also eine doppelte Pufferung implementieren.
Ich habe einen Test gemacht:
Clear a rect, wait for some time, then fill with some color.
Wenn ich die Zeit auf 10 ms einstelle, sehe ich kein Flackern. Aber wenn ich es auf 20 ms stelle, passiert das Flackern.quelle