JavaScript 运动部分

目录

运动与游戏开发

认识运动

分享到菜单案例

淡入淡出案例

缓冲运动

缓冲运动案例

 多物体运动

多物体多样式运动

链式运动

链式运动概念

案例

碰撞

打砖块

圆周运行

完美运动框架


运动与游戏开发

认识运动

动画:图像

原理:人眼能够识别的最小的时间间隔是18帧

实现动画:只需要让动画的切换时间间隔大于18帧,一般情况下,电影院里放映的电影是24帧

简单的运动:

        让一个div从左向右开始运动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0px; padding: 0px;}
        #div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 0px; top: 100px;}
    </style>
    <script>
        /* 
            问题:
                1、停不下来
                2、当速度取某些值得时候停不下来
                3、到达目的值以后,点击还会继续往前运动
                    if...else  将运动和停止分开
                4、重复点击按钮,速度加快
                    保证只有一个定时器
                    每次启动定时器之前,先将上一次定时器关闭
         */

        /* 
            运动框架:
                1、每次启动定时器之前,先将上一次定时器关闭
                2、if...else  将运动和停止分开
        */

         window.onload = function(){
             var oBtn = document.getElementById("btn1");
             var oDiv = document.getElementById("div1");

             var speed = 7;
             var timer = null;
             oBtn.onclick = function(){
                 clearInterval(timer);
                 timer = setInterval(function(){
                     if(oDiv.offsetLeft >= 500){
                         clearInterval(timer);
                     }else{
                         oDiv.style.left = oDiv.offsetLeft + speed + 'px';
                     }
                 }, 30);
             }
         }
    </script>
</head>
<body>
    <button id="btn1">开始运动</button>
    <div id="div1"></div>
</body>
</html>

分享到菜单案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 100px; height: 200px; background-color: gray; position: absolute; left: -100px; top: 400px;}
        #div1 span{width: 20px; height: 60px; background-color: orange; position: absolute; left: 100px; top: 70px; line-height: 20px;}
    </style>
    <script>
        /* 
            鼠标移入:left从 -100 => 0
            鼠标移出:left从 0 => -100
        */

        window.onload = function(){
            var oDiv = document.getElementById("div1");
            oDiv.onmouseover = function(){
                startMove(5, 0);
            }
            oDiv.onmouseout = function(){
                startMove(-5, -100);
            }
        }

        var timer = null;
        function startMove(speed, iTarget){
            var oDiv = document.getElementById("div1");
            clearInterval(timer);
            timer = setInterval(function(){
                //将运动停止和分开
                if(oDiv.offsetLeft == iTarget){
                    clearInterval(timer);
                }else{
                    oDiv.style.left = oDiv.offsetLeft + speed + 'px';
                }
            }, 30);
        }

        /* function startMove2(){
            var oDiv = document.getElementById("div1");
            var speed = -5;
            clearInterval(timer);
            timer = setInterval(function(){
                //将运动停止和分开
                if(oDiv.offsetLeft == -100){
                    clearInterval(timer);
                }else{
                    oDiv.style.left = oDiv.offsetLeft + speed + 'px';
                }
            }, 30);
        } */


    </script>
</head>
<body>
    <div id="div1">
        <span>分享到</span>
    </div>
</body>
</html>

改进1:

window.onload = function(){
            var oDiv = document.getElementById("div1");
            oDiv.onmouseover = function(){
                startMove(0);
            }
            oDiv.onmouseout = function(){
                startMove(-100);
            }
        }

        var timer = null;
        function startMove(iTarget){
            var oDiv = document.getElementById("div1");
            var speed = 5;
            if(oDiv.offsetLeft > iTarget){
                speed = -Math.abs(speed);
            }else{
                speed = Math.abs(speed);
            }
            clearInterval(timer);
            timer = setInterval(function(){
                //将运动停止和分开
                if(oDiv.offsetLeft == iTarget){
                    clearInterval(timer);
                }else{
                    oDiv.style.left = oDiv.offsetLeft + speed + 'px';
                }
            }, 30);
        }

