使用CSS3实现椭圆动画效果

写在前面的话:

  有这样一个需求,在大屏中要实现几个球用椭圆形状的布局进行展示,展示的同时还要沿着椭圆轨道进行运动。经过 百度结合自身的思考之后给出了以下demo。

正文:

首先我们先写结构

<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>    
        <div class="area">
       <div class="ball ball1"></div> <div class="ball ball2"></div> <div class="ball ball3"></div> <div class="ball ball4"></div> <div class="ball ball5"></div> <div class="ball ball6"></div> </div> </body> </html>

类名为area的div为存放球类的容器,类名为ball的div为球

接着定义样式

<style>
            .area{
                width: 1200px;
                height: 800px;
                background: green;
            }
            .area>.ball{
                width: 60px;
                height: 60px;
                position: absolute;
                border-radius: 60px;
                background-image: linear-gradient(to top,blue,lightblue);
                box-shadow: 0px 0px 20px #0000ff5c;
            }
</style>

目前得到的效果如下:

 接着我们要将这六个球进行椭圆的排列并使其动起来:

分析过程:

椭圆轨迹的运动可以分解为左右反复运动和上下反复运动的叠加而形成的复合运动。知道了这一点之后我们就可以尝试使得一个球进行该运动

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <style>
            .area{
                width: 1200px;
                height: 800px;
                background: green;
            }
            .area>.ball{
                width: 60px;
                height: 60px;
                position: absolute;
                border-radius: 60px;
                background-image: linear-gradient(to top,blue,lightblue);
                box-shadow: 0px 0px 20px #0000ff5c;
            }
            
            .area>.ball1{
                animation: anmiteX 12s linear 0s infinite alternate,
                anmiteY 12s linear 0s infinite alternate;
            }
            /* 动画 */
            /* 在X轴上的移动 */
            @keyframes  anmiteX{
                from{
                    left: 100px;
                }
                to{
                    left: 1000px;
                }
            }
            /* 在轴上Y的移动 */
            @keyframes  anmiteY{
                from{
                    top: 100px;
                }
                to{
                    top: 600px;
                }
            }</style>
        <div class="area">
            <div class="ball ball1"></div>
           
        </div>
    </body>
</html>

以上的代码我们得到的是如下的动画,从左上角到右下叫的叠加动画,是不是之前的分析出错了呢,并没有只是我们漏分析了运动的时间差,当x轴开始运动的时候,Y轴的开始位置要在中间了,也可以理解为在开始运动的时候Y轴先运动了一半,那么假设整个完成一个椭圆的运动时间未24秒,也就是x轴来回运动叠加上Y轴来回运动的时间是24秒。那么运动一趟的时间未24/2=12秒,Y轴的运动时间是biX轴的领先一半那么时间未12/2=6秒;现在对XY轴的运动叠加上时间差

.area>.ball1{
                animation: anmiteX 12s linear -6s infinite alternate,/* 叠加上6秒时间差 */
                anmiteY 12s linear 0s infinite alternate;

            }

已经是一个椭圆的运行轨迹了。接下来就是进行六个球的同时运动。

