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 der ViewTransition-Schnittstelle verzögert das Beenden des Ansichtsübergangs und die Zerstörung des zugehörigen Pseudo-Element-Baums, bis ein in die Methode übergebener Promise aufgelöst wurde.
Syntax
waitUntil(promise)
Parameter
Rückgabewert
Keiner (undefined).
Beschreibung
Wenn ein Ansichtübergang im gleichen Dokument gestartet wird (normalerweise über Document.startViewTransition()), konstruiert der Browser automatisch einen Pseudo-Element-Baum, um ausgehende und eingehende Änderungen am DOM anzuzeigen und zu animieren. Dieser Baum wird konstruiert, wenn der Ansichtsübergang zu animieren beginnt und wird zerstört, wenn die Animationen, die mit allen Pseudo-Elementen des Ansichtsübergangs assoziiert sind, den beendeten Zustand erreichen (finished ist aufgelöst).
Dies funktioniert gut für die meisten Anwendungsfälle, aber es gibt einige, bei denen es von Vorteil ist, wenn der Pseudo-Baum über den Endzustand der Animation hinaus bestehen bleibt. Dies kann mit der Methode waitUntil() erreicht werden, die einen Promise als Argument erhält. Das Aufrufen von waitUntil() bewirkt, dass der Pseudo-Baum bestehen bleibt, bis der Promise aufgelöst wird. An diesem Punkt wird auch der finished-Promise aufgelöst.
Wiederholte Aufrufe von waitUntil() mit mehreren unterschiedlichen Promises verzögern den Endzustand, bis alle gegebenen Promises aufgelöst sind.
Anwendungsfälle beinhalten:
- Kombinieren eines Ansichtsübergangs mit scroll-gesteuerten Animationen. Wenn die Übergangsanimation von einem Scroll- oder Ansichtsvortschritts-Timeline gesteuert wird, sollte der Unterbaum bestehen bleiben, wenn die Animationen beendet sind, da beim Zurückscrollen die Pseudo-Elemente rückwärts animiert werden sollen.
- Kombinieren eines Ansichtsübergangs mit
requestAnimationFrame(). Wenn Sie den Zustand Ihrer Elemente inrequestAnimationFrame()-Rückrufen aktualisieren, weiß das Ansichtsübergangssystem nicht, wie lange der Pseudo-Element-Baum bestehen bleiben soll, und zerstört ihn sofort, sobald die CSS-Animationen beendet sind. - Jede Situation, in der Sie das Beenden des Ansichtsübergangs verzögern möchten, bis ein Ereignis eingetreten ist. Sie könnten zum Beispiel den Ansichtsübergang bei
pointerdownstarten und erst beipointerupbeenden wollen.
Beispiele
>Grundlegende Nutzung
Dieses Beispiel demonstriert die grundlegende Nutzung der waitUntil()-Methode, um das Beenden eines durch einen Button- oder Tastendruck gestarteten Ansichtsübergangs zu verzögern, bis die Button- oder Tasteneingabe endet.
HTML
Wir fügen ein <div>-Element ein, das Seiteninhalt enthält, inklusive eines <p>-Elements und eines <button>-Elements, das bei Betätigung den angezeigten Inhalt ändert. Der Absatz enthält ein aria-live-Attribut, damit DOM-Updates für Screenreader-Nutzer 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 ein, um Statusnachrichten zu protokollieren:
<p class="log"></p>
CSS
Zuerst setzen wir einen view-transition-name von page auf unser <div>-Element, damit wir nur diesen Bereich mit den Ansichtsübergangsanimationen ansprechen, anstatt die gesamte MDN-Seite.
.page {
view-transition-name: page;
}
Als Nächstes setzen wir eine animation-delay auf das ::view-transition-new()-Pseudo-Element (beachten Sie, wie wir den page-Baum ansprechen, anstatt den Standard-root-Baum). Dadurch verzögert sich die Einblendtransition des neuen DOM-Inhalts um 0.25 Sekunden, sodass es 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 das ::view-transition-old()- und das ::view-transition-new()-Element. Dies hat den Effekt, dass die Standard-Ausblend- und Einblendanimationen 0.5 Sekunden dauern und die Inhalts-opacity auf 0.5 gesetzt wird, bis der Ansichtsübergang abgeschlossen ist.
::view-transition-old(page),
::view-transition-new(page) {
animation-duration: 0.5s;
opacity: 0.5;
}
JavaScript
Unser Skript beginnt mit dem Abrufen von Referenzen zu dem Inhaltsabsatz, dem Button und dem Log-Absatz.
const content = document.querySelector(".content");
const btn = document.querySelector("button");
const log = document.querySelector(".log");
Dann setzen wir Event-Listener auf den Button, sodass bei pointerdown/keypress die benutzerdefinierte Funktion btnHandler() ausgeführt wird. Wir geben an, dass der keypress-Handler nur einmal ausgelöst wird, da er sonst bei langem Tastendruck mehrmals ausgelöst wird, wodurch die Ansichten ständig gewechselt werden, 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 Ansichtsübergang zu starten, und führt zunächst eine benutzerdefinierte Funktion namens updatePage() aus, die die zu animierenden DOM-Updates durchführt. Danach erstellen wir eine Variable namens resolveTransition und einen neuen Promise namens p. Wir setzen resolveTransition gleich der resolve-Funktion des Promise-Callbacks, sodass diese aufgerufen wird, wenn resolveTransition() aufgerufen wird, wie wir es in den nachfolgenden pointerup- und keyup-Event-Listenern tun. Beachten Sie, dass wir den keypress-Handler jedes Mal erneut anwenden müssen, wenn der keyup-Handler ausgelöst wird, da er jedes Mal nur einmal ausgelöst wird.
Wir führen waitUntil() aus und übergeben den Promise p als Argument. Das bedeutet, dass der Ansichtsübergang bestehen bleibt, bis p bei pointerup aufgelöst ist. Um dies zu bestätigen, verwenden wir den ViewTransition.finished-Promise, um eine showLog()-Funktion auszuführen, sobald der Übergang abgeschlossen ist, die eine Nachricht in den Log-Absatz schreibt.
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 Funktion updatePage(), die das Seiten-DOM aktualisiert. Sie schaltet zwischen dem Einstellen des textContent des Inhaltsabsatzes auf das erste und das zweite Element des pageContent-Arrays um.
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];
}
}
Abschließend definieren wir die Funktion showLog() — sie setzt den textContent des Log-Absatzes auf "View transition finished", wartet eine Sekunde und setzt ihn dann wieder auf einen leeren String zurück.
function showLog() {
log.textContent = "View transition finished";
setTimeout(() => {
log.textContent = "";
}, 1000);
}
Ergebnis
Versuchen Sie, den Button mit Ihrer Tastatur, Maus oder einem anderen Zeigegerät lange zu drücken — Sie werden sehen, dass die Überblendanimationsübergänge auftreten, aber der Inhalt bleibt ausgegraut (aufgrund der opacity: 0.5, die auf die Ansichtsübergangspseudo-Elemente eingestellt ist), bis Sie den langen Druck beenden. Dies liegt daran, dass der im waitUntil()-Aufruf referenzierte Promise p nicht aufgelöst ist und daher der Ansichtsübergang nicht beendet wird, bis die pointerup/keyup-Ereignisse ausgelöst werden.
Die Log-Nachricht "View transition finished" erscheint auch erst, wenn der Ansichtsübergang abgeschlossen ist, da die Funktion, die dies behandelt, an den ViewTransition.finished-Promise gebunden ist.
Spezifikationen
| Spezifikation |
|---|
| CSS View Transitions Module Level 2> # dom-viewtransition-waituntil> |