巧用 CSS 变量,实现动画函数复用,制作高级感拉满的网格动画 | 您所在的位置:网站首页 › js中变量不声明可以使用吗 › 巧用 CSS 变量,实现动画函数复用,制作高级感拉满的网格动画 |
本文将介绍一种基于 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,像是这样: 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 属性传入自定义变量。 我们再改造一下我们的 @keyframes: @keyframes move { 60%, 100% { transform: translate(var(--end)); background: var(--color); } }这一次,我们不需要通过 :nth-child() 去修改每一个 li 的 CSS,而是通过 HTML 元素的内联 style 属性,像是这样: 是的,每个 li 元素的 @keyframes 可以读取到每个 li 的 style 里面定义的不一样的 CSS 变量。 这样,我们就可以得到如下效果: 完整的代码,可以戳这里:CodePen Demo -- 巧用 CSS 变量,实现动画函数复用 实战演练下面我们实战演练一下,上一点难度。 在很久之前,我们实现过这样一个动画效果: 这个动画效果的实现方式在于: 父级元素实现一个 rotateZ(360deg) 的匀速动画子级元素实现一个反向的 rotateZ(-360deg) 的匀速动画给父级元素添加一个 rotateX(40deg) 的动画由于父容器和子容器同时相反向旋转,所以子元素看上去其实和没有旋转是一样的。但是由于又添加了一个 rotateX(40deg) 动画,因此看上去就会有这样一种 3D 效果。 在之前,我们的代码是这样的: .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); } }可以看到,我们这里实现了两个动画效果: @keyframes rotate {} 父容器的旋转动画@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动画正反旋转相消 图片旋转配合容器旋转下面,我们再来尝试一个有意思的动画效果,图片旋转配合容器旋转。 在上述的基础上,如果我们把子元素,改成图片,整个效果就会有意思不少,我们稍微改变一点点代码: 这里,我们做了什么事情呢? 去掉了 3D 效果给外层容器加了边框内层图片基于父容器绝对定位,水平垂直居中内外两层容器反向旋转 360° 动画这样,我们就能看到,虽然内外两层容器同时在进行相反方向的旋转 360° 动画,但是内部的图片其实是静止不动的! 效果如下: 由于,内部图片的大小为父容器的 100%,所以在旋转过程中,父容器会有明显的无法包裹住整个图片的情况。 这个很好解决,我们只需要把图片大小调整大一点: // ... 其它代码不变 .rotate { width: 150%; height: 150%; } .rotate { --degZ: 360deg; animation: rotate 5s linear infinite; }正常而言,对于正方形容器,内部图片设置到 141% 即可满足父容器旋转过程,可以一直包裹住图片的效果。那么,我们就能得到这样一种效果: 完整的代码,你可以戳这里:CodePen Demo -- Css动画正反旋转相消 Grid 布局配合正反旋转动画当然,上述当只有一个容器的时候,整个动画效果还不够震撼。 如果我们可以把这个效果融合进整个布局的动画之中,整个效果又会完全不一样。 在 Rotating gallery with CSS scroll-driven animations 这篇文章中,作者提供了一种非常巧妙的思路,将 Grid 布局动画与上述动画效果巧妙的结合了起来。 首先,我们利用 Grid 布局,实现这样一个简单的网格布局结构: 效果如下: 接下来,我们要做的,就是结合上面的知识点,容器滚动起来,图片反向滚动起来,配合一些 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 订阅收藏。 如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。 |
CopyRight 2018-2019 实验室设备网 版权所有 |