ViewTransition: waitUntil() Methode
Experimentell: Dies ist eine experimentelle Technologie
Überprüfen Sie die Browser-Kompatibilitätstabelle sorgfältig vor der Verwendung auf produktiven Webseiten.
Die waitUntil()-Methode des ViewTransition-Interfaces verzögert das Beenden der View-Übergangs und die Zerstörung des zugehörigen Pseudoelement-Baums, bis ein in die Methode übergebenes Promise aufgelöst wurde.
Syntax
waitUntil(promise)
Parameter
Rückgabewert
Keiner (undefined).
Beschreibung
Wenn ein View-Übergang im selben Dokument gestartet wird (typischerweise über Document.startViewTransition()), konstruiert der Browser automatisch einen Pseudoelement-Baum, um ausgehende und eingehende Änderungen am DOM anzuzeigen und zu animieren. Dieser Baum wird erstellt, wenn der View-Übergang zu animieren beginnt, und wird zerstört, wenn die mit allen View-Übergangs-Pseudoelementen verbundenen Animationen den abgeschlossenen Zustand erreichen (finished ist aufgelöst).
Dies funktioniert gut für die meisten Anwendungsfälle, es gibt jedoch einige, die davon profitieren, dass der Pseudobaum über den Animationsabschluss hinaus bestehen bleibt. Dies kann mit der waitUntil()-Methode erreicht werden, die ein Promise als Argument erhält. Der Aufruf von waitUntil() bewirkt, dass der Pseudobaum bestehen bleibt, bis das Promise aufgelöst wird. Zu diesem Zeitpunkt wird auch das finished-Promise aufgelöst.
Wiederholte Aufrufe von waitUntil() mit Angabe mehrerer unterschiedlicher Promises verzögern den Abschlusszustand, bis alle angegebenen Promises aufgelöst sind.
Anwendungsfälle umfassen:
- Die Kombination eines View-Übergangs mit scroll-gesteuerten Animationen. Wenn die Übergangsanimation durch einen Scroll-Fortschritt oder einen Ansichts-Fortschrittszeitstrahl gesteuert wird, sollte der Unterbaum bestehen bleiben, wenn die Animationen enden, da beim Zurückscrollen die Pseudoelemente rückwärts animiert werden können.
- Die Kombination eines View-Übergangs mit
requestAnimationFrame(). Wenn Sie den Status Ihrer Elemente inrequestAnimationFrame()-Callbacks aktualisieren, weiß das View-Übergangssystem nicht, wie lange der Pseudoelement-Baum bestehen bleiben soll, und zerstört ihn sofort, sobald die CSS-Animationen abgeschlossen sind. - Jede Situation, in der Sie das Beenden des View-Übergangs verzögern möchten, bis ein Ereignis aufgetreten ist. Beispielsweise könnten Sie den View-Übergang bei
pointerdownstarten und ihn erst beipointerupbeenden wollen.
Beispiele
>Grundlegende Verwendung
Dieses Beispiel zeigt die grundlegende Verwendung der waitUntil()-Methode, um das Beenden eines durch einen Button- oder Tastendruck gestarteten View-Übergangs zu verzögern, bis der Button- oder Tastendruck endet.
HTML
Wir fügen ein <div>-Element ein, das Seiteninhalt enthält, darunter ein <p>-Element und ein <button>-Element, das bei Betätigung den angezeigten Inhalt ändert. Der Absatz enthält ein aria-live-Attribut, sodass DOM-Updates für Bildschirmleser-Benutzer angekündigt werden.
<div class="page">
<p class="content" aria-live="polite">Hello! This is the first page.</p>
<button>Change page</button>
</div>
Wir fügen auch ein zweites <p>-Element hinzu, um Statusmeldungen zu protokollieren:
<p class="log"></p>
CSS
Zuerst wenden wir ein view-transition-name von page auf unser <div>-Element an, sodass wir nur diesen Bereich mit den View-Übergangsanimationen anstatt der gesamten MDN-Seite ansprechen können.
.page {
view-transition-name: page;
}
Als nächstes setzen wir eine animation-delay auf das ::view-transition-new()-Pseudoelement (beachten Sie, wie wir den page-Baum anstelle des Standard-root-Baums angeben). Dies verzögert die standardmäßige Einblendung des neuen DOM-Inhalts um 0.25 Sekunden, sodass er leicht nach dem Ausblenden des alten DOM-Inhalts einblendet.
::view-transition-new(page) {
animation-delay: 0.25s;
}
Nun setzen wir eine benutzerdefinierte animation-duration und opacity auf die ::view-transition-old() und ::view-transition-new()-Elemente. Dies hat zur Folge, dass die standardmäßigen Ausblend- und Einblendanimationen 0.5 Sekunden dauern und die Inhalts-opacity auf 0.5 gesetzt wird, bis der View-Übergang beendet ist.
::view-transition-old(page),
::view-transition-new(page) {
animation-duration: 0.5s;
opacity: 0.5;
}
JavaScript
Unser Skript beginnt damit, Referenzen zum Inhaltsabsatz, Button und Protokollabsatz zu erhalten.
const content = document.querySelector(".content");
const btn = document.querySelector("button");
const log = document.querySelector(".log");
Als nächstes setzen wir Event-Listener auf den Button, sodass bei pointerdown/keypress die btnHandler()-Funktion ausgeführt wird. Wir spezifizieren, dass der keypress-Handler nur once ausgelöst wird, da er sonst mehrfach ausgelöst wird, wenn eine Taste lange gedrückt wird, was dazu führt, dass zwischen den Ansichten ständig gewechselt wird, was nicht das gewünschte Verhalten ist.
btn.addEventListener("pointerdown", btnHandler);
btn.addEventListener("keypress", btnHandler, {
once: true,
});
Die Funktion btnHandler() ruft Document.startViewTransition() auf, um den View-Übergang zu starten, und führt zunächst eine benutzerdefinierte Funktion namens updatePage() aus, die die DOM-Updates durchführt, die animiert werden sollen. Anschließend erstellen wir eine Variable namens resolveTransition und ein neues Promise namens p. Wir setzen resolveTransition gleich der resolve-Funktion des Promise-Callbacks, sodass, wenn resolveTransition() aufgerufen wird, wie wir es innerhalb der nachfolgenden pointerup- und keyup-Event-Listener tun, das Promise aufgelöst wird. Beachten Sie, dass wir den keypress-Handler jedes Mal erneut anwenden müssen, wenn der keyup-Handler ausgelöst wird, da er nur einmal pro Auslösung feuert.
Wir führen waitUntil() aus und übergeben es das Promise p als Argument. Dies bedeutet, dass der View-Übergang bestehen bleibt, bis p bei pointerup aufgelöst wird. Um dies zu beweisen, verwenden wir das ViewTransition.finished-Promise, um eine showLog()-Funktion auszuführen, sobald der Übergang beendet ist, die eine Nachricht in den Protokollabsatz drucken wird.
function btnHandler() {
const transition = document.startViewTransition(() => {
updatePage();
let resolveTransition;
const p = new Promise((resolve) => {
resolveTransition = resolve;
});
window.addEventListener("pointerup", () => {
resolveTransition();
});
window.addEventListener("keyup", () => {
resolveTransition();
btn.addEventListener("keypress", btnHandler, {
once: true,
});
});
transition.waitUntil(p);
transition.finished.then(() => showLog());
});
}
Als nächstes definieren wir die updatePage()-Funktion, die das Page-DOM aktualisiert. Sie wechselt zwischen dem Setzen des textContent des Inhaltsabsatzes auf das erste und zweite Element des pageContent-Arrays.
const pageContent = [
"Hello! This is the first page.",
"Well, this is the second page.",
];
function updatePage() {
if (content.textContent === pageContent[0]) {
content.textContent = pageContent[1];
} else {
content.textContent = pageContent[0];
}
}
Schließlich definieren wir die showLog()-Funktion – diese setzt den textContent des Protokollabsatzes auf "View transition finished", wartet eine Sekunde und setzt ihn dann wieder auf einen leeren String.
function showLog() {
log.textContent = "View transition finished";
setTimeout(() => {
log.textContent = "";
}, 1000);
}
Ergebnis
Versuchen Sie, die Taste mit Ihrer Tastatur, Maus oder einem anderen Zeigegerät lange zu drücken – Sie werden sehen, dass die Cross-Fade-Animationsübergänge auftreten, aber der Inhalt bleibt ausgegraut (aufgrund der opacity: 0.5, die auf die View-Übergangspseudoelemente gesetzt ist), bis Sie den langen Druck beenden. Dies liegt daran, dass das innerhalb des waitUntil()-Aufrufs referenzierte p-Promise nicht aufgelöst ist und daher der View-Übergang nicht beendet ist, bis die pointerup/keyup-Ereignisse ausgelöst werden.
Die Protokollnachricht "View transition finished" erscheint ebenfalls erst, wenn der View-Übergang beendet ist, da die Funktion, die dies behandelt, an das ViewTransition.finished-Promise gebunden ist.
Spezifikationen
| Spezifikation |
|---|
| CSS View Transitions Module Level 2> # dom-viewtransition-waituntil> |