• js学习总结----弹性势能动画之抛物线运动


    抛物线运动就是:当拖拽结束的时候,我们让当前的元素同时水平运动+垂直运动

    在同样的移动距离下,我们鼠标移动的速度快,move方法触发的次数少,相反移动的速度慢,move方法触发的次数就多->浏览器对于每一次的move行为的触发都是由一个最小时间的

    通过观察,我们发现一个事情:水平方向我们盒子在结束拖拽的时候移动的速度和移动的距离没有必然的联系,和开始拖拽的速度也没有必然的联系,只和最后一次即将松开的那一瞬间鼠标的速度是有关系的,最后瞬间鼠标如果移动的快,我们水平运动的距离和速度也是比较大的。->获取鼠标最后一次即将松开时候的速度。

    在JS盒子模型中,offsetLeft是获取当前元素的左偏移,获取到的值永远不会出现小数,  他会把真实的left值按照小数点的四舍五入进行计算

    具体代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            *{
                margin:0;
                padding:0;
            }
            html,body{
                100%;
                height:100%;
            }
            #box{
                position:absolute;
                top:50%;
                left:50%;
                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='box'>
            
        </div>
        <script>
            //JS实现让当前的元素在屏幕居中的位置
            var box = document.getElementById('box');
            // 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>
  • 相关阅读:
    对面向对象设计原则的总结
    sql server连接字符串
    js页面加载进度条
    Yui.Compressor高性能ASP.NET开发:自动压缩CSS、JS
    asp.net利用多线程执行长时间的任务,客户端显示出任务的执行进度的示例(一)_转
    asp.net删除目录,Session丢失
    extjs ComboBox使用注意
    转:使Eclipse的智能感知可以像 Visual Studio 一样快速提示
    Android ContentProvider 填删改查 实例
    Windows Phone StackPanel 布局示例
  • 原文地址:https://www.cnblogs.com/diasa-fly/p/7244638.html
Copyright © 2020-2023  润新知