首頁  >  文章  >  web前端  >  JavaScript中彈性勢能動畫之關於拋物線運動的程式碼案例

JavaScript中彈性勢能動畫之關於拋物線運動的程式碼案例

黄舟
黄舟原創
2017-07-27 16:30:591740瀏覽

拋物線運動就是:當拖曳結束的時候,我們讓當前的元素同時水平運動+垂直運動

在同樣的移動距離下,我們滑鼠移動的速度快,move方法觸發的次數少,相反移動的速度慢,move方法觸發的次數就多->瀏覽器對於每一次的move行為的觸發都是由一個最小時間的

透過觀察,我們發現一個事情:水平方向我們盒子在結束拖曳的時候移動的速度和移動的距離沒有必然的聯繫,和開始拖曳的速度也沒有必然的聯繫,只和最後一次即將放開的那一瞬間滑鼠的速度是有關係的,最後瞬間滑鼠如果移動的快,我們水平移動的距離和速度也是比較大的。 ->取得滑鼠最後一次即將放開時候的速度。

在JS盒子模型中,offsetLeft是取得目前元素的左偏移,得到到的值永遠不會出現小數,  他會把真實的left值按照小數點的四捨五入進行計算

具體程式碼如下:##

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        html,body{
            width:100%;
            height:100%;
        }
        #box{
            position:absolute;
            top:50%;
            left:50%;
            width:200px;
            height:200px;
            background:#ff6600;
            margin:-100px 0 0 -100px;
            cursor:move;
            /*
                不知道宽高的情况下的居中
            position:absolute;
            top:0;
            left:0;
            right:0;
            bottom:0;
            margin:auto;
            */    
        }
    </style>
</head>
<body>
    <div id=&#39;box&#39;>
        
    </div>
    <script>
        //JS实现让当前的元素在屏幕居中的位置
        var box = document.getElementById(&#39;box&#39;);
        // box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight)-box.offsetHeight)/2 + "px";

        // box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth)-box.offsetWidth)/2 + "px";
        //拖拽的原理
        /*
            当鼠标在盒子上按下的时候,我们开始拖拽(给盒子绑定onmousemove和onmouseup),当鼠标移动的时候,我们计算盒子的最新位置
            当鼠标抬起的时候说明拖拽结束了,我们的move和up就没用了,我们再把这两个方法移除
        */
        box.onmousedown = down;
        function down(e){
            e = e || window.event;
            //记录开始位置的信息
            this["strX"] = e.clientX;
            this["strY"] = e.clientY;
            this["strL"] = parseFloat(this.style.left);
            this["strT"] = parseFloat(this.style.top);
            //给元素绑定移动和抬起的事件
            if(this.setCapture){
                this.setCapture()//把当前的鼠标和this绑定在一起
                this.onmousemove = move;
                this.onmouseup= up;
            }else{
                var _this = this;
                document.onmousemove = function(e){
                    // move(e)//这个里面的this是window
                    move.call(_this,e);
                }
                    ;
                document.onmouseup= function(e){
                    up.call(_this,e);
                };
            }
            //当盒子运动中我们想要执行下一次拖拽,我们按下鼠标,但是由于盒子还是运动着呢,导致鼠标抓不住盒子->在按下的同时我们应该停止盒子的运动
            window.clearInterval(this.flyTimer);
            window.clearInterval(this.dropTimer);
            
        }
        function move(e){
            e = e || window.event;
            var curL = (e.clientX-this["strX"])+this["strL"];
            var curT = (e.clientY-this["strY"])+this["strT"];
            //边界判断
            var minL = 0,minT = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth,maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight;
            curL = curL < minL ? minL :(curL > maxL ? maxL : curL);
            curT = curT < minT ? minT :(curT > maxT ? maxT : curT)
            this.style.left = curL + "px";
            this.style.top = curT + "px";

            //计算我们水平方向移动的速度
            /*
                在浏览器最小反应时间内触发一次move,我们都记录一下当前盒子的位置,让当前的位置-上一次记录的位置=当前最后一次的偏移
            */
            if(!this.pre){
                this.pre = this.offsetLeft;
            }else{
                this.speedFly = this.offsetLeft - this.pre;
                this.pre = this.offsetLeft;
            }
        }
        function up(e){
            if(this.releaseCapture){
                this.releaseCapture();//把当前的鼠标和盒子解除绑定
                this.onmousemove = null;
                this.onmouseup= null;
            }else{
                document.onmousemove = null;
                document.onmouseup= null;
                //这样绑定的话,move和up绑定的this都是document
            }
            //当鼠标离开结束拖拽的时候,我们开始进行水平方向的动画运动
            fly.call(this);
            //当鼠标离开结束拖拽的时候,我们开始进行垂直方向的动画运动
            drop.call(this);
            
        }
        //当鼠标移动过快的时候,我们的鼠标会脱离盒子,导致盒子的mousemove和mouseup事件都移除不到->"鼠标焦点丢失"
        //在IE和火狐浏览器中,我们用一个方法把盒子和鼠标绑定在一起即可。
        //鼠标再快也跑不出去文档:我们把mousemove和mouseup绑定给document
        
        
        function fly(){
            //this->当前要操作的盒子
            var _this = this;
            _this.flyTimer = window.setInterval(function(){
                //我们运动的速度是一直在减慢的,一直到停止("指数衰减运动")
                //this->window
                //盒子停止运动,清除定时器:利用offsetLeft获取的值不会出现小数,对小数部分进行了四舍五入,所以我们加上或者减去一个小于0.5的速度值,其实对于盒子本身的位置并没有发生实质的改变,我们认为此阶段的盒子就停止运动了。

                if(Math.abs(_this.speedFly)<0.5){
                    window.clearInterval(_this.flyTimer);
                    return;
                }
                _this.speedFly*=0.98;
                var curL = _this.offsetLeft + _this.speedFly;
                var minL = 0,maxL = (document.documentElement.clientWidth || document.body.clientWidth) - _this.offsetWidth;
                if(curL>=maxL){
                    _this.style.left = maxL + "px";
                    _this.speedFly*=-1;
                }else if(curL<=minL){
                    _this.style.left = minL + "px";
                    _this.speedFly*=-1;
                }else{
                    _this.style.left = curL;
                }
            },10)
            

        }

        function drop(){
            var _this = this;
            _this.dragFlag = 0;
            _this.dropTimer = window.setInterval(function(){
                if(_this.dragFlag>1){//到底的时候dragFlag就大于1了
                    window.clearInterval(_this.dropTimer);
                    return;
                }
                _this.dropSpeed = !_this.dropSpeed ? 9.8 : _this.dropSpeed + 9.8;
                //衰减
                _this.dropSpeed*=0.98;
                var curT = _this.offsetTop + _this.dropSpeed;
                var maxT = (document.documentElement.clientHeight || document.body.clientHeight) - _this.offsetHeight;
                if(curT >= maxT){// 到底了
                    _this.style.top = maxT + "px";
                    _this.dropSpeed*=-1;
                    _this.dragFlag++;
                }else{
                    _this.style.top = curT + "px";
                    _this.dragFlag = 0;
                }
            })
            
        }
    </script>
</body>
</html>


 

#

以上是JavaScript中彈性勢能動畫之關於拋物線運動的程式碼案例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn