js-運動總結(常見運動效果)

  1. 勻速運動
  2. 加速運動
  3. 緩衝運動
  4. 碰撞運動
  5. 重力運動
  6. 多物體多值多鏈式運動框架

1. 勻速運動

速度isSpeed是個定值

function startmov(obj) {
            clearInterval(timer);
            var isSpeed = 10;
            timer = setInterval(function () {
                obj.style.left = obj.offsetLeft + isSpeed + 'px';
            },30);
        }

2. 變速運動

核心就是isSpeed每次執行發生改變

// 變速運動
        function starSpeedChangeMove(obj,target) {
            clearInterval(timer);
            var isSpeed;
            timer = setInterval(function () {
                isSpeed = (target - obj.offsetLeft) / 15;
                isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
                obj.style.left = obj.offsetLeft + isSpeed + 'px';
            },30);
        }
應用(伸縮欄)
<!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>
    .wrapper{
        position : absolute;
        top: 200px;
        left: -400px;
        width: 400px;
        height: 100px;
        background: yellowgreen;
    }
    .demo{
        position: absolute;
        top: 0;
        left: 400px;
        width: 40px;
        height: 100px;
        background: yellow;
    }
    </style>
</head>
<body>
    
    <div class="wrapper">
        <div class="demo">

        </div>
    </div>

    <script>

        var oDivDemo = document.getElementsByClassName('wrapper')[0];
        var timer = null;
        oDivDemo.onmouseenter = function () {
            starSpeedChangeMove(this,0);
        }
        oDivDemo.onmouseleave = function () {
            
            starSpeedChangeMove(this,-400);
        }
        
        function starSpeedChangeMove(obj,target) {
            clearInterval(timer);
            var isSpeed;
            timer = setInterval(function () {
                isSpeed = (target - obj.offsetLeft) / 15;
                isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
                obj.style.left = obj.offsetLeft + isSpeed + 'px';
            },30);
        }
    </script>
</body>
</html>

3. 緩衝運動

顧名思義,所謂緩衝,就是說速度不同;在一定條件下,距離越大,速度越大;距離越小,速度也就越小。
也就是跟變速運動差不多代碼

4.碰撞運動(彈性運動)

在發生碰撞的時候,我們把對應的x,y方向的速度乘以"摩擦係數"

// 彈性運動
        function starMove (obj, target) {
            clearInterval(obj.timer);
            var isSpeed = 20;
            var a, u = 0.8;  // u表示摩擦係數
            obj.timer = setInterval(function (){
                a = (target - obj.offsetLeft) / 15;
                isSpeed = isSpeed + a;
                isSpeed = isSpeed * 0.9;
                if(Math.abs(isSpeed) < 1 && Math.abs(target - obj.offsetLeft) < 1){
                    clearInterval(obj.timer);
                }else{
                    obj.style.left = obj.offsetLeft + isSpeed + 'px'; 
                }
                
                
            },30);
        }
應用(彈性導航欄)
<!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>
        *{
            margin: 0px;
            padding: 0px;
            list-style: none;
        }
        ul{
            position: relative;
            width: 600px;
            height: 80px;
            /* border: 1px solid #000; */
            margin : 100px auto 0;
        }
        ul li.nav{
            width: 148px;
            height: 78px;
            border: 1px solid #000;
            color : #000;
            text-align: center;
            line-height: 78px;
            float: left;
        }
        ul li.bg{
            position: absolute;
            top: 0px;
            left: 0px;
            width: 150px;
            height: 80px;
            background: rgb(214, 49, 49);
            z-index: -1;
        }
    </style>
</head>
<body>
    
    
    <ul>
        <li class="nav">ES6</li>
        <li class="nav">Webpack</li>
        <li class="nav">Vue</li>
        <li class="nav">Node</li>
        <li class="bg"></li>
    </ul>
    
    <script>
        
        var oLi = document.getElementsByTagName('li');
        var oBg = document.getElementsByClassName('bg')[0];
        var oLiArr = Array.prototype.slice.call(oLi, 0);
        oLiArr.forEach(function (ele, index){
            ele.onmouseenter = function (){
                starMove(oBg,this.offsetLeft);
            }
        });
        
        function starMove (obj, target) {
            clearInterval(obj.timer);
            var isSpeed = 20;
            var a, u = 0.8;  // u表示摩擦係數
            obj.timer = setInterval(function (){
                a = (target - obj.offsetLeft) / 15;
                isSpeed = isSpeed + a;
                isSpeed = isSpeed * 0.9;
                if(Math.abs(isSpeed) < 1 && Math.abs(target - obj.offsetLeft) < 1){
                    clearInterval(obj.timer);
                }else{
                    obj.style.left = obj.offsetLeft + isSpeed + 'px'; 
                }
                
                
            },30);
        }
    </script>
