likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 20

前言

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

相信你肯定大有收获。

一个简单的渐变蒙版

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

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

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

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%);
}

水平擦除过渡转场

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

基本的 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

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

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

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

@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 以将其显示在第一个场景之上。

时钟转场

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

@property --angle {
  syntax: '<angle>';
  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 处)。渐变结合在一起为场景创建蒙版。

自定义图形缩放转场

.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% 时间标记处结束。

全文完

谢谢!

点击查看活动详情

转载自:https://juejin.cn/post/7200214412787417144
评论
请登录