淡入淡出案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #img1{opacity: 0.3; filter: alpha(opacity = 30); }
    </style>
    <script>
        window.onload = function(){
            var oImg = document.getElementById("img1");
            oImg.onmouseover = function(){
                //透明度由 30 -->  100
                startMove(100);
            }
            oImg.onmouseout = function(){
                //透明度由 100 --> 30
                startMove(30);
            }
        }

        //设置一个中间变量,透明度当前值
        var alpha = 30;
        var timer = null;
        function startMove(iTarget){
            var oImg = document.getElementById("img1");
            clearInterval(timer);
            var speed = 2;
            speed = iTarget > alpha ? Math.abs(speed) : -Math.abs(speed);
            timer = setInterval(function(){
                if(iTarget == alpha){
                    clearInterval(timer);
                }else{
                    alpha += speed;
                    //重新设置透明度
                    oImg.style.opacity = alpha / 100;
                    oImg.style.filter = `alpha(opacity=${alpha})`;
                }

                //document.title = alpha; /* 通过title上的数值检查alpha是否复合我们的预期 */
               

            }, 30);
        }
    </script>
</head>
<body>
    <img id="img1" src="./images/sxx1.jpg" style="width: 405px; height: 270px;">
</body>
</html>

缓冲运动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0px; padding: 0px;}
        #div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 0px; top: 200px; }
    </style>
    <script>
        /* 
            刹车

            不是物理规律的特点:速度和距离成正相关

            var speed = 距离
            var speed = (iTarget - iCur) / 8;
        */
        window.onload = function(){
            var oBtn = document.getElementById("btn1");
            var oDiv1 = document.getElementById("div1");

            oBtn.onclick = function(){
                startMove(500);
            }
        }

        var timer = null;

        function startMove(iTarget){
            var oDiv1 = document.getElementById("div1");
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (iTarget - oDiv1.offsetLeft) / 8;//速度和距离公式

                if(oDiv1.offsetLeft == iTarget){
                    clearInterval(timer);
                }else{
                    oDiv1.style.left = oDiv1.offsetLeft + speed + 'px';
                }
            },30);
        }
    </script>
</head>
<body>
    <button id="btn1">开始运动</button>
    <div id="div1"></div>
</body>
</html>

当我们添加一个speed = 500时的标志,我们会发现红色方块无法完全贴合次标志

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0px; padding: 0px;}
        #div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 0px; top: 200px; }
    </style>
    <script>
        /* 
            刹车

            不是物理规律的特点:速度和距离成正相关

            var speed = 距离
            var speed = (iTarget - iCur) / 8;
        */
        window.onload = function(){
            var oBtn = document.getElementById("btn1");
            var oDiv1 = document.getElementById("div1");

            oBtn.onclick = function(){
                startMove(500);
            }
        }

        var timer = null;

        function startMove(iTarget){
            var oDiv1 = document.getElementById("div1");
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (iTarget - oDiv1.offsetLeft) / 8;//速度和距离公式

                if(oDiv1.offsetLeft == iTarget){
                    clearInterval(timer);
                }else{
                    oDiv1.style.left = oDiv1.offsetLeft + speed + 'px';
                }
            },30);
        }
    </script>
</head>
<body>
    <button id="btn1">开始运动</button>
    <div id="div1"></div>
    <span style="width: 1px; height: 500px; background-color: black; position: absolute; left: 500px;"></span>
</body>
</html>

修改版:
 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0px; padding: 0px;}
        #div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 1000px; top: 200px; }
    </style>
    <script>
        /* 
            刹车

            不是物理规律的特点:速度和距离成正相关

            var speed = 距离
            var speed = (iTarget - iCur) / 8;

            【注】计算机最小能识别的像素时一像素
        */
        window.onload = function(){
            var oBtn = document.getElementById("btn1");
            var oDiv1 = document.getElementById("div1");

            oBtn.onclick = function(){
                startMove(500);
            }
        }

        var timer = null;

        function startMove(iTarget){
            var oDiv1 = document.getElementById("div1");
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (iTarget - oDiv1.offsetLeft) / 8;//速度和距离公式
                /* speed = Math.ceil(speed);//向上取整;但是对于反向缓冲运动来说,此方法无法解决此问题 */
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(oDiv1.offsetLeft == iTarget){
                    clearInterval(timer);
                }else{
                    oDiv1.style.left = oDiv1.offsetLeft + speed + 'px';
                }

                var oTxt1 = document.getElementById("txt1");
                oTxt1.value += speed + ',' + oDiv1.offsetLeft + '\n'
            },30);
        }
    </script>
