前言
前面一些文章我们介绍了 tailwinds、变换和动画、less(sass),这篇文章我们就利用他们实现一个旋转摩天轮效果(实际上主要使用的是 动画、sass,less 使用的没有 sass 高,也换成 sass 了,tailwinds 是基础,设置一些基础css不多介绍)
先看看效果(比较懒没放图片)
实现步骤和问题
下面介绍一下实现步骤 和 中间可能出现的问题以及解决方案,如果后面介绍代码有不理解的,可以参考下面
要实现摩天轮要经过如下步骤
- 创建一个父节点盒子,用于外部模仿摩天轮外圈旋转效果,通过父节点带动子节点旋转
- 子节点之间根据数量平均分割一圈,先使用绝对布局设置到与顶部中心对齐,然后通过循环,设置子节点 nth-child,实现平分弧度
- 由于重力效果,子节点应该自身保持垂直方向,盒子不应当旋转(否则里面的人没办法平稳坐着),因此需要处理自身随着父节点旋转问题,反向自转解决
- 添加两个动画,父节点顺时针,子节点元素顺时针
问题与解决方案:
- 子节点通过循环设置 nth-child,那么也是默认相对自己中心,无法形成图片效果?
- 可以通过设置 transfrom-origin 也就是旋转初始点,可以认为是锚点,改变其位置为父节点中心位置即可
- 子节点已经设置 transfrom 了,在设置自身的 transfrom 动画,会影响实际效果吧?
- 可以通过给添加孙子节点,让孙子节点反向自转即可,这样就互不影响了
- 孙子节点动画发现有问题,即使反向旋转,也是有的节点有正常重力效果,有些没有?
- 孙子节点默认为了水平已经反向自转了,也就是自带偏移了,执行动画时,可以添加上这个偏移即可,结束动画添加上偏移就行了(开始动画也可以添加,因为默认就有,所以也没啥必要哈)
实现
先编写 css ,一个父节点,几个子节点(item-view),每个子节点各有一个孙子节点(假的img,所以起名img😂)
<div id="circle_bkg" class="rounded-full border-[1px] border-red-500">
<div class="item-view">
<div class="img bg-amber-200" />
</div>
<div class="item-view">
<div class="img bg-amber-700" />
</div>
<div class="item-view">
<div class="img bg-green-400" />
</div>
<div class="item-view">
<div class="img bg-blue-400" />
</div>
<div class="item-view">
<div class="img bg-cyan-500" />
</div>
</div>
接下来就是重头戏了,编写我们的css 了
//标记我们的父节点宽高、子节点个数(孙子节点个数),以及平均弧度
$parentSize: 400px;
$n: 5;
//有人不加 calc 发现也没事,我不加就报错了哈,可能是vue的使用问题,加上😂
$degPer: calc(360deg / 5);
//设置动画连续滚动
#circle_bkg {
animation: circleFrame 10s linear infinite;
width: $parentSize;
height: $parentSize;
position: relative;
}
//设置子布局为绝对布局,其相对于父节点的顶部中心,大小约 20%
.item-view {
position: absolute;
width: 20%;
height: 20%;
left: 40%;
//向上偏移 10%
top: -10%;
//设置子节点变换,让其围绕外部一个点旋转变换,也就是父节点中心
//默认应该是 50% 的父节点宽度,实际上我们为了保持中心在轴线,向上偏移了 10%,要加上
//那么就是 0.6倍的父节点宽度了,x则是父节点中心直接设置center
transform-origin: center $parentSize * 0.6;
//循环处理节点情况
@for $i from 1 through $n {
//无引号字符串需要 #{} 方式插值
&:nth-child(#{$i}) {
$deg: $degPer * ($i - 1); //索引 * 弧度 = 当前节点弧度(索引从 1~n 开始所以要减1)
transform: rotateZ($deg); //设置子节点根据弧度旋转
//孙子节点
.img {
//由于设置了初始偏移 transform,所以用css变量记录一下,方便动画使用
//sass变量不能在动画使用忽略,直接使用css变量即可
--initialDeg: #{-$deg};
//由于父节点旋转,孙子节点也旋转了,若想符合重力效果好,反向旋转同样角度即可
transform: rotateZ(-$deg); //为了保证水平放置,里面的 img 需要反转同样角度
animation: selfFrame 10s linear infinite;
}
}
}
}
.img {
width: 100%;
height: 100%;
}
@keyframes circleFrame {
to {
transform: rotateZ(360deg);
}
}
@keyframes selfFrame {
to {
//设置偏移是,需要加上默认的偏移,这样就可以实现效果了
//需要注意是孙子节点是反向旋转,所以是 -360deg
transform: rotateZ(calc(-360deg + var(--initialDeg)));
}
}
最后
css 基础知识有了,有时候做动画真的需要一些思路,需要一些想象力,不然空有知识无用武之地了,当然如果想象力还是不足够,那么可以学习,毕竟学习使人进步,不是每个人都是天才!
学习使人进步,俺也一样!🤣