关于前端:巧用-CSS-变量实现动画函数复用制作高级感拉满的网格动画

33次阅读

共计 5528 个字符,预计需要花费 14 分钟才能阅读完成。

本文将介绍一种基于 CSS 变量技巧,通过正当应用 CSS 变量,实现 CSS 动画 @keyframes 的复用。

CSS 自定义变量

CSS 自定义变量大家应该都比拟相熟了,曾经不能算是新常识了,疾速过一遍。

CSS 自定义变量(CSS Variable),在之前也叫做 CSS 自定义属性,其应用形式如下:

// 申明一个变量::root{--bgColor: #000;}

这里咱们借助了下面 #12、结构性伪类 中的 :root{} 伪类,在全局 :root{} 伪类中定义了一个 CSS 变量,取名为 --bgColor

定义完了之后则是应用,假如我要设置一个 div 的背景色为彩色:

.main{background:var(--bgColor);
}

这里,咱们在须要应用之前定义变量的中央,通过 var(定义的变量名) 来调用。

在 @keyframes 中应用 CSS 变量

OK,回归咱们的正题。 巧用 CSS 变量,实现动画函数复用

假如,咱们当初有多个元素,须要实现一个位移动画,从地位 A 位移到 地位 B,地位 A 雷同,然而地位 B 不一样,像是这样:

失常而言,因为起点不一样,咱们可能须要实现 3 个不一样的 @keyframes,像是这样:

<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>
li:nth-child(1) {animation: move1 2s linear;}
li:nth-child(2) {animation: move2 2s linear;}
li:nth-child(3) {animation: move3 2s linear;}

@keyframes move1 {
    60%,
    100% {transform: translate(150px);
    }
}
@keyframes move2 {
    60%,
    100% {transform: translate(120px);
    }
}
@keyframes move3 {
    60%,
    100% {transform: translate(200px);
    }
}

这个代码有问题吗?没有。

然而,咱们能够利用 CSS 变量,让它变得更为简洁,咱们革新一下 @keyframes 代码,将固定的位移值,变成一个变量:

@keyframes move {
    60%,
    100% {transform: translate(var(--dis));
    }
}

因为 CSS 变量是存在作用域的,咱们能够通过 CSS 变量的形式,给每一个 li 定义一个不同的 --dis 变量,像是这样:

li:nth-child(1) {--dis: 150px;}
li:nth-child(2) {--dis: 120px;}
li:nth-child(3) {--dis: 200px;}

这样,尽管动画的完结点不一样,然而咱们利用 CSS 变量,复用了同一个 @keyframes 函数:

通过内联 style 属性传入自定义变量

除了通过在 <style> 内传入不同的自定义变量,咱们还能够通过内联 style 属性传入自定义变量。

咱们再革新一下咱们的 @keyframes:

@keyframes move {
    60%,
    100% {transform: translate(var(--end));
        background: var(--color);
    }
}

这一次,咱们不须要通过 :nth-child() 去批改每一个 li 的 CSS,而是通过 HTML 元素的内联 style 属性,像是这样:

<ul>
    <li style="--end: 150px; --color: red;"></li>
    <li style="--end: 200px; --color: blue;"></li>
    <li style="--end: 120px; --color: green;"></li>
</ul>

是的,每个 li 元素的 @keyframes 能够读取到每个 li 的 style 外面定义的不一样的 CSS 变量。

这样,咱们就能够失去如下成果:

残缺的代码,能够戳这里:CodePen Demo — 巧用 CSS 变量,实现动画函数复用

实战演练

上面咱们实战演练一下,上一点难度。

在很久之前,咱们实现过这样一个动画成果:

这个动画成果的实现形式在于:

  1. 父级元素实现一个 rotateZ(360deg) 的匀速动画
  2. 子级元素实现一个反向的 rotateZ(-360deg) 的匀速动画
  3. 给父级元素增加一个 rotateX(40deg) 的动画

因为父容器和子容器同时相同向旋转,所以子元素看上去其实和没有旋转是一样的。然而因为又增加了一个 rotateX(40deg) 动画,因而看上去就会有这样一种 3D 成果。

在之前,咱们的代码是这样的:

<div class="reverseRotate">
    <div class="rotate">
    </div>
</div>
.rotate {animation: rotate 5s linear infinite;}
.reverseRotate {animation: reverseRotate 5s linear infinite;}
@keyframes rotate {
    0% {transform: rotateX(0deg) rotateZ(0deg);
    }
    50% {transform: rotateX(40deg) rotateZ(180deg);
    }
    100% {transform: rotateX(0deg) rotateZ(360deg);
    }
}
@keyframes reverseRotate {
    0% {transform: rotateZ(0deg);
    }
    100% {transform: rotateZ(-360deg);
    }
}

能够看到,咱们这里实现了两个动画成果:

  1. @keyframes rotate {} 父容器的旋转动画
  2. @keyframes reverseRotate {} 子容器的旋转动画

其实,这里,使用明天的技巧,咱们能够把两个动画合成为一个,利用 CSS 自定义变量进行管制。革新后更简洁的 CSS 代码如下:

.rotate {
    --degZ: 360deg;
    --degZMiddle: 180deg;
    --degX: 30deg;
    animation: rotate 5s linear infinite; 
}