</head>
<body>
    <button id="btn1">开始运动</button>
    <div id="div1"></div>
    <textarea name="" id="txt1" cols="30" rows="10"></textarea>
    <span style="width: 1px; height: 500px; background-color: black; position: absolute; left: 500px;"></span>
</body>
</html>

缓冲运动案例

1、匀速运动

        <1>每次启动定时器,关闭上一次定时器

        <2>if...else将运动和停止分开

2、分享到菜单        淡入淡出效果(alpha)

        startMove(iTarget);

3、缓冲运动

        var speed = (iTarget - iCur) / 8;(经过长期实验÷8动画最明显,iCur为当前位置)

        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

缓冲运动实现的缓冲菜单:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0px; padding: 0px;}
        #div1{width: 50px; height: 50px; background-color: red; position: absolute; right: 0px;}
    </style>
    <script>
        window.onload = function(){
            var oDiv = document.getElementById("div1");
            //获取居中的top值
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;  //获取滚动了的高度
            var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;  //获取可视窗口的高度
            
            var iH = parseInt(scrollTop + (windowHeight - oDiv.offsetHeight) / 2); //top居中值
            startMove(iH);

            //窗口滚动时,红色方块也靠右居中
            window.onscroll = function(){
                //获取居中的top值
                var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;  //获取滚动了的高度
                var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;  //获取可视窗口的高度
                
                var iH = parseInt(scrollTop + (windowHeight - oDiv.offsetHeight) / 2); //top居中值
                startMove(iH);
            }

            //窗口放大缩小时,红色方块也靠右居中
            window.onresize = function(){
                //获取居中的top值
                var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;  //获取滚动了的高度
                var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;  //获取可视窗口的高度
                
                var iH = parseInt(scrollTop + (windowHeight - oDiv.offsetHeight) / 2); //top居中值
                startMove(iH);
            }

        }

        var timer = null;
        function startMove(iTarget){
            var oDiv = document.getElementById("div1");
            clearInterval(timer);
            timer = setInterval(function(){
                //计算速度
                var speed = (iTarget - oDiv.offsetTop) / 8;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(oDiv.offsetTop == iTarget){
                    clearInterval(timer);
                }else{
                    oDiv.style.top = oDiv.offsetTop + speed + 'px';
                }

                document.title = oDiv.offsetTop + ',' + iTarget;  //测试
            }, 30);
        }
    </script>
</head>
<body style="height: 3000px;">
    <div id="div1"></div>
</body>
</html>

 多物体运动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{width: 100px; height: 50px; background-color: red; margin: 100px;}
    </style>
    <script>
        window.onload = function(){
            var aDivs = document.getElementsByTagName("div");

            for(var i = 0; i < aDivs.length; i++){
                aDivs[i].onmousemove = function(){
                    startMove(this, 300);
                }
                aDivs[i].onmouseout = function(){
                    startMove(this, 100);
                }
            }

        }

        /* 让谁进行运动不确定,增加一个node参数
           多物体运动,但实际上只有一个定时器
           让每一个运动的物体都有一个定时器,
        */
        var timer = null;
        function startMove(node, iTarget){
            clearInterval(timer);
            timer = setInterval(function(){
                var speed = (iTarget - node.offsetWidth) / 8;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(node.offsetWidth == iTarget){
                    clearInterval(timer);
                }else{
                    node.style.width = node.offsetWidth + speed + 'px';
                }
            }, 30);
        }
    </script>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</body>
</html>

出现的问题:当移入其中一个div后快速移入另一个div中,上一个动画被关闭,无法还原

                                        

修改版:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{width: 100px; height: 50px; background-color: red; margin: 100px;}
    </style>
    <script>
        window.onload = function(){
            var aDivs = document.getElementsByTagName("div");

            for(var i = 0; i < aDivs.length; i++){
                aDivs[i].onmouseover = function(){
                    startMove(this, 300);
                }
                aDivs[i].onmouseout = function(){
                    startMove(this, 100);
                }
            }

        }

        /* 让谁进行运动不确定,增加一个node参数
           多物体运动,但实际上只有一个定时器
           让每一个运动的物体都有一个定时器,
        */
        /* var timer = null; */
        function startMove(node, iTarget){
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                var speed = (iTarget - node.offsetWidth) / 8;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(node.offsetWidth == iTarget){
                    clearInterval(node.timer);
                }else{
                    node.style.width = node.offsetWidth + speed + 'px';
                }
            }, 30);
        }
    </script>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</body>
</html>

添加淡入淡出效果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{width: 100px; height: 50px; background-color: red; margin: 100px; opacity: 0.3; filter: alpha(opacity=30);}
    </style>
    <script>
        window.onload = function(){
            var aDivs = document.getElementsByTagName("div");

            for(var i = 0; i < aDivs.length; i++){
                aDivs[i].alpha = 30;
                aDivs[i].onmouseover = function(){
                    startMove(this, 100);
                }
                aDivs[i].onmouseout = function(){
                    startMove(this, 30);
                }
            }
        }

        // var alpha = 30;
        /* 
            在多物体运动中:
                1、定时器不可共用
                2、任何数据都不能共用
        */
        function startMove(node,iTarget){
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                var speed = (iTarget - node.alpha) / 30;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(iTarget == node.alpha){
                    clearInterval(node.timer);
                }else{
                    node.alpha += speed;

                    node.style.opacity = node.alpha / 100;
                    node.style.filter = "alpha(opacity=" + node.alpha + ")";
                }

            },30);
        }
    </script>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</body>
</html>

多物体多样式运动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 200px; height: 100px; background-color: red; border: 1px solid black;}
    </style>
    <script>
        /* 
            每隔30ms width-1
            加上border后,width+1; 原因是offsetWidth获取的不仅仅是width还会加上border
        */
        window.onload = function(){
            var oDiv = document.getElementById("div1");
            setInterval(function(){
                alert(oDiv.offsetWidth);    //获取width + border
                oDiv.style.width = oDiv.offsetWidth - 1 + 'px';
            },30);
        }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

解决加上border后width变为width+1问题:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 200px; height: 100px; background-color: red; border: 1px solid black;}
    </style>
    <script>
       /* 
            实现运动的函数里面,都用getStyle方法来获取当前有效样式
       */
        window.onload = function(){
            var oDiv = document.getElementById("div1");
            setInterval(function(){
                //获取当前值
                var iCur = parseInt(getStyle(oDiv,"width"));
                alert(iCur);
                oDiv.style.width = iCur - 1 + 'px';
            },30);
        }

        //获取当前有效样式浏览器兼容的写法
        function getStyle(node,cssStr){
            return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
        }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

多物体多样式的运动:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{width: 100px; height: 100px; background-color: red; margin: 50px;}
    </style>
    <script>
        window.onload = function(){
            var aDivs = document.getElementsByTagName("div");
            aDivs[0].onclick = function(){
                //宽变为300px
                startMove(this, "width", 300);
            }
            aDivs[1].onclick = function(){
                //高变为300px
                startMove(this, "height", 300);
            }
            aDivs[2].onclick = function(){
                //margin-left变为300px
                startMove(this, "margin-left", 300);
            }
            aDivs[3].onclick = function(){
                //font-size变为100px
                startMove(this, "font-size", 100);
            }
        }

        function startMove(node, attr, iTarget){
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                //计算速度
                var iCur = parseInt(getStyle(node,attr));
                var speed = (iTarget - iCur) / 8;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(iCur == iTarget){
                    clearInterval(node.timer);
                }else{
                    node.style[attr] = iCur + speed + 'px'; //没有attr这个样式,所以需要用'[ ]'获取attr
                }
            },30);
        }
        //获取当前有效样式浏览器兼容的写法
        function getStyle(node,cssStr){
            return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
        }
    </script>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div>div文本</div>
</body>
</html>

缺点:只能解决带px的样式

如果要添加透明度操作:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{width: 100px; height: 100px; background-color: red; margin: 50px; opacity: 0.3; filter: alpha(opacity=30);}
    </style>
    <script>
        window.onload = function(){
            var aDivs = document.getElementsByTagName("div");
            aDivs[0].onclick = function(){
                //宽变为300px
                startMove(this, "width", 300);
            }
            aDivs[1].onclick = function(){
                //高变为300px
                startMove(this, "height", 300);
            }
            aDivs[2].onclick = function(){
                //margin-left变为300px
                startMove(this, "margin-left", 300);
            }
            aDivs[3].onclick = function(){
                //font-size变为100px
                startMove(this, "font-size", 100);
            }
            aDivs[4].onmouseover = function(){
                startMove(this, "opacity", 100);
            }
            aDivs[4].onmouseout = function(){
                startMove(this, "opacity", 30);
            }
        }

        function startMove(node, attr, iTarget){
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                //计算速度
                var iCur = null;
                if(attr == 'opacity'){
                    iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
                }else{
                    iCur = parseInt(getStyle(node,attr));
                }
                var speed = (iTarget - iCur) / 8;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(iCur == iTarget){
                    clearInterval(node.timer);
                }else{
                    if(attr == "opacity"){
                        iCur += speed;
                        node.style.opacity = iCur / 100;
                        node.style.filter = "alpha(opacity" + iCur + ")";
                    }else{
                        node.style[attr] = iCur + speed + 'px'; 
                    }
                }
            },30);
        }
        //获取当前有效样式浏览器兼容的写法
        function getStyle(node,cssStr){
            return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
        }
    </script>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div>div文本</div>
    <div></div>
