今天在这个网站看到了上面类似的效果,然后就想弄一个,然后就有了上面的
-
先简单来一个样式和布局
- 我使用的是vue 原生区别就是用js在控制class的切换,差别不大,可放心食用
-
<template> <div class="list" @click="isCollapse = !isCollapse" :class="isCollapse ? 'collapse' : 'backCollapse'" > <div class="list-item"></div> <div class="list-item"></div> <div class="list-item"></div> </div> </template> <script setup> import { ref } from "vue"; let isCollapse = ref(false); </script>
- 接下来是css (我使用的是scss)先都写出来,方便粘贴,后面继续讲解
-
<style lang="scss" scoped> $list-width: 15px;// 列表的宽度 $list-height: 2px;//列表子项的高度 即每一个长条的宽度 $list-color: black;// 列表子项的颜色 $list-time: .5s;// 动画时间 $list-margin-bottom: 3px;// 列表子项之间的间距 $list-box-height: ($list-height + $list-margin-bottom) * 3 -$list-margin-bottom;//列表的高度 // 列表高度是用来计算选择的中心的 .list { margin-left: 50px; margin-top: 10px; //以上两个不影响,只是为了自己更好观察 width: $list-width; height: $list-box-height; .list-item { width: $list-width; height: $list-height; background: black; margin-bottom: $list-margin-bottom; transition: opacity, transform $list-time; } } .collapse { position: relative; // transform-origin: center;//这个记得是旋转中心,但是我没有使用成功,有人会也可以教我一下 transform: rotateZ(45deg);//动画后的旋转最后位置,让动画衔接起来 animation: collapse45 $list-time; .list-item:nth-child(1) { top: $list-box-height/2;//动画后的最后位置,让动画衔接起来,下面的top和rotate都是一样的 position: absolute; transform: rotate(90deg); animation: collapse $list-time; } .list-item:nth-child(2) { position: absolute; top: $list-box-height/2; } .list-item:nth-child(3) { top: $list-box-height/2; position: absolute; animation: reCollapse $list-time; transform: rotate(90deg); } } .backCollapse { position: relative; transform-origin: center; transform: rotateZ(0deg); animation: backCollapse $list-time; .list-item:nth-child(1) { position: absolute; animation: backCollapse-1 $list-time; } .list-item:nth-child(2) { position: absolute; top: $list-box-height/2; } .list-item:nth-child(3) { top: $list-box-height; position: absolute; animation: backCollapse-3 $list-time; } } // 开始的动画 @keyframes collapse45 { //从0-50都不变是要让子项的部分动画先完成,相同时间用百分比划分就可以控制动画开始时间 0% { transform: rotate(0deg); } 25% { transform: rotate(0deg); } 50% { transform: rotate(0deg); //从50%-100% 让整体旋转45度 } 100% { transform: rotate(45deg); } } @keyframes collapse { //0-25:先完成1,2,3重合;25-50%:完成旋转90edg(1和3旋转相同的90,不要一个90,一个-90这样不好看);50-100%;维持状态,让上面整体旋转 0% { transform: rotate(0deg); top: 0; } 25% { transform: rotate(0deg); top: $list-box-height/2; } 50% { transform: rotate(90deg); top: $list-box-height/2; } 100% { transform: rotate(90deg); top: $list-box-height/2; } } //0-25:先完成1,2,3重合;25-50%:完成旋转90edg(1和3旋转相同的90,不要一个90,一个-90这样不好看);50-100%;维持状态,让上面整体旋转 这个一开始写的是旋转-90edg 不好看 @keyframes reCollapse { 0% { transform: rotate(0deg); } 25% { transform: rotate(0deg); top: $list-box-height/2; } 50% { transform: rotate(90deg); top: $list-box-height/2; } 100% { transform: rotate(90deg); top: $list-box-height/2; } } // 返回的动画 @keyframes backCollapse { //这个就是把上面的整体旋转反过来 0%{ transform: rotate(45deg); } 25%{ transform: rotate(45deg); } 50% { transform: rotate(45deg); } 100% { transform: rotate(0deg); } } @keyframes backCollapse-1 { // 0-25%:先旋转回0deg(保持当前位置) 25-50%:保持旋转开始位置移动;50-100%:保持不变,让整体旋转 0% { transform: rotate(90deg); top: $list-box-height/2; } 25% { transform: rotate(0deg); top: $list-box-height/2; } 50% { transform: rotate(0deg); top: 0; } 100% { transform: rotate(0deg); top: 0; } } // 0-25%:先旋转回0deg(保持当前位置) 25-50%:保持旋转开始位置移动;50-100%:保持不变,让整体旋转 @keyframes backCollapse-3 { 0% { transform: rotate(90deg); top: $list-box-height/2; } 25% { transform: rotate(0deg); top: $list-box-height/2; } 50% { transform: rotate(0deg); top: $list-box-height; } 100% { transform: rotate(0deg); top: $list-box-height; } } </style>
-
分析--html部分就不说明了
-
公共的scss变量放在这里,方便查看
-
$list-width: 15px;// 列表的宽度 $list-height: 2px;//列表子项的高度 即每一个长条的宽度 $list-color: black;// 列表子项的颜色 $list-time: .5s;// 动画时间 $list-margin-bottom: 3px;// 列表子项之间的间距 $list-box-height: ($list-height + $list-margin-bottom) * 3 -$list-margin-bottom;//列表的高度 // 列表高度是用来计算选择的中心的
-
//以下为基础样式 .list { margin-left: 50px; margin-top: 10px; //以上两个不影响,只是为了自己更好观察 width: $list-width; height: $list-box-height; .list-item { width: $list-width; height: $list-height; background: black; margin-bottom: $list-margin-bottom; transition: opacity, transform $list-time; } }
-
开始旋转
-
分为三步
- 先看慢动作
-
//第一步,用这两个来调整1和3的位置,让1,2,3重合 top: $list-box-height/2; position: absolute;
-
//以第一个为例子 transform: rotate(90deg);//设置最后的旋转位置 animation: collapse $list-time; @keyframes collapse { //0-25:完成位置变化 35-50:完成旋转 50-100:不变,这个阶段父盒子旋转 ,其他保持不动即可 0% { transform: rotate(0deg); top: 0; } 25% { transform: rotate(0deg); top: $list-box-height/2; } 50% { transform: rotate(90deg); top: $list-box-height/2; } 100% { transform: rotate(90deg); top: $list-box-height/2; } }
- 3和1是类似的 ,下面为父盒子的
-
@keyframes collapse45 { //从0-50都不变是要让子项的部分动画先完成,相同时间用百分比划分就可以控制动画开始时间 0% { transform: rotate(0deg); } 25% { transform: rotate(0deg); } 50% { transform: rotate(0deg); //从50%-100% 让整体旋转45度 } 100% { transform: rotate(45deg); } }
- 组合起来就完成了开始的点击旋转
-
恢复原状
- 老规矩看慢放
- 首先旋转到全部重合,其次位置还原
-
@keyframes backCollapse-1 { // 0-25%:先旋转回0deg(保持当前位置) 25-50%:保持旋转开始位置移动;50-100%:保持不变,让整体旋转 0% { transform: rotate(90deg); top: $list-box-height/2; } 25% { transform: rotate(0deg); top: $list-box-height/2; } 50% { transform: rotate(0deg); top: 0; } 100% { transform: rotate(0deg); top: 0; } }
- 盒子旋转回原样
- 父盒子动画
-
@keyframes backCollapse { //这个就是把上面的整体旋转反过来 0%{ transform: rotate(45deg); } 25%{ transform: rotate(45deg); } 50% { transform: rotate(45deg); } 100% { transform: rotate(0deg); } }
-
建议
- 可以写为一个组件,通过父子通信来控制展开和关闭
- 再去影响父盒子的抽屉的展开和关闭
-
-
-