Verwenden der View Transition API
Dieser Artikel erklärt die Theorie hinter der Funktionsweise der View Transition API, wie Sie View Transitions erstellen und die Übergangsanimationen anpassen können, und wie Sie aktive View Transitions manipulieren. Dies umfasst View Transitions sowohl für DOM-Zustandsaktualisierungen in einer Single-Page-App (SPA) als auch für die Navigation zwischen Dokumenten in einer Multi-Page-App (MPA).
Der View Transition Prozess
Lassen Sie uns den Prozess durchgehen, durch den ein View Transition funktioniert:
-
Ein View Transition wird ausgelöst. Wie dies geschieht, hängt vom Typ des View Transitions ab:
- Bei denselben Dokumentübergängen (SPAs) wird ein View Transition ausgelöst, indem die Funktion, die die DOM-Aktualisierung des View Changes auslösen würde, als Callback an die Methode
document.startViewTransition()
übergeben wird. - Im Falle von dokumentübergreifenden Übergängen (MPAs) wird ein View Transition durch die Navigation zu einem neuen Dokument ausgelöst. Sowohl das aktuelle als auch das Zieldokument der Navigation müssen auf demselben Ursprung sein und in den View Transition einwilligen, indem sie eine
@view-transition
Regel in ihrem CSS mit einemnavigation
Descriptor vonauto
enthalten.Hinweis: Ein aktiver View Transition hat eine zugehörige
ViewTransition
Instanz (zum Beispiel, zurückgegeben vonstartViewTransition()
im Falle von gleich dokumentierten (SPA) Übergängen). DasViewTransition
Objekt enthält mehrere Versprechen, die es Ihnen ermöglichen, Code in Reaktion auf verschiedene Teile des View Transition Prozesses auszuführen. Weitere Informationen finden Sie unter Controlling view transitions with JavaScript.
- Bei denselben Dokumentübergängen (SPAs) wird ein View Transition ausgelöst, indem die Funktion, die die DOM-Aktualisierung des View Changes auslösen würde, als Callback an die Methode
-
Auf der aktuellen (alten Seite) Ansicht erfasst die API statische Bildsnapshots von Elementen, die eine
view-transition-name
deklariert haben. -
Der View Change erfolgt:
-
Im Falle von gleich dokumentierten Übergängen (SPAs) wird der Callback, der an
startViewTransition()
übergeben wird, aufgerufen, was dazu führt, dass sich das DOM ändert.Wenn der Callback erfolgreich ausgeführt wurde, wird das
ViewTransition.updateCallbackDone
Versprechen erfüllt, was Ihnen ermöglicht, auf die DOM-Aktualisierung zu reagieren. -
Im Falle von dokumentübergreifenden Übergängen (MPAs) erfolgt die Navigation zwischen dem aktuellen und dem Zieldokument.
-
-
Die API erfasst "Live"-Snapshots (das heißt interaktive DOM-Bereiche) aus der neuen Ansicht.
An diesem Punkt ist der View Transition dabei, ausgeführt zu werden, und das
ViewTransition.ready
Versprechen wird erfüllt, was Ihnen ermöglicht, beispielsweise eine benutzerdefinierte JavaScript-Animation anstelle der Standardanimation auszuführen. -
Die Snapshots der alten Seite animieren "heraus", während die Snapshots der neuen Ansicht "hinein" animieren. Standardmäßig animieren die alten Ansichtssnapshots von
opacity
1 zu 0 und die neuen Ansichtssnapshots vonopacity
0 zu 1, was einen Überblendeffekt erzeugt. -
Wenn die Überganganimationen ihre Endzustände erreicht haben, wird das
ViewTransition.finished
Versprechen erfüllt, was Ihnen ermöglicht zu reagieren.
Hinweis:
Wenn der Seite Sichtbarkeitsstatus des Dokuments hidden
ist (zum Beispiel, wenn das Dokument von einem Fenster verdeckt wird, der Browser minimiert ist oder eine andere Browser-Registerkarte aktiv ist), während eines document.startViewTransition()
Aufrufs, wird die View Transition komplett übersprungen.
Eine Randbemerkung zu Snapshots
Es ist bemerkenswert, dass wir beim Sprechen über View Transitions häufig den Begriff snapshot verwenden, um sich auf einen Teil der Seite zu beziehen, der einen view-transition-name
deklariert hat. Diese Abschnitte werden separat von anderen Teilen der Seite mit unterschiedlichen view-transition-name
Werten animiert. Während der Prozess, einen Snapshot über eine View Transition zu animieren, tatsächlich zwei separate Snapshots umfasst — einen des alten und einen des neuen UI-Zustands — verwenden wir "snapshot", um der Einfachheit halber auf den gesamten Seitenbereich zu verweisen.
Der Snapshot des alten UI-Zustands ist ein statisches Bild, sodass der Benutzer nicht damit interagieren kann, während es "heraus" animiert.
Der Snapshot des neuen UI-Zustands ist ein interaktiver DOM-Bereich, sodass der Benutzer beginnen kann, mit dem neuen Inhalt zu interagieren, während es "hinein" animiert.
Der View Transition Pseudoelement-Baum
Um die ausgehenden und eingehenden Überganganimationen zu erstellen, konstruiert die API einen Pseudoelement-Baum mit folgender Struktur:
::view-transition └─ ::view-transition-group(root) └─ ::view-transition-image-pair(root) ├─ ::view-transition-old(root) └─ ::view-transition-new(root)
Im Falle von gleich dokumentierten Übergängen (SPAs) wird der Pseudoelement-Baum im Dokument verfügbar gemacht. Bei dokumentübergreifenden Übergängen (MPAs) wird der Pseudoelement-Baum nur im Zieldokument verfügbar gemacht.
Die interessantesten Teile der Baumstruktur sind wie folgt:
-
::view-transition
ist die Wurzel des View Transitions Overlays, das alle View Transition Gruppen enthält und über allen anderen Inhalten der Seite sitzt. -
Ein
::view-transition-group()
fungiert als Container für jeden View Transition-Snapshot. Dasroot
Argument gibt den Standard-Snapshot an — die View Transition Animation wird auf den Snapshot angewendet, dessenview-transition-name
root
ist. Standardmäßig ist dies ein Snapshot des:root
Elements, da die Standard-Browser-Stile dies definieren:css:root { view-transition-name: root; }
Beachten Sie jedoch, dass Seitenautoren dies ändern können, indem sie das Obenstehende aufheben und
view-transition-name: root
auf einem anderen Element setzen. -
::view-transition-old()
zielt auf den statischen Snapshot des alten Seitenelements ab und::view-transition-new()
zielt auf den Live-Snapshot des neuen Seitenelements ab. Beide werden als ersetzter Inhalt gerendert, auf die gleiche Weise wie ein<img>
oder<video>
, was bedeutet, dass sie mit Eigenschaften wieobject-fit
undobject-position
gestylt werden können.
Hinweis:
Es ist möglich, verschiedene DOM-Elemente mit verschiedenen benutzerdefinierten View Transition Animationen zu animieren, indem auf jedem ein anderer view-transition-name
gesetzt wird. In solchen Fällen wird für jedes ein ::view-transition-group()
erstellt. Siehe Different animations for different elements für ein Beispiel.
Hinweis:
Wie Sie später sehen werden, müssen Sie, um die ausgehenden und eingehenden Animationen zu personalisieren, die ::view-transition-old()
und ::view-transition-new()
Pseudoelemente mit Ihren Animationen anvisieren.
Erstellen eines einfachen View Transitions
Dieser Abschnitt veranschaulicht, wie man einen einfachen View Transition sowohl im SPA- als auch im MPA-Fall erstellt.
Einfacher SPA View Transition
Ein SPA kann Funktionalitäten beinhalten, um neue Inhalte abzurufen und das DOM als Reaktion auf ein Ereignis irgendeiner Art zu aktualisieren, wie z.B. das Klicken auf einen Navigationslink oder ein von einem Server gepushtes Update.
Unser View Transitions SPA-Beispiel ist eine einfache Bildergalerie. Wir haben eine Reihe von <a>
Elementen, die Thumbnail-<img>
Elemente beinhalten, die dynamisch mit JavaScript erzeugt werden. Wir haben auch ein <figure>
Element, das ein <figcaption>
und ein <img>
enthält, das die Großformat-Galeriebilder anzeigt.
Wenn auf ein Thumbnail geklickt wird, wird die Funktion displayNewImage()
über Document.startViewTransition()
ausgeführt, was dazu führt, dass das Großformatbild und die zugehörige Bildunterschrift im <figure>
angezeigt werden. Wir haben dies in eine updateView()
Funktion eingekapselt, die die View Transition API nur aufruft, wenn der Browser sie unterstützt:
function updateView(event) {
// Handle the difference in whether the event is fired on the <a> or the <img>
const targetIdentifier = event.target.firstChild || event.target;
const displayNewImage = () => {
const mainSrc = `${targetIdentifier.src.split("_th.jpg")[0]}.jpg`;
galleryImg.src = mainSrc;
galleryCaption.textContent = targetIdentifier.alt;
};
// Fallback for browsers that don't support View Transitions:
if (!document.startViewTransition) {
displayNewImage();
return;
}
// With View Transitions:
const transition = document.startViewTransition(() => displayNewImage());
}
Dieser Code reicht aus, um den Übergang zwischen angezeigten Bildern zu handhaben. Unterstützte Browser zeigen den Wechsel von alten zu neuen Bildern und Bildunterschriften als glattes Überblenden an (die Standardansicht Transition). Es funktioniert immer noch in nicht unterstützenden Browsern, aber ohne die schöne Animation.
Einfacher MPA View Transition
Beim Erstellen eines dokumentübergreifenden (MPA) View Transitions ist der Prozess sogar einfacher als bei SPAs. Kein JavaScript ist erforderlich, da das Update der Ansicht durch eine dokumentübergreifende, gleich-originelle Navigation statt durch eine JavaScript-initiierte DOM-Änderung ausgelöst wird. Um einen einfachen MPA View Transition zu ermöglichen, müssen Sie in beiden den aktuellen und Zieldokumenten eine @view-transition
Regel in ihrem CSS angeben, um sie einzuoptieren, wie folgt:
@view-transition {
navigation: auto;
}
Unser View Transitions MPA-Beispiel zeigt diese Regel in Aktion und demonstriert zusätzlich, wie Sie die ausgehenden und eingehenden Animationen des View Transitions anpassen können.
Hinweis: Derzeit können MPA View Transitions nur zwischen gleich-originellen Dokumenten erstellt werden, aber diese Einschränkung könnte in zukünftigen Implementierungen gelockert werden.
Anpassen Ihrer Animationen
Die View Transitions Pseudoelemente haben standardmäßig CSS Animationen angewendet (die in ihren Referenzseiten) detailliert sind.
Die meisten Erscheinungsübergänge erhalten eine standardmäßige sanfte Überblendungsanimation, wie oben erwähnt. Es gibt einige Ausnahmen:
height
undwidth
Übergänge haben eine glatte Skalierungsanimation angewendet.position
undtransform
Übergänge haben eine glatte Bewegungsanimation angewendet.
Sie können die Standardanimationen in jeder gewünschten Weise mit regulärem CSS modifizieren — visieren Sie die "from" Animation mit ::view-transition-old()
an, und die "to" Animation mit ::view-transition-new()
.
Zum Beispiel, um die Geschwindigkeit beider zu ändern:
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.5s;
}
Es wird empfohlen, dass Sie das ::view-transition-group()
mit solchen Stilen anvisieren, in Fällen, in denen Sie sie auf ::view-transition-old()
und ::view-transition-new()
anwenden möchten. Wegen der Pseudoelement-Hierarchie und der Standard-Benutzeragenten-Stile werden die Stile von beiden geerbt. Zum Beispiel:
::view-transition-group(root) {
animation-duration: 0.5s;
}
Hinweis:
Dies ist auch eine gute Möglichkeit, Ihren Code zu sichern — ::view-transition-group()
animiert auch und Sie könnten unterschiedliche Dauer für die group
/image-pair
Pseudoelemente gegenüber den old
und new
Pseudoelementen haben.
Im Falle von dokumentübergreifenden (MPA) Übergängen müssen die Pseudoelemente nur im Zieldokument enthalten sein, damit der View Transition funktioniert. Wenn Sie den View Transition in beide Richtungen verwenden möchten, müssen Sie ihn in beiden einbeziehen.
Unser View Transitions MPA-Beispiel enthält das obige CSS, geht aber noch einen Schritt weiter, indem es benutzerdefinierte Animationen definiert und sie auf die ::view-transition-old(root)
und ::view-transition-new(root)
Pseudoelemente anwendet. Das Ergebnis ist, dass der Standard-Überblendungsübergang durch einen "Hochwischen"-Übergang ersetzt wird, wenn eine Navigation stattfindet:
/* Create a custom animation */
@keyframes move-out {
from {
transform: translateY(0%);
}
to {
transform: translateY(-100%);
}
}
@keyframes move-in {
from {
transform: translateY(100%);
}
to {
transform: translateY(0%);
}
}
/* Apply the custom animation to the old and new page states */
::view-transition-old(root) {
animation: 0.4s ease-in both move-out;
}
::view-transition-new(root) {
animation: 0.4s ease-in both move-in;
}
Verschiedene Animationen für verschiedene Elemente
Standardmäßig werden alle verschiedenen Elemente, die sich während des Ansicht-Updates ändern, mit derselben Animation übergeblendet. Wenn Sie möchten, dass einige Elemente anders als die Standard root
Animation animieren, können Sie sie mit der view-transition-name
Eigenschaft trennen. Zum Beispiel, in unserem View Transitions SPA-Beispiel erhalten die <figcaption>
Elemente einen view-transition-name
von figure-caption
, um sie in Bezug auf View Transitions vom Rest der Seite zu trennen:
figcaption {
view-transition-name: figure-caption;
}
Mit diesem CSS angewendet würde der generierte Pseudoelement-Baum jetzt so aussehen:
::view-transition ├─ ::view-transition-group(root) │ └─ ::view-transition-image-pair(root) │ ├─ ::view-transition-old(root) │ └─ ::view-transition-new(root) └─ ::view-transition-group(figure-caption) └─ ::view-transition-image-pair(figure-caption) ├─ ::view-transition-old(figure-caption) └─ ::view-transition-new(figure-caption)
Das Vorhandensein des zweiten Satzes von Pseudoelementen ermöglicht es, separate View Transition Stylinge nur auf das <figcaption>
anzuwenden. Die verschiedenen alten und neuen Ansichts-Snapshots werden getrennt voneinander behandelt.
Der folgende Code wendet eine benutzerdefinierte Animation nur auf das <figcaption>
an:
@keyframes grow-x {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
@keyframes shrink-x {
from {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
::view-transition-group(figure-caption) {
height: auto;
right: 0;
left: auto;
transform-origin: right center;
}
::view-transition-old(figure-caption) {
animation: 0.25s linear both shrink-x;
}
::view-transition-new(figure-caption) {
animation: 0.25s 0.25s linear both grow-x;
}
Hier haben wir eine benutzerdefinierte CSS-Animation erstellt und sie auf die ::view-transition-old(figure-caption)
und ::view-transition-new(figure-caption)
Pseudoelemente angewendet. Wir haben auch eine Reihe anderer Stile zu beiden hinzugefügt, um sie an der gleichen Stelle zu halten und die Standardstilierung daran zu hindern, unsere benutzerdefinierten Animationen zu beeinträchtigen.
Hinweis:
Sie können *
als Bezeichner in einem Pseudoelement verwenden, um auf alle Snapshot-Pseudoelemente zu zielen, unabhängig davon, welchen Namen sie haben. Beispiel:
::view-transition-group(*) {
animation-duration: 2s;
}
Gültige view-transition-name
Werte
Die view-transition-name
Eigenschaft kann einen eindeutigen <custom-ident>
Wert annehmen, der jede Kennung sein kann, die nicht als ein Schlüsselwort missverstanden werden würde. Der Wert von view-transition-name
für jedes gerenderte Element muss eindeutig sein. Falls zwei gerenderte Elemente gleichzeitig denselben view-transition-name
haben, wird ViewTransition.ready
abgelehnt und der Übergang übersprungen.
Sie kann auch Schlüsselwortwerte annehmen wie:
none
: Verursacht, dass das Element nicht an einem separaten Snapshot teilnimmt, es sei denn, es hat ein übergeordnetes Element mit einem gesetztenview-transition-name
, in diesem Fall wird es als Teil dieses Elements gesnapshottet.match-element
: Setzt automatisch eindeutigeview-transition-name
Werte auf allen ausgewählten Elementen.
Nutzen Sie die Standardanimationsstile
Beachten Sie, dass wir auch eine andere Übergangsoption entdeckt haben, die einfacher ist und ein schöneres Ergebnis als das oben Genannte produziert hat. Unser endgültiger <figcaption>
View Transition sah schließlich so aus:
figcaption {
view-transition-name: figure-caption;
}
::view-transition-group(figure-caption) {
height: 100%;
}
Dies funktioniert, weil ::view-transition-group()
standardmäßig width
und height
zwischen den alten und neuen Ansichten mit einem sanften Maßstab überblendet. Wir mussten nur eine feste height
auf beiden Zuständen setzen, um es arbeiten zu lassen.
Hinweis:>Sanfte Übergänge mit der View Transition API enthält mehrere andere Anpassungsbeispiele.
Kontrollieren von View Transitions mit JavaScript
Ein View Transition hat eine zugehörige ViewTransition
Objektinstanz, die mehrere Versprechen-Mitglieder enthält, die es Ihnen ermöglichen, JavaScript als Reaktion auf verschiedene Zustände des Übergangs auszuführen. Zum Beispiel wird ViewTransition.ready
erfüllt, sobald der Pseudoelement-Baum erstellt und die Animation im Begriff ist zu starten, während ViewTransition.finished
erfüllt wird, sobald die Animation abgeschlossen ist und die neue Seitenansicht für den Benutzer sichtbar und interaktiv ist.
Der ViewTransition
kann wie folgt aufgerufen werden:
- Im Falle von gleich dokumentierten (SPA) Übergängen gibt die Methode
document.startViewTransition()
denViewTransition
zurück, der mit dem Übergang assoziiert ist. - Im Falle von dokumentübergreifenden (MPA) Übergängen:
- Ein
pageswap
Ereignis wird ausgelöst, wenn ein Dokument aufgrund einer Navigation entladen werden soll. Sein Ereignisobjekt (PageSwapEvent
) bietet Zugriff auf denViewTransition
über diePageSwapEvent.viewTransition
Eigenschaft als auch eineNavigationActivation
überPageSwapEvent.activation
mit Informationen über den Navigationstyp und die aktuellen und zukünftigen Dokument-Historieeinträge.Hinweis: Wenn die Navigation eine Cross-Origin-URL irgendwo in der Umleitungskette hat, gibt die
activation
Eigenschaftnull
zurück. - Ein
pagereveal
Ereignis wird ausgelöst, wenn ein Dokument erstmals gerendert wird, entweder beim Laden eines neuen Dokuments aus dem Netzwerk oder beim Aktivieren eines Dokuments (entweder aus dem bfcache oder prerender). Sein Ereignisobjekt (PageRevealEvent
) bietet Zugriff auf denViewTransition
über diePageRevealEvent.viewTransition
Eigenschaft.
- Ein
Lassen Sie uns einige Beispielcodes betrachten, um zu zeigen, wie diese Funktionen verwendet werden könnten.
Eine durch JavaScript kraftvolle benutzerdefinierte gleich dokumentierte (SPA) Transition
Das folgende JavaScript könnte verwendet werden, um eine kreisförmige Enthüllungsansichts-Transition zu erzeugen, die von der Position des Cursors des Benutzers beim Klicken ausgeht, wobei die Animation durch die Web Animations API bereitgestellt wird.
// Store the last click event
let lastClick;
addEventListener("click", (event) => (lastClick = event));
function spaNavigate(data) {
// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
updateTheDOMSomehow(data);
return;
}
// Get the click position, or fallback to the middle of the screen
const x = lastClick?.clientX ?? innerWidth / 2;
const y = lastClick?.clientY ?? innerHeight / 2;
// Get the distance to the furthest corner
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
);
// Create a transition:
const transition = document.startViewTransition(() => {
updateTheDOMSomehow(data);
});
// Wait for the pseudo-elements to be created:
transition.ready.then(() => {
// Animate the root's new view
document.documentElement.animate(
{
clipPath: [
`circle(0 at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
],
},
{
duration: 500,
easing: "ease-in",
// Specify which pseudo-element to animate
pseudoElement: "::view-transition-new(root)",
},
);
});
}
Diese Animation erfordert auch das folgende CSS, um die Standard-CSS-Animation auszuschalten und die alten und neuen Ansichts-Zustände daran zu hindern, in irgend einer Weise zu mischen (der neue Zustand "wischt" direkt über den alten Zustand, anstatt in ihn hinein zu überblenden):
::view-transition-image-pair(root) {
isolation: auto;
}
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
display: block;
}
Eine durch JavaScript kraftvolle benutzerdefinierte dokumentübergreifende (MPA) Transition
Das Liste der Chrome DevRel Teammitglieder Demo bietet eine grundlegende Sammlung von Teamprofilseiten und demonstriert, wie man die pageswap
und pagereveal
Ereignisse verwendet, um die ausgehenden und eingehenden Animationen einer dokumentübergreifenden View Transition basierend auf den "von" und "zu" URLs zu personalisieren.
Der pageswap
Ereignis-Listener sieht wie folgt aus. Dieser setzt View Transition Namen auf den Elementen auf der ausgehenden Seite, die auf die Profilseiten verlinken. Wenn von der Startseite zu einer Profilseite navigiert wird, werden benutzerdefinierte Animationen nur für das angeklickte Verknüpfungselement bereitgestellt.
window.addEventListener("pageswap", async (e) => {
// Only run this if an active view transition exists
if (e.viewTransition) {
const currentUrl = e.activation.from?.url
? new URL(e.activation.from.url)
: null;
const targetUrl = new URL(e.activation.entry.url);
// Going from profile page to homepage
// ~> The big img and title are the ones!
if (isProfilePage(currentUrl) && isHomePage(targetUrl)) {
// Set view-transition-name values on the elements to animate
document.querySelector(`#detail main h1`).style.viewTransitionName =
"name";
document.querySelector(`#detail main img`).style.viewTransitionName =
"avatar";
// Remove view-transition-names after snapshots have been taken
// Stops naming conflicts resulting from the page state persisting in BFCache
await e.viewTransition.finished;
document.querySelector(`#detail main h1`).style.viewTransitionName =
"none";
document.querySelector(`#detail main img`).style.viewTransitionName =
"none";
}
// Going to profile page
// ~> The clicked items are the ones!
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the elements to animate
document.querySelector(`#${profile} span`).style.viewTransitionName =
"name";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"avatar";
// Remove view-transition-names after snapshots have been taken
// Stops naming conflicts resulting from the page state persisting in BFCache
await e.viewTransition.finished;
document.querySelector(`#${profile} span`).style.viewTransitionName =
"none";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"none";
}
}
});
Hinweis:
Wir entfernen die view-transition-name
Werte, nachdem die Snapshots in jedem Fall aufgenommen wurden. Wenn wir sie gesetzt lassen würden, würden sie bei der Navigation im bfcache im Seitenstatus gespeichert bleiben. Wenn dann der Zurück-Button gedrückt würde, würde der pagereveal
Ereignishandler der Seite, zu der zurück navigiert wird, dann versuchen, dieselben view-transition-name
Werte auf andere Elemente zu setzen. Wenn mehrere Elemente denselben view-transition-name
gesetzt haben, wird die View Transition übersprungen.
Der pagereveal
Ereignis-Listener sieht wie folgt aus. Dieser funktioniert auf ähnliche Weise wie der pageswap
Ereignis-Listener, obwohl Sie daran denken sollten, dass wir hier die "zu" Animation für Seitenelemente auf der neuen Seite personalisieren.
window.addEventListener("pagereveal", async (e) => {
// If the "from" history entry does not exist, return
if (!navigation.activation.from) return;
// Only run this if an active view transition exists
if (e.viewTransition) {
const fromUrl = new URL(navigation.activation.from.url);
const currentUrl = new URL(navigation.activation.entry.url);
// Went from profile page to homepage
// ~> Set VT names on the relevant list item
if (isProfilePage(fromUrl) && isHomePage(currentUrl)) {
const profile = extractProfileNameFromUrl(fromUrl);
// Set view-transition-name values on the elements to animate
document.querySelector(`#${profile} span`).style.viewTransitionName =
"name";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"avatar";
// Remove names after snapshots have been taken
// so that we're ready for the next navigation
await e.viewTransition.ready;
document.querySelector(`#${profile} span`).style.viewTransitionName =
"none";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"none";
}
// Went to profile page
// ~> Set VT names on the main title and image
if (isProfilePage(currentUrl)) {
// Set view-transition-name values on the elements to animate
document.querySelector(`#detail main h1`).style.viewTransitionName =
"name";
document.querySelector(`#detail main img`).style.viewTransitionName =
"avatar";
// Remove names after snapshots have been taken
// so that we're ready for the next navigation
await e.viewTransition.ready;
document.querySelector(`#detail main h1`).style.viewTransitionName =
"none";
document.querySelector(`#detail main img`).style.viewTransitionName =
"none";
}
}
});
Stabilisieren des Seitenzustands, um dokumentübergreifende Transitionen konsistent zu machen
Vor dem Ausführen einer dokumentübergreifenden Transition möchten Sie idealerweise warten, bis der Zustand der Seite stabilisiert ist, und sich auf Renderblockierung verlassen, um sicherzustellen, dass:
- Kritische Stile geladen und angewendet werden.
- Kritische Skripte geladen und ausgeführt werden.
- Das HTML für die anfängliche Ansicht des Benutzers auf der Seite analysiert wurde, sodass es konsistent gerendert wird.
Stile werden standardmäßig renderblockiert, und Skripte können durch das blocking="render"
Attribut renderblockiert werden.
Um sicherzustellen, dass Ihr anfängliches HTML analysiert wurde und immer konsistent gerendert wird, bevor die Übergangsanimation ausgeführt wird, können Sie <link rel="expect">
verwenden. In diesem Element beinhalten Sie die folgenden Attribute:
rel="expect"
um anzugeben, dass Sie dieses<link>
Element verwenden möchten, um einige HTML-Inhalte auf der Seite renderblockiert zu verhindern.href="#element-id"
um die ID des Elements anzugeben, das Sie renderblockiert verhindern möchten.blocking="render"
um die angegebene HTML zu renderblockiert zu verhindern.
Lassen Sie uns untersuchen, wie das mit einem Beispiel HTML-Dokument aussieht:
<!doctype html>
<html lang="en">
<head>
<!-- This will be render-blocking by default -->
<link rel="stylesheet" href="style.css" />
<!-- Marking critical scripts as render blocking will
ensure they're run before the view transition is activated -->
<script async src="layout.js" blocking="render"></script>
<!-- Use rel="expect" and blocking="render" to ensure the
#lead-content element is visible and fully parsed before
activating the transition -->
<link rel="expect" href="#lead-content" blocking="render" />
</head>
<body>
<h1>Page title</h1>
<nav>...</nav>
<div id="lead-content">
<section id="first-section">The first section</section>
<section>The second section</section>
</div>
</body>
</html>
Das Ergebnis ist, dass das Dokument-Rendering blockiert wird, bis die Lead-Content-<div>
analysiert wurde, was eine konsistente Übergangsansicht gewährleistet.
Sie können auch ein media
Attribut auf <link rel="expect">
Elementen angeben. Zum Beispiel möchten Sie vielleicht das Rendering auf eine kleinere Menge von Inhalten blockieren, wenn die Seite auf einem Gerät mit schmalem Bildschirm geladen wird, als auf einem Gerät mit breitem Bildschirm. Das macht Sinn — auf einem Mobile wird weniger Inhalt sichtbar sein, wenn die Seite zuerst lädt, als im Fall eines Desktops.
Dies könnte mit dem folgenden HTML erreicht werden:
<link
rel="expect"
href="#lead-content"
blocking="render"
media="screen and (min-width: 641px)" />
<link
rel="expect"
href="#first-section"
blocking="render"
media="screen and (max-width: 640px)" />