锦绣山河网

【一个让你停不下来的动效】——难道不来瞅瞅?(含源码+思路)

【一个让你停不下来的动效】——难道不来瞅瞅?(含源码+思路)

在这里插入图片描述
在这里插入图片描述



个人名片:

🐼作者简介:一名大一在校生
🐻‍❄️个人主页:小新爱学习.
🐼个人WeChat:hmmwx53
🕊️系列专栏:零基础学java----- 重识c语言---- 计算机网络
🐓每日一句:站在属于自己的个让高度 看自己该看的风景


文章目录

  • 一个停不下来的动效!!动效!难道
    • 前言:😶‍🌫️
    • 思路😶‍🌫️
    • 静态页面😶‍🌫️
      • 容器😶‍🌫️
      • 滑块😶‍🌫️
      • 按钮😶‍🌫️
    • 滑块动效😶‍🌫️
      • 按钮动效😶‍🌫️
      • 容器动效😶‍🌫️
      • 添加按钮✨
      • 最终效果图😶‍🌫️
    • 欢迎添加微信,不瞅加入我的瞅含核心小队,请备注来意

一个停不下来的源码动效!!思路!个让

前言:😶‍🌫️

最近在某平台看都这样一篇文章,动效听说这个动效可以玩一天?果然玩起来就停不下来,难道于是不瞅突发奇想,想要复刻一个一模一样的瞅含出来,怪小生实力太差,源码好些地方都不理解,思路做出来的个让实在难以入目,那么就来看看这问大佬和我的结合版吧~很喜欢他的写作风格,幽默风趣——urias
😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️😶‍🌫️
在这里插入图片描述

思路😶‍🌫️

这一个动效乍一看好像其实并没有觉得很复杂,但是如果往细了看(多细?比吴签还细吗?🤫)


好像其实也没有很复杂。
先聊聊思路:任何组件都是有静态开始,加上动作,赋予生动化,于是就变活起来了

首先看静态的东西,我们可以把这个动效拆成容器,按钮和滑块三个部分,包含各类样式;
容器在被点击时需要添加css透视和一定幅度的Y轴旋转,构造成被点击下陷的感觉,仔细观察发现不同按钮点击后两侧容器旋转的偏移量还不尽相同,所以我们还需要动态修改他的原点;
按钮则是包含相关内容的一个盒子,有选中和未选中的两种不同状态,再仔细点呢,盒子内的内容在切换状态时还有一定量的缩放scale,缩放详细为:

被选中时,先稍微多放大一些,再缩小为选中的放大状态保持;
未选中时,先稍微多缩小一些,再放大为未选中的正常状态保持;

滑块就比较简单了,单纯的静态样式加上点以后滑动到对应按钮下方,稍微麻烦一点就是这个点击后的过渡效果(滑动)需要起始和结尾稍慢,中间较快的速度,可能需要用贝塞尔函数来实现,对于css贝塞尔函数已经遗忘的同学可以再去温习一遍。css贝塞尔函数

多说无益,在下先干为敬!

静态页面😶‍🌫️

首先当然是我们的静态页面了,动效再怎么动,也得先有能动的玩意儿是波。

容器😶‍🌫️

咱们先随便点,先画个容器,起个名儿就叫btnWrapper吧,因为滑块用绝对定位,所以容器得先相对定位,同时给定宽高:

#btnWrapper {     position: relative;    width: 380px;    height: 80px;    padding: 12px 16px;    border-radius: 12px; // 圆角    overflow: hidden; // 超出隐藏    background-color: #e2e6eb; // 背景色    box-shadow: -10px -10px 15px #f5f9fd, 10px 10px 15px #d8dbe5; // 阴影(阴影可以添加多条,别告诉我你不知道!!)}

滑块😶‍🌫️

然后就是滑块,因为滑块并没有复杂的逻辑,也不需要存放一些其他元素,所以在下选择的是用伪元素来实现,这就没有结构(html)代码了。

尺寸图解:
在这里插入图片描述
代码示例:

