使用API​​ ViewTransition创建交易
#javascript #css #前端 #braziliandevs

在这篇文章中,我将谈论一个非常酷的API,很少有人在评论:视图过渡。

在文本中有几个链接,单击它们可以访问浏览器中的实现。


什么是

API View Transition旨在使动物和视觉效果的创造更有效。使用它的好处之一是,它允许您在页面和元素状态之间变得更柔和的交易。

在Google Chrome 76上, paint Holding :闪烁的白色白色在用户更改并且整体实现时发生的,并且在屏幕上呈现了整个争论(绘制)。但是,某些变化仍然突然发生。

尽管使用此API在动画和交易方面带来了好处,但必须考虑可能的可访问性和可用性问题。在屏幕读取器中,两个不同状态的组成可能会引起 aria-wai 的问题。


使用新的API创建交易

要启动交易,只需在document.startViewTransition函数中执行礼物的更改即可。当更改HTML礼物的那一刻,浏览器将在HTML结构的顶部创建伪元素,该元素将在交易结束后将其删除。

document.startViewTransition(() => {
    document.body.innerHTML = `<your code>`;
});

伪rvore

由于该文档捕获了要修改的新旧状态和旧状态,因此创建了Abiaoqian结构3:

html
|_::view-transition
  ├─ ::view-transition-group(name)
  │  └─ ::view-transition-image-pair(name)
  │     ├─ ::view-transition-old(name)
  │     └─ ::view-transition-new(name)
  └─ …Other groups…


其中每个功能的功能:

描述£o 的元素
pseudoelemento
:: View-Transition 堆叠将遭受交易的每个元素的组
:: view-transition-group 分组遭受交易的元素的状态
:: view-transition-image-pair 存储每个状态的图像:旧和新
:: View-Transition Old 存储事务元素的状态(旧屏幕截图)
:: View-Transition-New ã存储状态(新屏幕截图)的元素,将更新

padrã£o,transiã§oo将拥有efeito de fade:当元素褪色并在该位置出现另一个元素时。


交易的工作方式

执行的交易步骤没有错误或中断:

  1. koude1被调用并返回接口koude2;
  2. 捕获了Panigan的当前状态; <​​/li>
  3. renderiza
  4. 执行步骤1的回调。他有责任进行更改;
  5. a 承诺 koude3已实现。它可以用于您知道何时更新礼物的更改;
  6. 捕获步骤4的更改后,Panigan的新状态; <​​/li>
  7. 伪元是在padga的根部创建的(在<html>中);
  8. 步骤2状态适用于伪校;
  9. a 承诺 koude5已实现。它可以用来识别何时准备开始交易(以下将有一个示例)
  10. 交易发生在伪元之间;
  11. A Promise koude6实现了。

创建简单的交易

让我们从非常简单的例子开始,以促进理解,不是吗? ð

function changePage(data) {
    // Altera o conteúdo sem o uso das transições caso o navegador
    // não suporte a operação
    if (!document.startViewTransition) {
        changeContentPage(data);
        return;
    }

    document.startViewTransition(() => changeContentPage(data));
}

这样,我们将获得以下结果:

只是看,这是超级幻想!而且您可以改进。让我们使用CSS进行动画。

::view-transition-old(root) {
    animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
        300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}

::view-transition-new(root) {
    animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
        300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

@keyframes fade-in {
    from { opacity: 0; }
}

@keyframes fade-out {
    to { opacity: 0; }
}

@keyframes slide-from-right {
    from { transform: translateX(30px); }
}

@keyframes slide-to-left {
    to { transform: translateX(-30px); }
}

这是新结果:

不是一切。您可以自由选择要遭受过渡的要素。 ð


与母亲元素进行交易

两个元素之间的创建遵循与以前的示例相同的模式。但是,要进行此类交易,您需要使用属性:koud7命名CSS元素。因此,浏览器将创建一个新的伪级,这些伪验到从一个位置转移到另一个位置。想知道更多?看看这个很酷的例子。

检查我们是否命名了遭受交易的交易

#header-menu {
  view-transition-name: header-menu;
}
#first {
  view-transition-name: el-first;
}
#second {
  view-transition-name: el-second;
}

我们还更改了元素的交易方式#first#second

