标题当然是我自创的啦,这个效果是我偶然做出来的,并没有人严肃地起过名字。那我为什么会偶然做出这个东西呢?
最近做一个PC端官网的项目,首页的banner迟迟没有定下来,感觉客户想搞个大文章。果然后来客户说了个“要会动的banner”?什么是会动的?banner图左边有一个大圆环,(圆环上有8个栏目,每个栏目有个小圆圈,下面是标题)所以我认为,会动是圆环会转动。然后我花了好几个小时,研究如何使用animation动画让圆环转动,而且不让里面的文字颠倒。
banner的截图,长这样——
简单介绍一下圆环转动的思路:
这个思路不是我原创的,而是来自一本叫做
《CSS揭秘》
的书的最后一节。
这个圆环有个特点:
里面的每个项目并不是单纯的一个圆,而是含有文字的
,甚至文字和圆是在同一张切图上的,
也就是说,
这些子项目的中心点并不是圆心。
让圆环转动不难,但是
如果只是圆环在转动,文字会颠倒,所以文字需要做相反方向的转动。
据我所知有两种实现方法。
第一种是我一开始使用的,
很蠢,非常蠢
——
分别指定每个子项目的transform-origin为圆环的圆心位置
(因为不同的对于不同的点来说,圆心的位置不一样,)让子项目绕着圆心转动,因为它们本身就在圆环上,所以绕圆心转动,就是沿着圆环转动,
理想的情况下是刚好在圆上的
。然后让子项目里再套一层子元素(图片是子元素的背景图),子元素旋转的方向相反,让文字不颠倒。这个方法很麻烦,需要一一指定转动的中心,而且指定的位置如果没那么准确,转的时候会脱离轨道,效果很尴尬。
第二种效果好多了,那就是,
不让每个子项目自己绕着圆心转,而是就摆在圆环上,让圆环自己转动
,子项目自然就被带动着转起来了。
然后,找到每个子项目中的圆心位置,让子项目绕着自己的圆心做方向相反的转动,
就保证了文字不颠倒。这样计算量小得多,也不容易出意外(因为每个子项目看起来差不多大,圆心的位置几乎是一样的,只需要设置一次就可以了)
代码是这样的——
<!-- banner -->
<div class="banner-box">
<img src="img/banner_bg.png" class="index-img"/>
<!-- 左边,圆环 -->
<div class="left-box">
<div class="circle-box">
<div class="menu-box menu-box1">
<a href="#" class="menu">创新成果</a>
</div>
...
<!-- 这里一共8个子项目,每个子项目有两层,外层是div,class为menu-box,内层是a,class为menu --->
</div>
<!-- 中间的文字 -->
<img src="img/gxdjlc.png" alt="高校对接流程" class="circle-title"/>
</div>
<!-- 右边不重要 -->
<div class="right-box">
<img/><img/>
</div>
</div>
/* 两个方向相反的旋转关键帧动画 */
@keyframes spin{
to{transform: rotate(1turn);}
}
@keyframes spin-reverse{
from{
transform:rotate(1turn);
}
}
/* 圆环 */
.banner-box .circle-box {
width: 560px;
height: 560px;
transform-origin: center;
background: url("../img/circle_bg.png");
/* 圆环转动 */
animation:spin 60s infinite linear;
}
/* banner里面的每一个子项目div */
.banner-box .circle-box .menu-box {
position: absolute;
animation: inherit;
animation-name: spin-reverse;
transform-origin: 50% 40px;
/* 子元素转动,animation是继承了圆环的,但是指定了另一个动画名字,所以是倒着转的 */
animation: inherit;
animation-name: spin-reverse;
}
/* 每个子元素div的位置,menu-box1到menu-box8各不相同,这里省略了其他的 */
.banner-box .circle-box .menu-box1 {
top: -39px;
left: 218px;
}
/* 每个里面的a的大小和背景图 */
.banner-box .circle-box .menu-box1 .menu {
width: 125px;
height: 131px;
background: url("../img/banner_menu1.png");
}
/* 圆盘悬浮时暂停动画,设置动画播放状态为暂停 */
.banner-box .circle-box:hover .menu-box {
animation-play-state: paused;
}
结果我满头大汗做出来给客户看了以后,客户居然说“不是要转动的。是像某某项目一样有发光、发散的效果。转动先留着。如果领导想不开,可能会想让圆环转起来”。所以重点并不是圆环转动,而是小圆发光。于是我接着去做小圆发光的事情……
为了防止给HTML代码“添乱”,我这里借用了伪元素,大部分元素都有两个伪元素,分别叫before和after。这样,
看似一个元素,其实就有两个跟它站在一起的”分身“
。思路是这样的(这个思路也不是我原创的,我在看黑马程序员老师讲CSS3的时候看到的):因为发光的时候
光线会随着时间变淡
,所以应该是
透明度降低
;而且光线应该是
渐渐走出我们的视野
,所以应该是变透明的同时
放大
了;而且发光的时候看起来是
一闪一闪
的,所以必须
有两个光圈同时在动,而且节奏不一致。
更进一步说,两个光圈同时在动,但节奏不同,说明它们用的是同一个动画但有不同的延时,而这两个光圈,可以使用绝对定位、背景透明但有白色边框的伪元素来做。用js给子元素做了轮流闪烁的效果。另外,为了在鼠标悬浮时吸引用户的注意,我让鼠标悬浮的项目加上动画,并且次数为无数次。
/* 用伪元素做两个白色小圆环,初始状态下透明度为0,看不见 */
.banner-box .circle-box .menu::before,
.banner-box .circle-box .menu::after {
content: '';
position: absolute;
top: 0;
left: 50%;
margin-left: -39.5px;
width: 80px;
height: 80px;
box-sizing: border-box;
border: 2px solid #fff;
border-radius: 50%;
transform-origin: center;
opacity: 0;
}
/* 发光动画,在动的时候,透明度变淡,同时光圈变大 */
@keyframes shining {
from {
opacity: 1;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(1.8);
}
}
/* 悬浮和active闪烁*/
.banner-box .circle-box .menu.active::before,
.banner-box .circle-box .menu:hover::before {
/* 加上发光动画 */
animation: shining 3s infinite linear;
}
/* after的动画有延时 */
.banner-box .circle-box .menu.active::after,
.banner-box .circle-box .menu:hover::after {
animation: shining 3s infinite 1.5s linear;
}
/* 如果是加上了active,那么就只动一次 */
.banner-box .circle-box .menu.active::after,
.banner-box .circle-box .menu.active::before {
animation-iteration-count: 1;
}
// 让元素自己闪的动画
// 现在闪烁的元素索引
let activeIndex = 0;
let links = $('.circle-box .menu');
// 先让第一个元素闪烁
links.eq(0).addClass('active')
/* 让里面的链接自动按顺序闪烁 */
window.setInterval(function() {
activeIndex++;
// 只有当前的元素有active类
links.removeClass('active')
links.eq(activeIndex % 8).addClass('active')
}, 4500) //闪烁一次时间是4.5秒
效果是这样的——
我不知道怎么截gif,所以就随手灵魂截图截了几张给大家看看,子项目的位置在变,说明有在旋转,而且有的子项目外面有半透明圆圈。
整体来说,这是一个不太难,但是又比较有趣的一个效果,莫名地有一种摩天轮的感觉。如果有小伙伴在学习CSS3动画,可以来了解一下,练习一下。好啦,这一个效果讲完了。我是南宫,我的愿望是——好好学习,好好生活,早日找到好工作!