#btnWrapper::before {     content: "";    position: absolute;    left: 16px; // 要考虑到父盒子的内边距    top: 12px; // 同上    width: calc(50% - 16px - 8px);    height: calc(100% - 24px);    border-radius: 12px;    box-shadow: inset 8px 8px 6px #d9dce6,                 inset -5px -5px 15px #f5f9fd,                 inset -5px -5px 15px #f5f9fd,                 inset 7px 7px 6px #d9dce6;}

在这里插入图片描述

按钮😶‍🌫️

按钮呢因为他本身没有轮廓样式,所以我是直接把它理解为均分了容器的两个透明盒子,然后内部元素不确定,用弹性布局让按钮的子元素都居中就行。
但是因为按钮要跟滑块重叠,并且居于滑块之上,所以按钮也需要浮动起来,每个都占50%宽度,这里在下选择让他俩都float: left;,如果还想继续使用绝对定位也是可以实现的,配置不同left即可,这里就不再赘述了。
同时按钮还有选中状态,👇👇👇

按钮1
按钮2
.btn {     float: left;    display: flex; // 弹性布局    align-items: center; // 列居中    justify-content: center; // 行居中    width: 50%;    height: 100%;    padding: inherit; // 偷懒内边距继承了父元素,也可以自己修改    color: #aaa; // 默认文字颜色是灰色,随便选了个色号    cursor: pointer; // 鼠标经过图标为小手}.active {     color: #111; // 选中颜色}

现在的效果,还能看的过眼吧,哈哈哈
在这里插入图片描述

滑块动效😶‍🌫️

静态页面倒是写完了,但这并没有什么卵用就是一张图片动也不会动一下,在下的目标是希望它动起来,如标题一样玩一整天的丝滑😤😤。
而效果图中在下一眼看见动幅最大的就是这个滑块了,所以决定先让滑块动起来,其实让滑块动起来非常简单,修改滑块的left值即可,再添加过渡效果让滑块更加丝滑~
这里动态修改样式,我选择使用css变量,通过js给容器添加和修改css变量来达到动态修改样式的效果。
🎠来吧,展示!🎠

#btnWrapper::before {     content: "";    /* ...其他属性 */    left: var(--groove-left); // 使用css变量    /* ...其他属性 */    transition: left 1s cubic-bezier(0.82, 0.12, 0.18, 0.88); // 添加过渡效果,贝塞尔曲线}
// 获取容器元素let wrapper = document.getElementById('btnWrapper');// 先给容器设置一个css变量并附初始值wrapper.style.setProperty('--groove-left', '12px');// 获取按钮元素let btns = document.getElementsByClassName('btn');for (let i = 0; i < btns.length; i++) {     // 给每个按钮添加点击事件    btns[i].addEventListener('click', function (e) {         // 点击后,修改css变量的值        wrapper.style.setProperty('--groove-left', `calc(12px + ${ i * 50}%)`);    })}

在这里插入图片描述

按钮动效😶‍🌫️

👀那,滑块都自己动起来了,你按钮不得自己动?
👀自己动?
👀动?
懂了!直接在点击里修改每个按钮的类名不就行了?
没错,按钮不单纯只是改变了颜色,还改变了字体的缩放大小,并且选中非选中状态都有一个缩放的抖动。
所以在下决定,写两个动画(具体可以根据自己的感觉修改,只是在下的感觉就到这了)。(这里我脑子有点笨直接照搬了😶‍🌫️🤫🤫)
talk is cheap,show me the code!(在下想起来了!)

按钮1
按钮2
/* 按钮选中缩放动画 */@keyframes txtEnterScale {     0% {         transform: scale(1);    }    80% {         transform: scale(1.15);    }    100% {         transform: scale(1.1);    }}/* 按钮未选中缩放动画 */@keyframes txtOutScale {     0% {         transform: scale(1.1);    }    80% {         transform: scale(0.95);    }    100% {         transform: scale(1);    }}.btn {     /* ...其他属性 */    transition: color 0.4s linear; // 添加文字颜色过渡效果    animation: txtOutScale 0.6s linear; // 添加按钮未选中动画,注意时间    /* ...其他属性 */}.active {     color: #111;    transform: scale(1.1); // 修改选中状态原始缩放为1.1    animation: txtEnterScale 0.4s linear; // 添加按钮选中动画,注意时间}
let wrapper = document.getElementById('btnWrapper');wrapper.style.setProperty('--groove-left', '12px');let btns = document.getElementsByClassName('btn');for (let i = 0; i < btns.length; i++) {     btns[i].addEventListener('click', function (e) {         wrapper.style.setProperty('--groove-left', `calc(12px + ${ i * 50}%)`);        resetBtn(btns); // 初始化所有按钮类名        setTimeout(() =>{             btns[i].className = 'btn active'; // 给被点击的按钮添加选中样式,注意不要丢了原始样式        }, 500);    })}// 初始化所有按钮类名的方法function resetBtn(btns) {     for (let i = 0; i < btns.length; i++) {         setTimeout(() =>{             btns[i].className = 'btn';        }, 100)    }}

这里讲一下为什么需要注意时间,因为在下注意到,并不是一经点击按钮的动画就开始了,选中状态的类名,是在滑块几乎完全滑到对应按钮背后,按钮的缩放状态和颜色才开始变化,同理未选中状态也类似,只是时间稍微提早。
哼哼,一个小细节🧐🧐。
所以在下的处理方式是在点击后给添加类名的代码添加一个定时器,有无更好的方法麻烦告知在下。

文字的缩放和在下的小细节,能看出来吗?
在这里插入图片描述

容器动效😶‍🌫️

又凑了这么多字了🤪,工作量嘎嘎上去了…
哎哎哎客官别着急走哇,咱这还有个最大的容器还没动起来呢,错了错了,在下直接来。
整体容器
顺着在下前面的思路,首先先给他添加上css透视和Y轴旋转,然后咱们先看看效果如何,为了做出近大远小的视觉效果,咱们首先要给容器的父元素添加透视点,为了不耽搁客官老爷们的时间,不懂概念的同学就劳烦百度一下先了解一番。👉perspective👈

body {     perspective: 500px; // 添加透视}#btnWrapper {     /* ...其他属性 */    transform-origin: center; // 添加转换原点    transition: transform 0.4s cubic-bezier(0, 0, 0.48, 1); // 添加过渡效果}.rotateWrap {     transform: rotateY(var(--wraper-rotate)); // 添加Y轴旋转}
let wrapper = document.getElementById('btnWrapper');// ...其他代码let btns = document.getElementsByClassName('btn');for (let i = 0; i < btns.length; i++) {     btns[i].addEventListener('click', function (e) {         // ...其他代码        wrapper.style.setProperty('--wraper-rotate', `${ i === 0 ? -8 : 8}deg`);        wrapper.className = 'rotateWrap';        setTimeout(() =>{             wrapper.className = ''        }, 550); // 注意小细节!!!    })}// ...其他代码

亿点细节

看了目前成品图,是不是感觉跟上面那个玩一天丝滑的按钮大差不差,但是总感觉哪里有点不一样呢?😶‍🌫️😶‍🌫️😶‍🌫️脑子快炸了
没错,在下也看出来,感觉人家那个非常的灵活,而在下这个就像被钉住了一样。
没戳!!就是这个Y轴旋转量的问题,在下前面也提到了,解决方法就是需要动态修改css转换的原点。
在这里插入图片描述

添加按钮✨

在这里插入图片描述

在玩这个动效的时候,感觉两个按钮单纯的切换来切换去,是不是太过于单调了?(主要是水文的字数还没有搞上去)

于是,在下准备给这两个按钮加点功能。

切换主题思路:

把需要切换的颜色都提出来用css变量代替,并添加上过渡效果(不然看起来很突兀) 在不同主题类名里修改css变量
点击按钮,将类名添加到body上(有的也添加到html上,反正就是添加到你使用主题的最上层元素)
因为给body添加了类名权重更高,所以会覆盖body以元素名定义的css变量,经过css过渡以后,就实现了丝滑的换肤效果。很简单吧😶‍🌫️😶‍🌫️😶‍🌫️

直接展示,贴代码(有点长,但是是全部的代码):

白昼
黑夜
* {     margin: 0;    padding: 0;    box-sizing: border-box;}body {     background-color: #edf1f4;    perspective: 500px;    --c-wrap-shadow1: #f5f9fd;    --c-wrap-shadow2: #d8dbe5;    --c-wrap-bg: #e2e6eb;    --c-btn-shadow1: #d9dbe6;    --c-btn-shadow2: #f5f9fd;    --c-txt1: #aaa;    --c-txt2: #111;    transition: background-color 0.4s linear;}.dark {     background-color: #333;    --c-wrap-shadow1: #292929;    --c-wrap-shadow2: #202020;    --c-wrap-bg: #505050;    --c-btn-shadow1: #323232;    --c-btn-shadow2: #444;    --c-txt1: #888;    --c-txt2: #fff;}#btnWrapper {     position: relative;    width: 380px;    height: 80px;    padding: 12px 16px;    margin: 300px auto 0;    border-radius: 12px;    overflow: hidden;    background-color: var(--c-wrap-bg);    box-shadow: -10px -10px 15px var(--c-wrap-shadow1), 10px 10px 15px var(--c-wrap-shadow2);    transform-origin: var(--wraper-origin);    transition: transform 0.4s cubic-bezier(0, 0, 0.48, 1), box-shadow 0.4s linear, background-color 0.4s linear;}.rotateWrap {     transform: rotateY(var(--wraper-rotate));}#btnWrapper::before {     content: "";    position: absolute;    left: var(--groove-left);    top: 12px;    width: calc(50% - 16px - 8px);    height: calc(100% - 24px);    border-radius: 12px;    box-shadow: inset 8px 8px 6px var(--c-btn-shadow1), inset -5px -5px 15px var(--c-btn-shadow2), inset -5px -5px 15px var(--c-btn-shadow2), inset 7px 7px 6px var(--c-btn-shadow1);    transition: left 1s cubic-bezier(0.82, 0.12, 0.18, 0.88), box-shadow 0.4s linear;}.btn {     float: left;    display: flex;    align-items: center;    justify-content: center;    width: 50%;    height: 100%;    padding: inherit;    color: var(--c-txt1);    transition: color 0.4s linear;    animation: txtOutScale 0.6s linear;    cursor: pointer;}.active {     color: var(--c-txt2);    transform: scale(1.1);    animation: txtEnterScale 0.4s linear;}@keyframes txtEnterScale {     0% {         transform: scale(1);    }    80% {         transform: scale(1.15);    }    100% {         transform: scale(1.1);    }}@keyframes txtOutScale {     0% {         transform: scale(1.1);    }    80% {         transform: scale(0.95);    }    100% {         transform: scale(1);    }}
let wrapper = document.getElementById('btnWrapper');wrapper.style.setProperty('--groove-left', '12px');let btns = document.getElementsByClassName('btn');for (let i = 0; i < btns.length; i++) {     btns[i].addEventListener('click', function (e) {         ThemeChange(i === 1);        resetBtn(btns);        wrapper.style.setProperty('--groove-left', `calc(12px + ${ i * 50}%)`);        wrapper.style.setProperty('--wraper-origin', `${ i === 0 ? '75% top' : '25% top'}`);        wrapper.style.setProperty('--wraper-rotate', `${ i === 0 ? -8 : 8}deg`);        wrapper.className = 'rotateWrap';        setTimeout(() =>{             btns[i].className = 'btn active';        }, 500);        setTimeout(() =>{             wrapper.className = ''        }, 550);    })}// 重置按钮类名function resetBtn(btns) {     for (let i = 0; i < btns.length; i++) {         setTimeout(() =>{             btns[i].className = 'btn';        }, 100)    }}// 改变主题function ThemeChange(bol) {     let body = document.body;    body.className = bol ? 'dark' : ''}

最终效果图😶‍🌫️

在这里插入图片描述

反正我已经玩了一整天了,(实际是被一些小问题困扰一整天,呜呜呜)

✨✨好吧今天的水文就到此结束,感谢大家阅读观看~
在这里插入图片描述

然后就是往下看、往下看,往下看!!!
重要的事说三遍,快来加入我的核心小队!!!


在这里插入图片描述

欢迎添加微信,加入我的核心小队,请备注来意

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇

未经允许不得转载:锦绣山河网 » 【一个让你停不下来的动效】——难道不来瞅瞅?(含源码+思路)