Pixi.js: Beim Ändern der Leinwandgröße flackert ein weißer Hintergrund

Erstellt am 3. Dez. 2016  ·  7Kommentare  ·  Quelle: pixijs/pixi.js

Ich ändere die Größe der Leinwand mit einer einfachen Standalone-Funktion wie folgt:

function resizeCanvas(width, height) {
    game.canvas.width = width;
    game.canvas.height = height;
    game.canvas.style.width = width / game.resolution + 'px';
    game.canvas.style.height = height / game.resolution + 'px';
}

Und beim Hochfahren des Spiels mache ich so etwas:

game.renderer = new PIXI.WebGLRenderer(
    game.canvas.width,
    game.canvas.height,
    {
         view: game.canvas,
         backgroundColor: 0x000000,
     }
);

// recompute viewport size & canvas size with  browser window size 
game.scaler.update();  

// resize  renderer with new size.
game.renderer.resize(game.viewportWidth, game.viewportHeight);

Der Testfall ist sehr einfach: Zeichnen Sie ein kleines PNG-Bild.

Browser: Chrome 55 für macOS 10.12

Safari ist in Ordnung.

Ich weiß, dass dies vielleicht ein Problem von Chrome ist, aber ich hoffe, es gibt einen Hack-Weg, um es zu beheben.

Vielen Dank

💾 v4.x (Legacy)

Hilfreichster Kommentar

Ohh, danke! @mickdekkers das ist großartig, der Aufruf von render macht es sofort mit den ResizeObserver Callbacks.

Alle 7 Kommentare

Ich verwende den Code wie folgt, um diesen Fehler zu beheben:

    game.renderer.resize(game.viewportWidth - 1, game.viewportHeight);
    setTimeout(function() {
        game.renderer.resize(game.viewportWidth, game.viewportHeight);
    }, 1);

Es ist so hässlich , Wer könnte mir einen besseren Vorschlag machen ?

Sicherlich ,Der beste Weg ist, es dem Chrome-Team zu melden.
Wer könnte es tun? Mein Englisch ist zu schwach, um diesen Fehler zu beschreiben。

neues Chrome nein dieses Problem.

Ich möchte bestätigen, dass dies immer noch auf Desktop-Safari (neueste) und Edge geschieht. Pixi v4.3.0.

Edit: In Pseudocode machten wir so etwas wie

handleWindowDimensionChange(function() {
renderer.resize(window.innerWidth, window.innerHeight)
});

Die Größenänderung des Fensters führt in beiden genannten Browsern zu hässlichem Flackern. Nicht Chrome oder Firefox.

Hat jemand eine Idee, was das Flackern bei der Größenänderung möglicherweise verursachen kann? Ich habe das gleiche Problem in Electron (getestet mit verschiedenen Versionen, aber im Grunde Chromium 56, 58 und 59) und Pixi 4.5.5 (getestet unter Linux und macOS), aber nur in einem bizarren Szenario:

Ich ändere die Größe des Renderers (webgl) basierend auf einem Containerelement im DOM: Das Containerelement kann die Größe ändern, wenn die Größe des Fensters geändert oder durch ein in Javascript implementiertes Widget mit Größenanpassung ausgelöst wird. Wenn ich jetzt die Größe des Renderers im resize des Fensters und des benutzerdefinierten resize Handlers des Widgets (basierend auf mousemove Ereignissen) ändere, ist alles in Ordnung , aber wenn ich das neue ResizeObserver API auf dem Containerelement stattdessen bekomme ich ziemlich schlechtes Flackern.

Ein paar Beobachtungen:

  • Das Flackern wird dadurch verursacht, dass die gesamte Leinwand gelöscht wird (wie im OP erwähnt, in meinem Fall ist sie nicht weiß, sondern transparent): Dies ist deutlich sichtbar, wenn ich eine Leistungsaufnahme mit Screenshots in den Dev-Tools mache: Die Leinwand ist für ungefähr leer 100ms während der Größenänderung.
  • Ich nahm an, dass dies ein Leistungs- / Timing-Problem ist, da ResizeObserver häufiger ausgelöst wird, aber das ist nicht der Fall: Ich erhalte in beiden Szenarien eine vergleichbare Häufigkeit.
  • Außerdem drossle ich die Größenänderung selbst, sodass die Häufigkeit des tatsächlichen Aufrufs von renderer.resize in beiden Fällen identisch ist; Außerdem erfolgt der Aufruf in keinem der Event-Handler, sondern verzögert sich, so dass es für mich unwahrscheinlich erscheint, dass das Timing schuld ist.
  • Meine nächste Vermutung war, dass die von ResizeObserver gemeldeten Werte unterschiedlich sind; es meldet die Inhaltsbox des Containers, nicht die Begrenzungsbox, aber da es keinen Rahmen oder Auffüllen gibt, sind die Werte gleich. Außerdem runde ich die Abmessungen in beiden Szenarien auf volle Pixel. Tatsächlich sind sowohl die eingestellten Dimensionen als auch die Frequenz in beiden Fällen sehr ähnlich.
  • Das Flackern hört auf, wenn ich den Throttle-Timeout auf etwa 500 ms oder höher erhöhe
  • Mit den Window/Widget-Event-Handlern muss ich den Container mit getBoundingClientRect() messen – um diesen Aufruf zu speichern (was zu einem Repaint führt) ist eigentlich ein wichtiger Grund für die Verwendung von ResizeObserver aber ich habe mir gedacht, dass Das Fehlen des zusätzlichen Repaints kann das Flackern aus irgendeinem Grund verursachen. Also habe ich vor der Größenänderung einen unnötigen Aufruf zu getBoundingClientRect() hinzugefügt, aber ohne Erfolg.

Ich bin nicht allzu besorgt, weil es eine praktikable Problemumgehung gibt (mit den beiden separaten Handlern anstelle von ResizeObserver ), aber ich würde wirklich gerne wissen, was dies verursacht. Ich habe auch autoResize und antialias deaktiviert, aber das hat keinen Unterschied gemacht. Irgendwelche Ideen, was ich noch versuchen könnte?

@inukshuk In meinem Fall stellte sich die Lösung als wirklich einfach heraus: Rufen Sie nach der Größenänderung einfach render an.

app.renderer.resize(width, height)
// Immediately render because resizing clears the canvas
app.render()

Das hat das Flackern bei mir behoben. Denken Sie daran, dass bei laufenden Animationen nur der letzte Frame bis zu Ihrer nächsten Update-Schleife angezeigt wird, was zu einem "Einfrieren"-Effekt führen kann. Wenn Sie einen reibungslosen Ablauf gewährleisten möchten, sollten Sie Ihre Update-Funktion aufrufen, bevor Sie render aufrufen.

Ohh, danke! @mickdekkers das ist großartig, der Aufruf von render macht es sofort mit den ResizeObserver Callbacks.

Dieser Thread wurde automatisch gesperrt, da nach dem Schließen in letzter Zeit keine Aktivität stattgefunden hat. Bitte öffnen Sie eine neue Ausgabe für verwandte Fehler.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen