思路:

效果:

<html>

 

<head>

    <style>

        * {

            margin: 0;

            padding: 0;

        }

        

        .button {

            width: 30px;

            height: 30px;

            border-radius: 100%;

            background: blue;

            margin-left: 300px;

            margin-top: 50px;

            line-height: 30px;

            font-size: 1em;

            text-align: center;

            color: white;

            cursor: pointer;

        }

        

        .box {

            width: 100px;

            height: 100px;

            position: fixed;

            left: 0px;

            bottom: 0px;

        }

        /* openBox.png:一张打开的盒子图片 */

        

        .boxOpen {

            background: url('./openBox.png') no-repeat center;

            background-size: 100% 100%;

        }

        /* closeBox.png:一张关闭的盒子图片 */

        

        .boxClose {

            background: url('./closeBox.png') no-repeat center;

            background-size: 100% 100%;

        }

    </style>

    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />

</head>

 

<body>

    <!-- 放在左下角的盒子 -->

    <div class=" box boxClose" id="box"></div>

    <!-- 模拟菜单 -->

    <div id="buttonCon">

        <div class="button">

            1

        </div>

        <div class="button">

            2

        </div>

        <div class="button">

            3

        </div>

        <div class="button">

            4

        </div>

        <div class="button">

            5

        </div>

        <div class="button">

            6

        </div>

        <div class="button">

            7

        </div>

        <div class="button">

            8

        </div>

    </div>

 

    <script>

        // 获取按钮的容器

        var buttonCon = document.getElementById("buttonCon");

        // 获取盒子

        var box = document.getElementById("box");

        // 定义小球的个数

        var index = 0;

        // 委托代理事件

        buttonCon.addEventListener("click", function(e) {

            // 获取当前对象

            var target = e.target;

            // 判断当前对象样式列表中有没有button类

            if (target.classList.contains("button")) {

                // 判断盒子是否是关闭的盒子

                if (box.classList.contains("boxClose")) {

                    // 移除关闭盒子样式

                    box.classList.remove("boxClose");

                    // 增加打开盒子样式

                    box.classList.add("boxOpen");

                }

                // 创建动画小球的容器--运动时让小球容器朝下方运动,让里面的小球向左运动,这样就会使小球成弧形运动

                var ball = document.createElement("div");

                // 定义样式

                ball.style.position = "fixed"

                    // 定义在目标元素的上方

                ball.style.top = (target.offsetTop - target.offsetHeight) + "px";

                ball.style.left = target.offsetLeft;

                // 定义小球容器的大小

                ball.style.width = target.offsetWidth + "px"

                ball.style.height = target.offsetHeight + "px"

                ball.style.borderRadius = "100%"

                    // 设置为点击穿透

                ball.style.pointerEvents = "none"

                    // 设置过度动画--贝塞尔曲线

                ball.style.transition = "3s cubic-bezier(0.49,-0.3,0.75,0.41)"

 

 

                // 定义小球

                var ballIn = document.createElement("div");

                // 定义小球大小

                ballIn.style.width = target.offsetWidth + "px"

                ballIn.style.height = target.offsetHeight + "px"

                ballIn.style.borderRadius = "100%"

                ballIn.style.background = "red"

                ballIn.style.backgroundSize = "100% 100%"

                    // 定义过度效果

                ballIn.style.transition = " 3s linear"

                ballIn.innerHTML = ""

                    // 添加到dom中

                ball.appendChild(ballIn);

                document.body.appendChild(ball)

                    // 小球个数增加

                index++

                // 指定小球的落点

                setTimeout(function() {

                    // 指定小球容器的落点在y轴的底部

                    ball.style.transform = "translateY(" + (window.innerHeight - target.offsetTop - 30) + "px)"

                        // 指定小球的落点在x轴的左侧 同时旋转360度

                    ballIn.style.transform = "translateX(" + (-300 + 20) + "px) rotate(360deg)"

                        // 小球容器的过度动画结束时

                    ball.addEventListener('transitionend', function(ev) {

                        // 事件结束,小球容器删除

                        ball.remove();

                        // 因为执行两次 每次减去0.5  两次正好减去1  代表小球少一个

                        index -= 0.5

                            // 当没有小球的时候,只要有小球盒子应该一直保持打开的状态

                        if (index === 0) {

                            // 删掉打开的盒子样式

                            box.classList.remove("boxOpen")

                                // 增加关闭的盒子

                            box.classList.add("boxClose")

                        }

                    })

                });

            }

        }, false)

    </script>

</body>

 

</html>