</body>
</html>

链式运动

链式运动概念

                      在第一个动画结束的时候,开始第二个动画

                    【注】关键点,找到第一个动画结束的时候

        回调函数:我们把函数当作参数传入,并且在合适的地方调用,叫做回调函数。在别的编程语言(C语言、C++)叫做函数指针。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{width: 100px; height: 100px; background-color: red; margin: 50px; opacity: 0.3; filter: alpha(opacity=30);}
    </style>
    <script>
        /* 
            希望实现三个动画,且为链式进行
        */
        window.onload = function(){
            var aDivs = document.getElementsByTagName("div");
            aDivs[0].onclick = function(){
                startMove(this, "width", 300, show);
            }

            function show(){
                alert(this);    //指向当前的div
                alert("运动结束了");
            }
        }

        function startMove(node, attr, iTarget, complete){ //complete = show;
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                //计算速度
                var iCur = null;
                if(attr == 'opacity'){
                    iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
                }else{
                    iCur = parseInt(getStyle(node,attr));
                }
                var speed = (iTarget - iCur) / 8;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(iCur == iTarget){
                    clearInterval(node.timer);
                    if(complete){
                        // complete(); //为了使后续代码调用方便,将show函数的指向强制改变
                        complete.call(node);
                    }
                    
                    /* 第一次运动结束的点 */
                    // alert("运动结束");
                    /* 
                        当运动结束以后,应该做什么的代码在这里不能写死。
                        【注】封装函数,形参,根据汉书不确定的值决定的
                        可以将一段代码编写的权力交给别人,在函数上声明一个形参,这个形参是用来接收从外面封装好的一个函数的。
                    */
                }else{
                    if(attr == "opacity"){
                        iCur += speed;
                        node.style.opacity = iCur / 100;
                        node.style.filter = "alpha(opacity" + iCur + ")";
                    }else{
                        node.style[attr] = iCur + speed + 'px'; 
                    }
                }
            },30);
        }
        //获取当前有效样式浏览器兼容的写法
        function getStyle(node,cssStr){
            return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
        }
    </script>
</head>
<body>
    <div></div>
</body>
</html>

修改后:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{width: 100px; height: 100px; background-color: red; margin: 50px; opacity: 0.3; filter: alpha(opacity=30);}
    </style>
    <script>
        
        window.onload = function(){
            var aDivs = document.getElementsByTagName("div");
            aDivs[0].onmouseover = function(){
                startMove(this, "width", 300, function(){
                    startMove(this, "height" ,300, function(){
                        startMove(this, "opacity", 100);
                    });
                });
            }

            aDivs[0].onmouseout = function(){
                startMove(this, "opacity", 30, function(){
                    startMove(this, "width", 100, function(){
                        startMove(this, "height", 100);
                    });
                });
            }
        }

        function startMove(node, attr, iTarget, complete){ 
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                //计算速度
                var iCur = null;
                if(attr == 'opacity'){
                    iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
                }else{
                    iCur = parseInt(getStyle(node,attr));
                }
                var speed = (iTarget - iCur) / 8;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                if(iCur == iTarget){
                    clearInterval(node.timer);
                    if(complete){
                        complete.call(node);
                    }
                }else{
                    if(attr == "opacity"){
                        iCur += speed;
                        node.style.opacity = iCur / 100;
                        node.style.filter = "alpha(opacity" + iCur + ")";
                    }else{
                        node.style[attr] = iCur + speed + 'px'; 
                    }
                }
            },30);
        }
        //获取当前有效样式浏览器兼容的写法
        function getStyle(node,cssStr){
            return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
        }
    </script>
</head>
<body>
    <div></div>
</body>
</html>

案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        /* 
            KFC 点餐系统
        */
       function KFC(food, eatFunc){
            //点餐的时候告诉他需要打包还是堂食,但不论使打包还是堂食都是出餐之后才进行
            alert("您的餐" + food + "准备好了,请您及时就餐");
            eatFunc();  //先声明,再执行此函数
       }

    //    function xiaohua(){
    //        alert("打包带走");
    //    }
    //    KFC("老北京鸡肉卷",xiaohua);

    //    function xiaoming(){
    //        alert("堂食");
    //    }

       /* var xiaoming = function(){
           alert("堂食");
       } */
       KFC("香辣鸡腿堡", function(){ //函数在此执行
           alert("堂食");
       });
    </script>
</head>
<body>
    
</body>
</html>

碰撞

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 100px; top: 200px;}
        #div2{width: 100px; height: 100px; background-color: blue; position: absolute; left: 200px;}
    </style>
    <script>
        window.onload = function(){
            var oDiv1 = document.getElementById("div1");
            var oDiv2 = document.getElementById("div2");

            /* 
                让蓝色的块可以在当前页面上被拖拽
            */
           oDiv2 .onmousedown = function(ev){
               var e = ev || window.event;
               var offsetX = e.clientX - oDiv2.offsetLeft;
               var offsetY = e.clientY - oDiv2.offsetTop;

               document.onmousemove = function(ev){
                   var e = ev || window.event;

                    //判断
                    if(konck(oDiv1, oDiv2)){
                        oDiv1.style.backgroundColor = 'black';
                    }else{
                        oDiv1.style.backgroundColor = 'red';
                    }

                   oDiv2.style.left = e.clientX - offsetX + 'px';
                   oDiv2.style.top = e.clientY - offsetY + 'px';
               }
           }
           
           document.onmouseup = function(){
               document.onmousemove = null;
           }
        }
        /* 
            找两个物体怎样才会碰撞
            思路:找两个物体绝对碰不到
        */
       function konck(node1, node2){
            var l1 = node1.offsetLeft;
            var r1 = node1.offsetLeft + node1.offsetWidth;
            var t1 = node1.offsetTop;
            var b1 = node1.offsetTop + node1.offsetHeight;

            var l2 = node2.offsetLeft;
            var r2 = node2.offsetLeft + node2.offsetWidth;
            var t2 = node2.offsetTop;
            var b2 = node2.offsetTop + node2.offsetHeight;

            if(l2 > r1 || r2 < l1 || t2 > b1 || b2 < t1){
                return false;
            }else{
                return true;
            }
       }
    </script>
</head>
<body>
    <div id="div1"></div>
    <div id="div2"></div>
</body>
</html>

打砖块

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 600px; height: 600px; border: 1px solid black; position: relative; margin: 100px auto;}
        #ball{width: 20px; height: 20px; background-color: cornflowerblue; border-radius: 50%; position: absolute; bottom: 30px; left: 290px;}
        #bat{width: 100px; height: 30px; background-color: rgb(70, 70, 105); position: absolute; border: 1px solid black; bottom: 0px; left: 250px;}
        #brick div{width: 98px; height: 18px; border: 1px solid black; float: left;}
    </style>
    <script>
        window.onload = function(){
            var oDiv = document.getElementById("div1");
            var oBall = document.getElementById("ball");
            var oBat = document.getElementById("bat");
            var oBrick = document.getElementById("brick");
            var oBricks = oBrick.getElementsByTagName("div");

            dragX(oBat);
            creatBrick(60);

            //让小球可以水平方向运动,随机一个水平方向的速度
            var speedX = parseInt(Math.random() * 4) + 3;
            //让小球可以垂直方向运动,随机一个垂直方向的速度
            var speedY = -(parseInt(Math.random() * 3) + 5);
            setInterval(function(){
                oBall.style.left = oBall.offsetLeft + speedX +'px';
                oBall.style.top = oBall.offsetTop + speedY +'px';
                if(oBall.offsetLeft >=580 || oBall.offsetLeft <= 0 ){
                    speedX *= -1;
                }
                if(oBall.offsetTop <= 0){
                    speedY *= -1;
                }
                if(oBall.offsetTop >= 580){
                    alert("GAME OVER");
                    window.location.reload();
                }

                /* 进行碰撞检测 */
                //1、小球和拍子的碰撞检测
                if(konck(oBall, oBat)){
                    speedY *= -1;
                }

                //2、小球和砖块发生碰撞
                for(var i = 0; i < oBricks.length; i++){
                    if(konck(oBricks[i], oBall)){
                        speedY *= -1;
                        //砖块要被销毁
                        oBrick.removeChild(oBricks[i]);
                        break;
                    }
                }
            },30);

        }
        function dragX(node){
            node.onmousedown = function(ev){
                var e = ev || window.event;
                var offsetX = e.clientX - node.offsetLeft;
                
                document.onmousemove = function(ev){
                    var e = ev || window.event;
                    var l = e.clientX - offsetX;
                    //限制出界
                    if(l <= 0){
                        l = 0;
                    }
                    if(l >= 500){
                        l = 500;
                    }
                    node.style.left = l + 'px';
                }
            }
            document.onmouseup = function(){
                document.onmousemove = null;
            }
        }

        //创建砖块 n:创建n个砖块
        /* 
           文档流的转换:
            让相对定位 转 绝对定位
        */
        function creatBrick(n){
            var oBrick = document.getElementById("brick");
            for(var i = 0; i < n; i++){
                var node = document.createElement("div");
                node.style.backgroundColor = randomColor();
                oBrick.appendChild(node);
            }

            var oBricks = oBrick.getElementsByTagName("div");
            for(var i = 0; i < oBricks.length; i++){
                oBricks[i].style.left = oBricks[i].offsetLeft + 'px';
                oBricks[i].style.top = oBricks[i].offsetTop + 'px';
            }
            for(var i = 0; i < oBricks.length; i++){
                oBricks[i].style.position = 'absolute';
            } 
        }

        function randomColor(){
            var str = "rgba(" + parseInt(Math.random() * 256) + "," + parseInt(Math.random() * 256) + "," + parseInt(Math.random() * 256) + "," + parseInt(Math.random() * 256) + ")";
            return str;
        }

        /* 
            找两个物体怎样才会碰撞
            思路:找两个物体绝对碰不到
        */
       function konck(node1, node2){
            var l1 = node1.offsetLeft;
            var r1 = node1.offsetLeft + node1.offsetWidth;
            var t1 = node1.offsetTop;
            var b1 = node1.offsetTop + node1.offsetHeight;

            var l2 = node2.offsetLeft;
            var r2 = node2.offsetLeft + node2.offsetWidth;
            var t2 = node2.offsetTop;
            var b2 = node2.offsetTop + node2.offsetHeight;

            if(l2 > r1 || r2 < l1 || t2 > b1 || b2 < t1){
                return false;
            }else{
                return true;
            }
       }
    </script>
</head>
<body>
    <div id="div1">
        <div id="ball"></div>
        <div id="bat"></div>
        <div id="brick">
            <!-- <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div> -->
        </div>
    </div>
</body>
</html>

圆周运行

画圆的步骤:(同圆规画圆一致)

        1、确定圆心

        2、确定半径

        3、旋转 (顺时针)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{position: absolute; width: 30px; height: 30px; background-color: red;}
    </style>
    <script>
        /* 
            1弧度 = Math.PI / 180;
         */
         window.onload = function(){
             var oDiv = document.getElementById("div1");
            //圆心的位置
             var X = 400;
             var Y = 400;

             var r = 200;
             var i = 0;    //代表转过的弧度
             setInterval(function(){
                i++;
                var radian = i * Math.PI / 180;
                var a = Math.sin(radian) * r;
                var b = Math.cos(radian) * r;

                //计算圆上的点的具体位置
                oDiv.style.left = X + a + 'px';
                oDiv.style.top = Y - b + 'px';

                //只设置以上的步骤是没有圆周运动的轨迹,可以利用结点的创建
                var node = document.createElement("div");
                node.style.width = '5px';
                node.style.height = '5px';
                node.style.backgroundColor = 'black';
                node.style.position = 'absolute';
                node.style.left = oDiv.offsetLeft + 'px';
                node.style.top = oDiv.offsetTop + 'px';
                document.body.appendChild(node);
             }, 30);

         }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

完美运动框架