</body>
</html>

5. 重力運動

// targetSpeedX,targetSpeedY 表示的是x,y速度矢量值
        function starMove (obj,targetSpeedX,targetSpeedY){
            clearInterval(obj.timer);
            var iSpeedX,
                iSpeedY,
                g = 10,     // 重力加速度
                u = 0.8;   // 碰撞時速度損失
            iSpeedX = (typeof targetSpeedX == 'undefined' ? 6 : targetSpeedX),
            iSpeedY = (typeof targetSpeedY == 'undefined' ? 8 : targetSpeedY);
            console.log(iSpeedY,iSpeedX);
            obj.timer = setInterval(function (){
                iSpeedY += g;
                var newLeft = obj.offsetLeft + iSpeedX,
                    newTop = obj.offsetTop + iSpeedY;
                // 邊界處理
                if(newTop >= document.documentElement.clientHeight - obj.offsetHeight){
                    iSpeedY *= -1;
                    iSpeedY *= u;
                    iSpeedX *= u;
                    newTop = document.documentElement.clientHeight - obj.offsetHeight;

                }
                if(newTop <= 0){
                    iSpeedY *= -1;
                    iSpeedY *= u;
                    iSpeedX *= u;
                    newTop = 0;
                }
                if(newLeft >= document.documentElement.clientWidth - obj.offsetWidth){
                    iSpeedX *= -1;
                    iSpeedX *= u;
                    newLeft = document.documentElement.clientWidth - obj.offsetWidth;
                }
                if(newLeft <= 0){
                    iSpeedX *= -1;
                    iSpeedX *= u;
                    newLeft = 0; 
                }
                // 判斷結束條件
                if(Math.abs(document.documentElement.clientHeight-obj.offsetHeight-newTop) < 1 && Math.abs(iSpeedY) < 1){
                    clearInterval(obj.timer); 
                }else{
                    obj.style.left = newLeft + 'px';
                    obj.style.top = newTop + 'px';
                }
            },30);
        }
應用(拖拽拋出效果)
<!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>
        body{
            overflow: hidden;
        }
        .demo{
            position: absolute;
            left: 0px;
            top: 0px;
            width: 100px;
            height: 100px;
            border-radius: 50%;
            background: #000;
        }
    </style>
</head>
<body>
    
    <div class="demo"></div>
    <script>
        var oDiv = document.getElementsByClassName('demo')[0];

        // oDiv.onclick = function (){
        //     starMove(this,1,1); 
        // }
        var lastX = oDiv.offsetLeft,
            lastY = oDiv.offsetTop;
        oDiv.onmousedown = function (e) {
            var event = e || window.event;
            var disX = event.clientX - this.offsetLeft,
                disY = event.clientY - this.offsetTop,
                that = this;
            var iSpeedX = 0,
                iSpeedY = 0;
            document.onmousemove = function (e) {

                var newLeft = e.clientX - disX,
                    newTop = e.clientY - disY;
                    iSpeedX = newLeft - lastX,
                    iSpeedY = newTop - lastY,
                    lastX = newLeft,
                    lastY = newTop;
                that.style.left = newLeft + 'px';
                that.style.top = newTop + 'px';
                document.onmouseup = function () {
                    document.onmousemove = null;
                    document.onmouseup = null;
                    //iSpeedX,iSpeedY 相當於是速度的方向差值  正負表示方向
                    starMove(that,iSpeedX,iSpeedY);
                }
            }
        }

        // 模擬重力場   
        // targetSpeedX,targetSpeedY 表示的是x,y速度矢量值
        function starMove (obj,targetSpeedX,targetSpeedY){
            clearInterval(obj.timer);
            var iSpeedX,
                iSpeedY,
                g = 10,     // 重力加速度
                u = 0.8;   // 碰撞時速度損失
            iSpeedX = (typeof targetSpeedX == 'undefined' ? 6 : targetSpeedX),
            iSpeedY = (typeof targetSpeedY == 'undefined' ? 8 : targetSpeedY);
            console.log(iSpeedY,iSpeedX);
            obj.timer = setInterval(function (){
                iSpeedY += g;
                var newLeft = obj.offsetLeft + iSpeedX,
                    newTop = obj.offsetTop + iSpeedY;
                // 邊界處理
                if(newTop >= document.documentElement.clientHeight - obj.offsetHeight){
                    iSpeedY *= -1;
                    iSpeedY *= u;
                    iSpeedX *= u;
                    newTop = document.documentElement.clientHeight - obj.offsetHeight;

                }
                if(newTop <= 0){
                    iSpeedY *= -1;
                    iSpeedY *= u;
                    iSpeedX *= u;
                    newTop = 0;
                }
                if(newLeft >= document.documentElement.clientWidth - obj.offsetWidth){
                    iSpeedX *= -1;
                    iSpeedX *= u;
                    newLeft = document.documentElement.clientWidth - obj.offsetWidth;
                }
                if(newLeft <= 0){
                    iSpeedX *= -1;
                    iSpeedX *= u;
                    newLeft = 0; 
                }
                // 判斷結束條件
                if(Math.abs(document.documentElement.clientHeight-obj.offsetHeight-newTop) < 1 && Math.abs(iSpeedY) < 1){
                    clearInterval(obj.timer); 
                }else{
                    obj.style.left = newLeft + 'px';
                    obj.style.top = newTop + 'px';
                }
            },30);
        }
    
    </script>