.reverseRotate {
    --degZ: -360deg;
    --degZMiddle: -180deg;
    --degX: 0;
    animation: rotate 5s linear infinite; 
}

@keyframes rotate {
    0% {transform: rotateX(0deg) rotateZ(0deg);
    }
    50% {transform: rotateX(var(--degX)) rotateZ(var(--degZMiddle));
    }
    100% {transform: rotateX(0deg) rotateZ(var(--degZ));
    }
}

是的,咱们能够失去同样的成果!

残缺的代码,你能够戳这里:CodePen DEMO — Css 动画正反旋转相消

图片旋转配合容器旋转

上面,咱们再来尝试一个有意思的动画成果,图片旋转配合容器旋转。

在上述的根底上,如果咱们把子元素,改成图片,整个成果就会有意思不少,咱们略微扭转一点点代码:

<div class="reverseRotate">
    <img class="rotate" src="https://picsum.photos/1000/1000?random=5" alt="">
</div>
.rotate,
.reverseRotate {
    width: 60vh;
    height: 60vh;
}
.reverseRotate {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border: 3px solid #999;
    overflow: hidden;
}

.rotate {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100%;
    height: 100%;
}

.rotate {
    --degZ: 360deg;
    animation: rotate 5s linear infinite; 
}

.reverseRotate {
    --degZ: -360deg;
    animation: rotate 5s linear infinite; 
}

@keyframes rotate {
    0% {transform: translate(-50%, -50%) rotateZ(0deg);
    }
    100% {transform: translate(-50%, -50%) rotateZ(var(--degZ));
    }
}

这里,咱们做了什么事件呢?

  1. 去掉了 3D 成果
  2. 给外层容器加了边框
  3. 内层图片基于父容器相对定位,程度垂直居中
  4. 内外两层容器反向旋转 360° 动画

这样,咱们就能看到,尽管内外两层容器同时在进行相同方向的旋转 360° 动画,然而外部的图片其实是静止不动的!

成果如下:

因为,外部图片的大小为父容器的 100%,所以在旋转过程中,父容器会有显著的无奈包裹住整个图片的状况。

这个很好解决,咱们只须要把图片大小调整大一点:

// ... 其它代码不变
.rotate {
    width: 150%;
    height: 150%;
}
.rotate {
    --degZ: 360deg;
    animation: rotate 5s linear infinite; 
}

失常而言,对于正方形容器,外部图片设置到 141% 即可满足父容器旋转过程,能够始终包裹住图片的成果。那么,咱们就能失去这样一种成果:

残缺的代码,你能够戳这里:CodePen Demo — Css 动画正反旋转相消

Gird 布局配合正反旋转动画

当然,上述当只有一个容器的时候,整个动画成果还不够震撼。

如果咱们能够把这个成果交融进整个布局的动画之中,整个成果又会齐全不一样。

在 Rotating gallery with CSS scroll-driven animations 这篇文章中,作者提供了一种十分奇妙的思路,将 Grid 布局动画与上述动画成果奇妙的联合了起来。

首先,咱们利用 Gird 布局,实现这样一个简略的网格布局构造:

<div class="container">
  <div class="A">
      <img src="https://picsum.photos/600/600?random=1" alt=""></div>
  <div class="B">
      <img src="https://picsum.photos/600/600?random=2" alt=""></div>
  <div class="C">
      <img src="https://picsum.photos/600/600?random=3" alt=""></div>
  <div class="D">
      <img src="https://picsum.photos/600/600?random=4" alt=""></div>
  <div class="E">
      <img src="https://picsum.photos/600/600?random=5" alt=""></div>
</div>
.container {
    width: 60vmin;
    height: 60vmin;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr 1fr 1fr;
    gap: 4px;
    grid-template-areas:
        "E B B"
        "E A C"
        "D D C";
}
.container > div {
    border: 3px solid #431312;
    border-radius: 5px;
}

.A {grid-area: A;}
.B {grid-area: B;}
.C {grid-area: C;}
.D {grid-area: D;}
.E {grid-area: E;}

成果如下:

接下来,咱们要做的,就是联合下面的知识点,容器滚动起来,图片反向滚动起来,配合一些 tranfrom 变换。

有了下面的铺垫,上面的新增的代码就十分好了解了:

.container > div img {
    --scale: 1;
    --rotation: -360deg;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 260%;
    height: 260%;
    object-fit: cover;
    object-position: center;
}
.container,
.container > div img {animation: 10s scale-up both ease-in-out infinite alternate;}
@keyframes scale-up {
    0% {transform: translate(-50%, -50%) scale(var(--scale)) rotate(0deg);
    }
    100% {transform: translate(-50%, -50%) scale(1) rotate(var(--rotation));    
    }
}

这样,咱们就失去了一个高级感拉满的网格旋转动画:

留神,这里咱们仍旧是通过 CSS 自定义变量,在不同元素间,复用了同一个动画 @keyframes 函数。

残缺的代码,你能够戳这里:CodePen Demo — Grid 图片旋转动画 & 应用 CSS 变量复用动画函数

最初

好了,本文到此结束,心愿本文对你有所帮忙 :)

想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 — iCSS 前端趣闻 😄

更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。

如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

正文完
 0