用CSS 给《狂飙》做了4种转场

语言: CN / TW / HK

theme: channing-cyan

前言

最近《狂飙》大火,顺便蹭个热度,用CSS给狂飙做个转场动画。本文介绍了4种转场过渡效果,分别是水平擦除转场星型转场时钟转场自定义图形缩放转场

相信你肯定大有收获。

一个简单的渐变蒙版

CSS 蒙版允许您控制元素的显示情况。遮罩可以是图像或渐变。当蒙版应用于元素时,它充当一种映射。
遮罩可以使得元素部分被遮盖,从而产生半透明的样子。

下面的演示使用 CSS 遮罩将两图片交叉显示,呈现出淡入淡出。

jcode

第一个场景是高启强。第二个场景是 安欣,他直接位于第一个场景之上。在第二个场景中使用渐变蒙版使其左侧透明,从而将第一个场景显示出。

CSS中主要是定位和调整大小,以及设置场景图像,但要注意 .scene-2 上的 -webkit-mask-image

``` .wrapper { width: min(1000px, 100%); }

.scenes { position: relative; aspect-ratio: 2.4 / 1; }

.scene-1, .scene-2 { position: absolute; inset: 0; background-size: cover; }

.scene-1 { background-image: url(scene-1.jpg); }

.scene-2 { background-image: url(scene-2.jpg); -webkit-mask-image: linear-gradient(to right, transparent 33%, #fff 67%); } ```

-webkit-mask-image 上设置遮罩linear-gradient() ,表示从左到右的

  • 前三分之一是完全透明的,所以这部分场景是不可见的
  • 中间的三分之一从透明变为不透明的白色,场景逐渐淡入
  • 最后三分之一是完全不透明的白色,导致这部分场景完全可见

透明像素隐藏不透明像素显示。颜色甚至都不重要。任何颜色都可以。

另外,我使用的前缀为 -webkit-mask-image (所有主流浏览器均支持),但不使用 mask-image (目前仅 Firefox 和 Safari 可识别)。

.scene-2 { -webkit-mask-image: linear-gradient(to right, transparent 33%, #fff 67%); mask-image: linear-gradient(to right, transparent 33%, #fff 67%); }

水平擦除过渡转场

第一个场景过渡效果,即水平淡入淡出。

jcode

基本的 HTML 和 CSS 设置与上次相同。再一次,遮罩是一个 linear-gradient() ,从中间从 transparent 渐变到 #fff

那么淡入淡出是如何在场景中动画化的呢?

下方的可视化器。遮罩被拉伸到比实际场景更宽,然后动画水平滑动。

``` .scene-2 { background-image: url(scene-2.jpg); -webkit-mask-image: linear-gradient( to right, transparent 47.5%, #fff 52.5% ); -webkit-mask-size: 210%; -webkit-mask-position: left; }

/ 当.scenes 被聚焦或者移入的时候,在.scenes-2的这些样式激活/ .scenes:is(:hover, :focus) .scene-2 { -webkit-mask-position: right; transition: -webkit-mask-position 2s linear; } ```

遮罩的大小为 -webkit-mask-size: 210% 为场景提供了 100% 的宽度,

最终形成:开始完全透明 + 10% 的淡入淡出 + 另一个完全不透明

为了显示场景,我们将 -webkit-mask-position 的值设为 transition ,因此遮罩从 left 对齐变为 right 对齐。请注意, background-image 不会移动,只有遮罩会移动。

CSS 遮罩不仅遮罩了元素的背景,它还遮罩了整个元素及其中的所有内容

星形转场

接下来是星形转场,从中间淡出场景。注意,动画依赖于 CSS properties and values API

jcode

这次我们使用 radial-gradient() 作为遮罩。我们还需要以下方式处理动画。

定义 radial-gradient() 。然后我们可以对该自定义属性进行动画处理以对渐变进行动画处理。

但在此之前,我们需要使用 @property 注册自定义属性。

js @property --radius { syntax: '<percentage>'; inherits: true; initial-value: -5%; }

--radius 的自定义属性,它保存 percentage 值并且默认值为 -5% 。并使用简单的关键帧动画为 --radius 设置动画。

@keyframes scene-transition { to { --radius: 105%; } }

.scene-2 的 CSS组合在一起。

``` .scene-2 { background-image: url(scene-2.jpg); z-index: -1; -webkit-mask-image: radial-gradient( circle, #fff calc(var(--radius) - 5%), transparent calc(var(--radius) + 5%) ); }

.scenes:is(:hover, :focus) .scene-2 { z-index: 1; animation: scene-transition 2s linear forwards; } ```

radial-gradient() 中的颜色停止位置也是如此。是 --radius 值的 -5%+5% ,创建出渐变淡入淡出。

淡入淡出是 --radius 的值从 -5% 变为 105% 的原因。我们在开始时额外多出的 5% 确保所有像素都隐藏,然后在最后多出 5% 以确保所有像素都可见

但是这个 API 在 Firefox 和 Safari 中不起作用。我们可以将 .scene-2 设置 z-index: -1 ,将其隐藏在第一个场景后面,然后改成 z-index: 1 以将其显示在第一个场景之上。

时钟转场

jcode

我们使用 conic-gradient()angle 值设置动画。

``` @property --angle { syntax: ''; inherits: true; initial-value: -10deg; }

@keyframes scene-transition { to { --angle: 370deg; } }

.scene-2 { background-image: url(scene-2.jpg); z-index: -1; -webkit-mask-image: conic-gradient( #fff 0deg, #fff calc(var(--angle) - 10deg), transparent calc(var(--angle) + 10deg), transparent 360deg ), conic-gradient( transparent 340deg, #fff 360deg ); }

.scenes:is(:hover, :focus) .scene-2 { z-index: 1; animation: scene-transition 2s linear forwards; } ```

我们在 -webkit-mask-image 中使用了两个渐变。第一个 conic-gradient() 被动画化以创建时钟擦除效果,但它在其起点( 0deg 处)。渐变结合在一起为场景创建蒙版。

自定义图形缩放转场

jcode

.scene-2 的 CSS

``` @keyframes scene-transition { 25% { filter: brightness(100%); } 100% { filter: brightness(100%); -webkit-mask-size: 1800%; } }

.scene-2 { background-image: url(scene-2.jpg); filter: brightness(0%); -webkit-mask-image: url(jedi-crest.svg); -webkit-mask-size: 10%; -webkit-mask-position: center; -webkit-mask-repeat: no-repeat; }

.scenes:is(:hover, :focus) .scene-2 { animation: scene-transition 4s cubic-bezier(1, 0, 1, 1) forwards; } ```

这次没有渐变。相反, -webkit-mask-image 是一个 SVG,将 .scene-2 遮罩。遮罩位于场景的 center 中,大小为 10% 。添加 filter: brightness(0%) 会消除所有亮度,导致 SVG 完全变黑。

动画使用 cubic-bezier() 曲线,开始时非常慢,然后变得非常快。

-webkit-mask-size10%1800% 动画化,使得绝地 SVG 中间的狭窄部分变得足够大以覆盖整个场景。

filter: brightness()0%100% 动画,场景从黑色淡化回正常。这部分动画设置为在 -webkit-mask-size 完成生长之前在 25% 时间标记处结束。

全文完

谢谢!

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天

点击查看活动详情