::view-transition-old(el-first) {
  animation: scale-old 3s both ease-in-out;
}
::view-transition-new(el-first) {
  animation: scale-new 3s both ease-in-out;
}

/* --------------------------------------------------- */

::view-transition-old(el-second) {
  animation: back-in-up 3s;
}
::view-transition-new(el-second) {
  animation: back-in-down 3s;
}

很酷,不是吗?有时我们需要处理更复杂的动物,因此担心调试很酷。


debugando transiã§ãµEs

不是每个人都喜欢测试,但有必要

在本节中,我们将学习如何在您的网站上调试CSS动物。

为此,只需打开DevTools ( f12 ),然后选择“ Animations ”选项卡即可访问您的动物站点。通过单击“ 暂停”按钮,您可以停止交易,检查属性,尝试新的修改。

非常简单。您还可以检查性能并效仿其他设备,减少动画等。


在页面之间创建transaion(Spa-单页应用程序)

您可以轻松地更改pânão或文档。但是专心:这位母亲都是水疗中心独有的(至少目前为止)。

遵循一个顽皮的例子(只有名称​​ renata p¢mela )。

这很酷,但是让我们转到代码某些部分的评论并了解更多?

在此事件中,该站点的所有导航将被拦截以捕获当前的URL和目的地。命名房屋要素很重要。

navigation.addEventListener('navigate', (event) => {
    const toUrl = new URL(event.destination.url);
    if (location.origin !== toUrl.origin) return;

    const fromUrl = new URL(location.pathname, location.href);

    event.intercept({
        async handler() {
            onLinkNavigate(toUrl, fromUrl);
        }
    })
});

此拉伸是可选的。您可以将其更改为任何功能,并在Anchor类型的元素中使用onclick事件来调用它。

在此阶段,将使用getPage函数捕获目标PADGA的遏制(使用API​​ fetch执行申请)

async function onLinkNavigate(toUrl, fromUrl) {
    const response = await getPage(toUrl.href);

    ...
}

仍然在koud13中,我们有以下方法可以捕获所选舞者的 * card * *,并任命了 html elements 。执行过程中的名称是必要的,因为não é possível ter dois ou mais elementos具有相同的view-transition-name

/**
 * @param {{ personImage: HTMLImageElement, personName: HTMLDivElement }} elementsTarget
 */
function defineViewTransitionName(elementsTarget) {
    elementsTarget.personImage.classList.add('person-image');
    elementsTarget.personName.classList.add('person-name');
}

async function onLinkNavigate(toUrl, fromUrl) {
    ...

    if (toUrl.pathname.startsWith('/dancers')) {
        elementsTarget = getTargetElements(toUrl);
        if (elementsTarget) defineViewTransitionName(elementsTarget);
    }

    ...
}

apons确定和任命了元素,我们开始替换所有包含新p的古老的koud15。

async function onLinkNavigate(toUrl, fromUrl) {

    ...

    const transition = document.startViewTransition(() => {
        document.body.innerHTML = response;

            /**
             * Se a requisição for de /dancers/* para /index.html
             * então nomearemos o card da dançarina
             */
        if (fromUrl.pathname.startsWith('/dancers')) {
            elementsTarget = getTargetElements(fromUrl);
            if (elementsTarget) defineViewTransitionName(elementsTarget);
        }
    });

    transition.finished.then(() => {
        if (elementsTarget) {
            elementsTarget.personImage.classList.remove('person-image');
            elementsTarget.personName.classList.remove('person-name');
        }
    });

    ...

}

交易结束后,我们将删除定义view-transition-name属性的类以避免重复。

简单,不是吗? ð

,但我们可以做更多的事情。


使用JavaScript创建交易

已经结束了,您已经结束了吗? nop !!!

在最后一个示例中,我们将看到如何使用JavaScript制作动画。

正如我们之前看到的,当过渡准备启动时,将实现 Promise transition.ready。在其中,我们添加了个性化动画。在此 Promise中执行交易很重要,因为这是浏览器捕获两个必要状态(新的和旧的)并制成组成的时刻。

在上面的示例中,我们使用本机Api Element.animate,因为它为伪验提供了必要的支持。