设置样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 100px; height: 100px; background-color: red;}
    </style>
    <script>
        window.onload = function(){
            var oDiv1 = document.getElementById("div1");
            oDiv1.onclick = function(){
                setStyle(this, 'width', '300px');
                setStyle(this, 'height', '300px');
                setStyle(this, 'backgroundColor', 'blue');
            }
        }

        //设置css样式   必须使用这个方法进行修改
        function setStyle(node, attr, value){
            node.style[attr] = value;
        }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

设置样式(多个)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 100px; height: 100px; background-color: red;}
    </style>
    <script>
        window.onload = function(){
            var oDiv1 = document.getElementById("div1");
            oDiv1.onclick = function(){
                setStyle(this, 'width', '300px');
                setStyle(this, 'height', '300px');
                setStyle(this, 'backgroundColor', 'blue');
            }
        }

        //设置css样式   必须使用这个方法进行修改
        function setStyle(node, attr, value){
            node.style[attr] = value;
        }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

完美运动框架

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 100px; height: 100px; background-color: red; opacity: 1; filter: alpha(opacity=100);}
    </style>
    <script>
        window.onload = function(){
            var oDiv1 = document.getElementById("div1");
            /* 
                宽高透明度同时发生变化
            */
           oDiv1.onmouseover = function(){
            //    /* 
            //     这两个函数无法同时执行,因为每一个运动只有一个定时器,多次调用只能有一个运动生效
            //    */
            //    startMove(this, 'width', 300);  
            //    startMove(this, 'height', 300);

                startMove(this,{
                    width: 300,
                    height: 300,
                    opacity: 30
                });
           }

           oDiv1.onmouseout = function(){
            startMove(this,{
                    width: 100,
                    height: 100,
                    opacity: 100
                });
           }
        }

        function startMove(node, cssObj, complete){ 
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                for(var attr in cssObj){
                    /* 每隔30ms将所有的css样式都改变一次 */
                    var iTarget = cssObj[attr];
                    //计算速度
                    var iCur = null;
                    if(attr == 'opacity'){
                        iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
                    }else{
                        iCur = parseInt(getStyle(node,attr));
                    }
                    var speed = (iTarget - iCur) / 8;
                    speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

                    if(iCur == iTarget){
                        clearInterval(node.timer);
                        if(complete){
                            complete.call(node);
                        }
                    }else{
                        if(attr == "opacity"){
                            iCur += speed;
                            node.style.opacity = iCur / 100;
                            node.style.filter = "alpha(opacity" + iCur + ")";
                        }else{
                            node.style[attr] = iCur + speed + 'px'; 
                        }
                    }
                }
            },30);
        }
        //获取当前有效样式浏览器兼容的写法
        function getStyle(node,cssStr){
            return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
        }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

问题:

        当宽高变化不为等比例的时候,先达到目的值的那个会关闭定时器

解决:当所有的动画到达目的值,才能关闭定时器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{width: 100px; height: 100px; background-color: red; opacity: 1; filter: alpha(opacity=100);}
    </style>
    <script>
        window.onload = function(){
            var oDiv1 = document.getElementById("div1");
                startMove(this,{
                    width: 300,
                    height: 102,  
                    opacity: 30
                });
           }

           oDiv1.onmouseout = function(){
            startMove(this,{
                    width: 100,
                    height: 100,
                    opacity: 100
                });
           }
        }

        function startMove(node, cssObj, complete){ 
            clearInterval(node.timer);
            node.timer = setInterval(function(){
                var isEnd = true;   //假设所有的动画都到达目的值
                for(var attr in cssObj){
                    /* 每隔30ms将所有的css样式都改变一次 */
                    var iTarget = cssObj[attr];
                    //计算速度
                    var iCur = null;
                    if(attr == 'opacity'){
                        iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
                    }else{
                        iCur = parseInt(getStyle(node,attr));
                    }
                    var speed = (iTarget - iCur) / 8;
                    speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                
                    if(attr == "opacity"){
                        iCur += speed;
                        node.style.opacity = iCur / 100;
                        node.style.filter = "alpha(opacity" + iCur + ")";
                    }else{
                        node.style[attr] = iCur + speed + 'px'; 
                    }

                    if(iCur != iTarget){
                        isEnd = false;
                    }
                }

                if(isEnd){
                    clearInterval(node.timer);
                    if(complete){
                        complete.call(node);
                    }
                }
            },30);
        }
        //获取当前有效样式浏览器兼容的写法
        function getStyle(node,cssStr){
            return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
        }
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值