This is the 7th day of my participation in the August Text Challenge.More challenges in August

preface

When an app opens a page, it sometimes sees an animation where some elements of the current page jump to the next page, similar to the following:

So is there any way to achieve the animation effect similar to the app side page switch? After some exploration, Google Chrome already provides an experimental API like this:

documentTransition
Copy the code

It is a proposal for a new scripting API that allows the use of a simple set of transition animations in both single-page applications (SPA) and multi-page applications (MPAs). This feature is inspired by the transitions outlined in the Material Design principles. The goal is to support transitions similar to Android Activity Transitions.

Enable the API function in the browser

This feature needs to be manually enabled because it is an experimental function. Type in your browser

chrome://flags/#document-transition
Copy the code

Then set the documentTransition to Enabled.

After setting it up, restart the browser, open the console, and type:

'documentTransition' in document
Copy the code

The result prints true, indicating that our browser has successfully enabled the experimental function API.

What do you make of this API

The API proposal can be divided into two parts: root transition and shared Element transition.

Root transition

Root conversion can be understood as the animated transition effect of the “page” at load time, such as the iOS side click to jump to the next page, the next page is pushed from right to left. The following code implements this effect (note: the effect is quite different from the APP, the overall effect is that you can see the “page” is pushed in from right to left, please run the code to see the effect in the browser) :

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>RootTransition sample</title>
  </head>
  <style>
    .list {
      height: 100vh;
    }
    .details {
      height: 100vh;
      background-color: aquamarine;
    }
    .hide {
      display: none;
    }
  </style>
  <body>
    <div class="list">List of pp.<button id="btn">Click on the details page</button>
    </div>
    <div class="details hide">Details page</div>
    <script>
      const btn = document.querySelector('#btn')
      const details = document.querySelector('.details')
      const list = document.querySelector('.list')
      btn.addEventListener('click'.() = > {
        navigateToDetailsPage()
      })
      async function navigateToDetailsPage() {
        await document.documentTransition.prepare({
          rootTransition: "cover-left"}); details.classList.remove('hide')
        list.classList.add('hide')
        document.documentTransition.start();
      }
    </script>
  </body>
</html>

Copy the code

This is an example of root transition. Its usage model can be summarized as follows:

NavigateToSettingsPage () {navigateToSettingsPage() { To prepare await animation document. DocumentTransition. Prepare ({rootTransition: 'cover - left', / / "page" switching effect}); UpdateDOMForNextPage (); / / call the start start animation await the document. The documentTransition. Start (); // End of animation}Copy the code

Supported animation effects

RootTransition supports the following properties:

  • reveal-left: Slides the old content from the center to the specified direction to display the new content.
  • reveal-right
  • reveal-up
  • reveal-down
  • cover-left: New content slides from the edge in the specified direction to overwrite old content.
  • cover-right
  • cover-up
  • cover-down
  • explode: Old content “explodes” by growing and becoming more transparent and revealing new content.
  • implode: New content will implode, shrinking from the big side, becoming opaque, transforming old content.

Click here to see the effect of each property online.

Shared Element Transition

Taking the GIF at the beginning of the article, the shared element is the user’s profile picture and name. It can be seen that these two elements are always visible from the current page to the next page after loading, and there is a smooth transition effect from the display position size of the current page to the display position size of the next page.

How to use shared Elements

async function navigateToSettingsPage() {

  await document.documentTransition.prepare({
    rootTransition: 'cover-up',
    sharedElements: [element1, element2, element3],
  });

  // updateDOM

  await document.documentTransition.start({
    sharedElements: [element1, element4, element5],
  });

}
Copy the code

SharedElements is an array that holds elements shared across pages, which in the GIF example is the DOM that holds the user’s avatar and name. Note that:

  1. The sharedElements property is set in both the prepare and start methods in a one-to-one relationship. For example, when element2 switches to “Next page,” it transitions to where Element4 is.
  2. Contain: paint; contain: paint; contain: paint; This property also ensures that descendants of an element are not displayed if it is not visible outside the window or for other reasons. See: contain

Multi-page application

The code example mentioned above is for single-page applications. For multi-page applications, there is no relevant implementation API at present. You can pay attention to the progress of this issue

A complete example

The following code is used to implement an example, the effect is shown as follows:

Complete code:

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, </ > <title>rootTransition example </title> </head> <style> body{margin:0}. Flex-center {display:flex; align-items:center; justify-content:center}.list{height:100vh}.details{height:100vh}.hide{display:none! important}.card{display:flex; align-items:center; margin:0 20px; box-shadow:0 0 50px #ccc; border-radius:12px; overflow:hidden}.card .desc{font-size:18px; color:#333; font-weight:bold; margin-left:20px}.details-desc{font-size:22px; color:limegreen}.list{display:flex; flex-direction:column; justify-content:center}.button-wrap{margin-top:20px; text-align:center}.back-btn{display:inline-block; width:100px; height:40px}.details-cover{display:block; width:100%}.details-desc{position:absolute; right:20px; top:20px}.cover,.details-cover,.desc,.details-desc{contain:paint} </style> <body> <div class="list"> <div class="card"> <img class="cover" src="http://p1-q.mafengwo.net/s18/M00/52/27/CoUBYGDMNO-AOlK4AAVHKFDW8_Y808.jpg?imageMogr2%2Fthumbnail%2F%21220x150r%2Fst Rip %2Fgravity%2FCenter%2Fcrop%2F%21220x150%2Fquality%2F90" /> <span class="desc"> </span> <div > <div Class ="button-wrap"> <button ID =" BTN "> </button> </div> <div class="details hide"> <div> <div style="position: relative;" > <img class="details-cover" src="http://p1-q.mafengwo.net/s18/M00/52/27/CoUBYGDMNO-AOlK4AAVHKFDW8_Y808.jpg?imageMogr2%2Fthumbnail%2F%21220x150r%2Fst Rip %2Fgravity%2FCenter%2Fcrop%2F%21220x150%2Fquality%2F90" /> <div class="details-desc"> <div > <div Class ="button-wrap"> <button class="back-btn"> returns </button> </div> </div> <script> const BTN = document.querySelector('#btn') const details = document.querySelector('.details') const list = document.querySelector('.list') const backBtn = document.querySelector('.back-btn') const cover = document.querySelector('.cover') const desc = document.querySelector('.desc') const detailsCover = document.querySelector('.details-cover') const detailsDesc = document.querySelector('.details-desc') btn.addEventListener('click', () => { navigateToDetailsPage() }, false) backBtn.addEventListener('click', () => { showList() }, false) async function navigateToDetailsPage() { await document.documentTransition.prepare({ rootTransition: "cover-up", sharedElements: [ cover, desc ] }); details.classList.remove('hide') list.classList.add('hide') document.documentTransition.start({ sharedElements: [ detailsCover, detailsDesc ] }); } async function showList() { await document.documentTransition.prepare({ rootTransition: "implode", sharedElements: [ detailsCover, detailsDesc ] }); details.classList.add("hide"); list.classList.remove("hide"); await document.documentTransition.start({ sharedElements: [ cover, desc ] }); } </script> </body> </html>Copy the code

Refer to the link

Use the shared element conversion API for smooth and simple page conversion

Shared Element Transitions