transition.ready.then(() => {
    document.documentElement.animate(
      [
        { transform: "rotate(0) scale(1)" },
        { transform: "rotate(360deg) scale(0)" },
      ],
      {
        duration: 1500,
        easing: "cubic-bezier(0.68,-0.55,0.27,1.55)",
        pseudoElement: "::view-transition-old(image)",
      }
    );

    document.documentElement.animate(
      {
        clipPath: [`circle(0 at 100px 100px)`, `circle(200px at 100px 100px)`],
      },
      {
        duration: 1500,
        easing: "ease-in",
        pseudoElement: "::view-transition-new(image)",
      }
    );
  });

使用框架ð

如果您使用一些前端框架,也可以使用Koud18。以下是其中一些例子。

VUE JS
这里的关键是©`nextTick',一旦更新礼物,它就会实现承诺。 [检查一个示例。](https://bit.ly/44wpgwr)
Svelte
与Vue非常相似,但整体等待下一个更改为©tick。 [检查一个示例。](https://svelte.dev/repl/84CFFC3241514C1581BF951BF951BDF818DEF?venion = 3.55.1))
lit
关键是诺言`this.updatecomplete`,在更新礼物后履行承诺。 [检查一个示例。](https://shorturl.at/kcp7)
Angular
使用`applicationref.tick`。 [conferir um exemplo。](https://stackblitz.com/edit/angular-bp4pvy?file=src%2fmain.ts)
react
使用`flushsync',请小心返回的承诺。 [检查一个示例。](https://codesandbox.io/s/nervous-mclaren-j8v8y0?file=/src/app/app.tsx)

aplicando接口无打字稿ð

正如最近的资源(今天2023-08-03)一样,大多数发布者都不认识API。因此,如果您使用Typescript,只需将下面的代码添加到koud19(或在 tsconfig.json on compilerOptions.typeRoots中输入类型文件

export {};

interface ViewTransition {
  /**
   * A promise that fulfills when the promise returned by updateCallback fulfills,
     * or rejects when it rejects.
   */
  readonly updateCallbackDone: Promise<undefined>,

  /**
   * A promise that fulfills once the pseudo-elements for the transition are created,
   * and the animation is about to start.
   * It rejects if the transition cannot begin. This can be due to misconfiguration,
   * such as duplicate 'view-transition-name’s, or if updateCallbackDone returns a
     * rejected promise.
   * The point that ready fulfills is the ideal opportunity to animate the view
     * transition pseudo-elements with the Web Animation API.
   */
  readonly ready: Promise<undefined>,

  /**
   * A promise that fulfills once the end state is fully visible and interactive to
     * the user.
   * It only rejects if updateCallback returns a rejected promise, as this indicates
     * the end state wasn’t created.
   * Otherwise, if a transition fails to begin, or is skipped (by skipTransition()),
   * the end state is still reached, so finished fulfills.
   */
  readonly finished: Promise<undefined>,

  /**
   * Immediately finish the transition, or prevent it starting.
   * This never prevents updateCallback being called, as the DOM change
   * is independent of the transition
   * If this is called before ready resolves, ready will reject.
   * If finished hasn’t resolved, it will fulfill or reject along with
   * updateCallbackDone.
   */
  skipTransition: () => void,
}

type UpdateCallback = null|Promise<any>;

declare global {
  interface Document {
    startViewTransition: (updateCallback: ) => ViewTransition;
  }
}

反思

铬。眨眼:渲染器/core/view_tsition。 Github,C2 Dispondãvelem:<https://github.com/chromium/chromium/tree/4817833c534a72d50606e5f97d1e003f5885494d/third_party/blink/renderer/core/view_transition>。 Aceso EM:05以前。 2023。

W3C。 CSS查看过渡模块级别1。W3C,2012年。Disponãvelem:<https://www.w3.org/TR/css-view-transitions-1/>。 Acesso EM:05以前。 2023。

wicg。查看过渡解释器。 Github,2021年。处置:<https://github.com/WICG/view-transitions/blob/main/explainer.md>。访问:05以前。 2023.

我可以使用。查看过渡。我可以使用[S.D.]。 Disponãvelem:<https://caniuse.com/view-transitions>。 Acesso EM:05以前。 2023。


fim! ð

Homem soltando fogos de artifício porque que você chegou ao fim

喜欢??你不喜欢吗?您有任何主题吗?

给我留言要了解更多。

我希望这是您的成绩。 ð