css3的两个不同贝塞尔曲线动画怎么衔接起来?

我现在要做一个动效,由两个css3动画衔接出来的。有个方块A,第一阶段是匀速运动,第二阶段是减速运动到目标点。期望是:方块A在匀速运动完以后,进入减速运动,减速运动的起始速率和匀速运动保持一致。这样两个动画组合起来才会流畅。

clipboard.png

做了一个测试页面,借用了jquery.transit.js做css3动画,蓝色区域和灰色区域都是500px宽,蓝色区域匀速运动,灰色区域减速运动。

clipboard.png

clipboard.png

现在遇到的问题是:方块A,B,C都是1000ms从蓝色区域运动完,但是进入灰色区域后,A和C的速率明显突变了一下,而不是从原来的匀速速率过渡过来的。为了测试方便,方块B一直是匀速运动。

线上测试地址为:https://codepen.io/quiettroja...

为了让方块C的减速运动的起始速率和匀速比较接近,我将方块C的减速运动时间调整为2000ms(匀速运动持续时间为1000ms),但是还是明显没有衔接上。如果用定时器做动画,这个头疼的速率衔接问题肯定能解决,但是现在更希望用css3动画来做,一来方便,二来性能高。怎么办呢?

阅读 3.7k
4 个回答

用补间动画库,kute.js,tween.js

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .wrap{width: 1000px; margin: 100px auto; height: 300px; background: linear-gradient(to right, #05afd1 50%, #ccc 50%);}
            .wrap div{width: 50px;height: 50px; margin-bottom: 20px; background: red; color: #FFF; text-align: center; line-height: 50PX;}
        </style>
    </head>
    <body>
        <div class="wrap">
            <div class="box1">1</div>
            <div class="box2">2</div>
            <div class="box3">3</div>
        </div>
        <script src = 'https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js'></script>
        <script>
            var t =new TimelineMax();
            t.staggerTo('.wrap div',1,{x:500,ease:Linear.ease,
            onComplete :function(){
                t.staggerTo('.wrap div',1,{x:1000,ease:Cubic.easeOut});
            }},0);
        </script>
    </body>
</html>

不知道是不是你要的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #div1{
            width: 200px;
            height: 200px;
            background:red;
            position: absolute;
            left: 0;
        }
    </style>
    <script>
        window.onload = function () {
            var oBtn = document.getElementById('btn');
            var oDiv = document.getElementById('div1');
            var timer = null;
            oBtn.onclick = function () {
                var start = 0;
                speed = 500 / 30;
                clearInterval(timer);
                timer = setInterval(() => {
                    target = start += speed;
                    oDiv.style.left = target + 'px';
                    if (parseFloat(oDiv.style.left) == 500) {
                        clearInterval(timer)
                        timer = setInterval(() => {
                            speed *= 0.99;
                            target = start += speed;
                            oDiv.style.left = target + 'px';
                            if (parseFloat(oDiv.style.left) >= 998) {
                                oDiv.style.left = Math.floor(target) + 'px';
                                clearInterval(timer);
                            }
                        }, 10);
                    }

                }, 10);
            };
        };
    </script>
</head>
<body>
    <input type="button" value="开始" id="btn">
    <div id="div1"></div>
</body>
</html>

用小学数学模拟了下,剩下的效果就自己调吧。感谢我小学老师当年养猪之余交给我了这么深奥的数学…… 对了初中老师告诉我,你这个效果就相当于匀速溜冰受到了一个摩擦力慢慢停下来,停下来所用的距离将好就是全程的一半,牛老师(牛顿),有公式,我没学会,就这么粗暴模拟你了下。

http://cubic-bezier.com/#.21,...

图片描述

第一段 用的是 linear,就是图里的蓝色直线图
第二段 用的是 自定义 bezier,是 红色曲线图

从图形化的角度来解释,之所以视觉有突变,是因为这两段线拼在一起 在拼接点上不连续(斜率不一致)
最好的解决方案是 第二段用 ease-out,这样两段线拼一起,在拼接点上是斜率更接近,视觉连续性更好

要真正连续,要用数学方法来计算参数,这个我也搞不定啦

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题