您听到了消息吗? Google Chrome 111 将于2023年3月1日发布,除其他事项外,自从我第一次听到它以来,我一直在尝试尝试: View Transitions 。这是Google在W3C上提出的新API,目前是1st Working Draft。可以在this Explainer中找到它的非正式摘要,该摘要似乎是去年在Chrome Developers网站上发布的原始introductory article的最新版本。我强烈建议您阅读任何文档。
那么,视图过渡对什么有益?简而言之,它们允许添加动画页面过渡。 Although we already have several standard options to animate stuff on web pages (CSS Transitions, CSS Animations or the Web Animations API) and countless more options in particular JavaScript frameworks and libraries (Framer Motion for React, Vue Transitions, Svelte Transitions, Swup, Barba.js or Animate.css to name just a few ),网络仍然缺乏一个基于标准的通用,易于使用的解决方案,用于在页面之间或DOM-更新期间进行过渡。至少这就是Google工程师所说的话,我倾向于同意他们的看法。
在 Hotwire Turbo 世界中,尤其是关于整合过渡动画的几个discussions也发生了,并且出现了一些有前途的方法,即Turn project或transitions in Bridgetown。 Noel Rappin’s Modern Front-End book还有一个章节和一个有趣的article,但总的来说,坦率地说,这个话题仍然有些早期和探索性。
这是View Transitions提案。它可以改变Hotwire和其他人的情况吗?当然,这取决于许多事情,最重要的是,other browser vendors和整个社区的采用率以及W3C推荐草案曲目是否成功。但是我有一种直觉,是的,它可能会改变事物!
一个你好世界的例子
让我们看一个简单的例子。巧合的是,Jake Archibald在React,Svelte和Lit中创建了许多动画柜台的示例,因此,让我们尝试在Turbo中进行相同的构建!我将在Rauds应用程序上的Ruby上演示它,因为这是我最习惯的,但在任何其他支持涡轮增压的框架中都应该使用。
因此,我们将创建一个带有大胆的数字和链接的简单页面,该页面将使用Turbo Frame递增此数字。首先,我们将构建一个单孔页面,然后添加一个视图过渡动画。
涡轮框架需要路由它的请求,因此让我们先添加一条路线:
# config/routes.rb
Rails.application.routes.draw do
resources :counter, only: :index
end
相应的控制器(顺便说一句,”singular“ one)可以基本上保持空:
# app/controllers/counter_controller.rb
class CounterController < ApplicationController
def index; end
end
模板呈现<turbo-frame>
标签及其内部链接和计数器本身(这里使用了Slim模板语言和Tailwind造型,希望符号足够自我解释):
/ app/views/counter/index.html.slim
= turbo_frame_tag(:incrementing_counter)
- counter = params[:counter].to_i
= link_to "Increment", counter_index_path(counter: counter + 1),
class: "block p-2 bg-gray-100 active:bg-gray-200"
#counter.absolute.w-full.text-8xl.font-bold.text-center
= counter
这就是到目前为止的外观:Turbo提出请求并在单击链接时替换框架,并且没有触发动画(如下右下面板中可以看到):
现在,让我们添加视图过渡到涡轮框架。为此,我们需要使用override the default rendering function在koude1 event处理程序中使用一种使用视图过渡的自定义镜架:
// app/javascript/application.js
addEventListener("turbo:before-frame-render", (event) => {
if (document.startViewTransition) {
const originalRender = event.detail.render
event.detail.render = (currentElement, newElement) => {
document.startViewTransition(()=> originalRender(currentElement, newElement))
}
}
})
首先,处理程序代码检查浏览器是否支持视图过渡,如果是,则将原始渲染函数包含使用koude2函数。 这就是!是的,整页确实是默认情况下动画的,但是由于页面上的大多数元素要么是相同的(涡轮框架之外的元素),要么被相同外观的元素替换(例如,框架内的链接),因此练习只有计数器本身就感到有动画。看起来这样:
最后,我们可以自定义过渡。为了匹配上述示例,让S在过渡过程中旋转计数器。为此,我们需要利用文档中的here来利用命名的视图。每当我们使用CSS选择器选择屏幕的一部分并使用view-transition-name
属性命名,浏览器就会独立于所有其他部分独立于相应的屏幕区域。这样,我们可以在页面上的一个或多个元素进行动画,而不会影响页面的其余部分。
因此,让我们添加以下CSS到index
模板(Slim识别一个css:
块,该块刚刚呈现一个普通的<style>
标签):
/ app/views/counter/index.html.slim
/ (anywhere outside the Turbo Frame tag)
css:
/* (1) */
#counter {
view-transition-name: counter;
contain: layout;
}
/* (2) */
@keyframes rotate-out {
to {
transform: rotate(90deg);
}
}
@keyframes rotate-in {
from {
transform: rotate(-90deg);
}
}
/* (3) */
::view-transition-old(counter) {
animation-duration: 200ms;
animation-name: -ua-view-transition-fade-out, rotate-out;
}
::view-transition-new(counter) {
animation-duration: 200ms;
animation-name: -ua-view-transition-fade-in, rotate-in;
}
让我们分解此代码:
-
CSS选择器
#counter
匹配计数器div,view-transition-name
属性为屏幕的此区域命名,以查看过渡为counter
。此名称将在下面的动画声明中使用。目前必须在此处添加
clone
属性,原因是当前视图过渡实现的某些原因,必须设置为paint
或layout
。不过,计划从规范中删除这种限制,实际上我听说过在Chrome Canary中不需要它。 -
此处定义了旋转动画keyframes。请注意,尽管过渡还使用淡入淡入淡入和淡入淡出动画,但它们不必在此处定义,因为规格requires浏览器以
-ua-view-transition-fade-in/out
的名称实现它们。 -
此处配置了计数器的CSS animations(名为
counter
的视图过渡区域)。 CSS选择器是过渡期间的pseudo-elements automatically created。-old
伪元素代表了旧的DOM状态的屏幕截图,该屏幕截图应以某种方式消失或从视口上消失。
因此,总的来说,此代码选择了页面的一部分,在涡轮帧DOM更新期间与页面的其余部分独立于动画。在幕后,该页面其余部分的默认交叉抛光仍在进行,因为它的所有元素在视觉上都是相同的,因此不可见。结果看起来像这样:
一些最初的提示和技巧
这个适用于Turbo Drive访问吗?
肯定会做到这一点,而且实际上很容易!我们要做的就是定义与上文相同的事件处理程序,但是attach将其转移到koude17 event。默认情况下,我们将在Turbo Drive页面访问期间获得整个页面的交叉动画。
不要试图命名涡轮框架本身
使用涡轮框架视图过渡时,我首先尝试通过通过view-transition-name
属性命名整个涡轮框架元素为整个涡轮框架元素使用自定义动画。由于某种原因,这是行不通的,您最终会在控制台中获得非常隐秘且误导性的错误消息(是的i di di di d did 在CSS声明中具有contain
属性):
流产过渡。元素必须包含用于查看转换名称的油漆或布局:计数器
so,当使用自定义动画时,必须选择并命名框架内部的元素。
调试视图过渡
从技术上讲,视图过渡只是普通的CSS动画,因此它们可以是inspected,其中包括Dev工具中的动画面板。同样,在过渡期间的“元素”选项卡中可见自动创建的伪元素:
结论
我承认,我对新观点过渡API感到非常兴奋。我特别喜欢的事情包括以下内容:
- 令人惊讶的是将其插入Hotwire Turbo中,您可以免费获得默认的交叉效率过渡动画(在最新的类似镀铬的浏览器中,即)。
- 由于这是在浏览器中本地实现的,因此动画是高度优化和表现的。
- 视图过渡应允许(今天或将来)建立类似于those in Material Design的高度互动过渡。
- 也有一些初始 support for Multi-Page Applications ,这是个好消息,因为我们可以将CSS中的过渡动画带入我们的旧售价Alty Apps。
- IT should be possible使用导航API根据访问的方向使用不同的动画(也仍然是实验性的,并且支持不太受支持)。
我仍然担心的事情:
- 浏览器支持:Firefox团队evaluates it,Safari团队是silent。这将是日志运行,制作多填充可能是too difficult。对于过渡动画至关重要的网站,这仍然是不行的。
-
如果您不够小心,则过渡会感觉更流畅,但也会慢一点。原因是,当旧状态和新状态都呈现时,视图转换开始了动画。这意味着延迟出口动画直到有新内容可用,直到那段时间才能发生。另外,新状态的输入动画通常会延迟其外观。
这不是查看过渡本身的问题,而是一个更通用的问题。如果出口动画(例如,淡出淡出)在用户交互后立即开始(例如,单击链接),则有时用户必须凝视空白页面,直到抓取新页面内容,呈现,渲染并通过输入动画运行。尽管如此,对这种情况的某种支持(可能是定制装载机或骨架)还是不错的。
-
尾风支持:我认为当前的尾风语法不允许针对HTML文档连接的伪元素,因此我们必须诉诸自定义CSS(实际上这不是一个大问题)。
-
所有的过渡都针对整个页面,目前没有选项可以使两个组件(帧)完全独立地进行动画。可以找到有关范围过渡的最初建议。
总的来说,我喜欢此功能,希望它能够成熟并尽快得到更广泛的支持!