</body>
</html>

6. 多物體多值多鏈式運動框架

多物體運動:
讓每一個運動的物體擁有自己的定時器 定時器獨立
把定時器作爲對象的屬性 讓定時器獨立

鏈式運動
上一個動作結束 進入到下一個動作
解決 : 在運動函數上加一個參數,參數代表回調函數

參數說明:obj 對應元素,
json 對象, 屬性是改變的樣式,比如 width height opacity
callback 回調函數 可以進行多個動作發生
小技巧: opacity 改變的時候,可以把isSpeed擴大100倍,最後在縮小100倍

function startMove(obj, json, callback){
            clearInterval(obj.timer);
            obj.timer = setInterval(function (){
                var oBstop = true,
                    isSpeed,
                    iCur;
                for(var attr in json){
                    if(attr == 'opacity'){
                        iCur = parseFloat(getStyle(obj,attr)) * 100;
                    }else{
                        iCur = parseInt(getStyle(obj,attr));
                    }
                    isSpeed = (json[attr] - iCur) / 7;
                    isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
                    if(attr == 'opacity'){
                        obj.style.opacity = (isSpeed + iCur) / 100;
                    }else{
                        obj.style[attr] = (isSpeed + iCur) + 'px';
                    }
                    if(json[attr] != iCur){
                        oBstop = false;
                    }
                }
                if(oBstop){
                    clearInterval(obj.timer);
                    typeof callback == 'function' ? callback() : "";
                }
            },30);
        }
demo(具體用法)
<!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>
        div{
            position : absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background : red;
            opacity: 1;
            border : 1px solid #000;
            margin: 100px;
        }
        .top {
            top : 100px;
        }
        .buttom {
            bottom : 100px;
        }
    </style>
</head>
<body>
    
    <div class="top">1</div>
    <div class="buttom">2</div>
    <script>
        

        var oDiv = document.getElementsByTagName('div');
        var timer = null;
        var targetObj = {
            width : 400,
            height : 400,
            opacity : 20,
            left : 200,
            top : 200
        }
        oDiv[0].onclick = function (){
            startMove(this,targetObj,function (){
                console.log('this == ', this);
                startMove(oDiv[1],targetObj);
            });
            console.log(222);
        }
        // 多物體多鏈式運動框架
        
        function getStyle (obj, attr) {
            if(obj.currentStyle){
                return obj.currentStyle[attr];
            }else{
                return window.getComputedStyle(obj,false)[attr];
            }
        }
        function startMove(obj, json, callback){
            clearInterval(obj.timer);
            obj.timer = setInterval(function (){
                var oBstop = true,
                    isSpeed,
                    iCur;
                for(var attr in json){
                    if(attr == 'opacity'){
                        iCur = parseFloat(getStyle(obj,attr)) * 100;
                    }else{
                        iCur = parseInt(getStyle(obj,attr));
                    }
                    isSpeed = (json[attr] - iCur) / 7;
                    isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
                    if(attr == 'opacity'){
                        obj.style.opacity = (isSpeed + iCur) / 100;
                    }else{
                        obj.style[attr] = (isSpeed + iCur) + 'px';
                    }
                    if(json[attr] != iCur){
                        oBstop = false;
                    }
                }
                if(oBstop){
                    clearInterval(obj.timer);
                    typeof callback == 'function' ? callback() : "";
                }
            },30);
        }
    </script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章