分析:六个球进行椭圆运动的轨迹没有变化,只是起始的时间不同,那么假设运行一圈的时间未24 秒 那么六个椭圆的时间差位24/6=4秒,也就是说每个球的其实位置间隔4秒那么CSS代码表现如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <style>
            .area{
                width: 1200px;
                height: 800px;
                background: green;
            }
            .area>.ball{
                width: 60px;
                height: 60px;
                position: absolute;
                border-radius: 60px;
                background-image: linear-gradient(to top,blue,lightblue);
                box-shadow: 0px 0px 20px #0000ff5c;
            }
            
            /* 6个球 总共运行一圈的时间为24秒  每个球的间隔时间为 4秒*/
            .area>.ball1{

                animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -6s infinite alternate,
                anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) 0s infinite alternate, 
                scale 24s cubic-bezier(0.6,0.3,0.3,0.6) 0s infinite alternate;
            }
             .area>.ball2{
                animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -10s infinite alternate,
                anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -4s infinite alternate,
                scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -4s infinite alternate;
            }
            .area>.ball3{
                animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -14s infinite alternate,
                anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -8s infinite alternate,
                scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -8s infinite alternate;
            }
            .area>.ball4{
                animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -18s infinite alternate,
                anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -12s infinite alternate,
                scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -12s infinite alternate;
            }
            .area>.ball5{
                animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -22s infinite alternate,
                anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -16s infinite alternate,
                scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -16s infinite alternate;
            }
            .area>.ball6{
                animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -26s infinite alternate,
                anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -20s infinite alternate,
                scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -20s infinite alternate;
            }
             /* 动画 */
            
            /* 在X轴上的移动 */
            @keyframes  anmiteX{
                from{
                    left: 100px;
                }
                to{
                    left: 1000px;
                }
            }
            /* 在轴上Y的移动 */
            @keyframes  anmiteY{
                from{
                    top: 100px;
                }
                to{
                    top: 600px;
                }
            }
            /* 对球进行放大和缩小在视觉上进行远近的模拟 */
            @keyframes  scale{
                0%{
                    transform: scale(0.7,0.7);
                }
                50%{
                    transform: scale(1.2,1.2);
                }
                100%{
                    transform: scale(0.7,0.7);
                }
            }
            
        </style>
        
        <div class="area">
            <div class="ball ball1"></div>
            <div class="ball ball2"></div>
            <div class="ball ball3"></div>
            <div class="ball ball4"></div>
            <div class="ball ball5"></div>
            <div class="ball ball6"></div>
        </div>
    </body>
</html>

以上是完整的代码 并添加了放大缩小的动画使得运动更加立体,运动轨迹使用塞尔曲线cubic-bezier()来定义,以下就是具体的运行结果了

进阶:

很多时候球的个数是不定的,而且需要进行悬浮小球暂停运动的操作,那么这样的需求就要使用到javascript来进行动态生成了

<script type="text/javascript">
                // nameArr 球的名称,runtime 运行一圈的时间.warmballArr 爆满的球素组
                function addBall(num,runtime){
                    let _parentbox=document.getElementsByClassName('area')[0];
                    let _innerHtml="";
                    for (let i = 0; i <num; i++) {
                    let _xtime=parseFloat(runtime/4);
                    let _ytime=parseFloat(runtime/num);
                     let _style=`
                     animation: anmiteX `+(runtime/2)+`s cubic-bezier(0.36, 0, 0.64, 1) -`+(_xtime+(i*_ytime))+`s infinite alternate,
                     anmiteY `+(runtime/2)+`s cubic-bezier(0.36, 0, 0.64, 1) -`+(i*_ytime)+`s infinite alternate,
                     scale `+runtime+`s cubic-bezier(0.36, 0, 0.64, 1) -`+(i*_ytime)+`s infinite alternate;
                     `;
                    
                        _innerHtml+=`
                        <div class=" ball`+(i+1)+` ball " Style="`+_style+`">
                        
                        </div>`
                    }
                    _parentbox.innerHTML=_innerHtml;
                }
                // 添加悬浮暂停事件
                function ballring(){
                    var items = document.getElementsByClassName("ball");
                    for (var i = 0; i < items.length; i++) {
                      items[i].addEventListener('click', function () {
                        // console.log(this)
                      })
                    }
                    for (var i = 0; i < items.length; i++) {
                      items[i].addEventListener('mouseover', function () {
                        for (j = 0; j < items.length; j++) {
                          items[j].style.animationPlayState = "paused";;
                        }
                      })
                      
                      items[i].addEventListener('mouseout', function () {
                        for (j = 0; j < items.length; j++) {
                          items[j].style.animationPlayState = "running";;
                        }
                      })
                    }
                }
            
                addBall(8,32);
                ballring();
            </script>

知识链接:

1.CSS3动画相关知识

2.塞尔曲线cubic-bezier()相关知识

码字不易,如果觉得不错给个赞咯!

原文地址:https://www.cnblogs.com/lin494910940/p/14051631.html