zoukankan      html  css  js  c++  java
  • 6弹性势能动画

    实现一个JS弹性势能动画效果代码:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>弹性势能动画</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
    
            html, body {
                width: 100%;
                height: 100%;
                background: #e1e1e1;
                overflow: hidden;
            }
    
            #mark {
                position: absolute;
                top: 20px;
                left: 10px;
                width: 100px;
                height: 100px;
                cursor: move;
                background: green;
            }
        </style>
    </head>
    <body>
    <div id="mark"></div>
    <script charset="utf-8" type="text/javascript" src="jss/event.js"></script>
    <script type="text/javascript">
        var mark = document.getElementById("mark");
        var winW = document.documentElement.clientWidth || document.body.clientWidth, winH = document.documentElement.clientHeight || document.body.clientHeight;
        var markW = mark.offsetWidth, markH = mark.offsetHeight;
        on(mark, "mousedown", dragDown);
    
        function dragDown(e) {
            this["strX"] = e.clientX;//this["strX"]存的自定义属性
            this["strY"] = e.clientY;
            this["strL"] = this.offsetLeft;
            this["strT"] = this.offsetTop;
            if (this.setCapture) {//->IE和火狐
                this.setCapture();
                zhufengEvent.on(this, "mousemove", dragMove);
                zhufengEvent.on(this, "mouseup", dragUp);
            } else {
                var _this = this;
                this.MOVE = function (e) {
                    dragMove.call(_this, e);
                };
                this.UP = function (e) {
                    dragUp.call(_this, e);
                };
                on(document, "mousemove", this.MOVE);
                on(document, "mouseup", this.UP);
    
                //->清除正在运行的动画
                window.clearInterval(this.flyTimer);
                window.clearInterval(this.dropTimer);
            }
        }
        function dragMove(e) {
            var curL = e.clientX - this["strX"] + this["strL"];
            var curT = e.clientY - this["strY"] + this["strT"];
            var minL = 0, minT = 0, maxL = winW - markW, maxT = winH - markH;
            curL = curL <= minL ? minL : (curL >= maxL ? maxL : curL);
            curT = curT <= minT ? minT : (curT >= maxT ? maxT : curT);
            mark.style.left = curL + "px";
            mark.style.top = curT + "px";
    
            //->动画
            //浏览器中每一个事件行为都有一个最短的反应时间minTime,在minTime以内,不会重复触发这个行为,只有超过了这个最短时间才会触发下一次的行为
            //我们水平方向运动的速度取决于拖拽结束的那一瞬间,鼠标移动的距离;
            //console.log("ok");
            if (!this["flyPre"]) {
                this["flyPre"] = this.offsetLeft;
            } else {
                this["flySpeed"] = this.offsetLeft - this["flyPre"];
                this["flyPre"] = this.offsetLeft;
            }
    
        }
        function dragUp(e) {
            if (this.releaseCapture) {
                this.releaseCapture();
                off(this, "mousemove", dragMove);
                off(this, "mouseup", dragUp);
            } else {
                off(document, "mousemove", this.MOVE);
                off(document, "mouseup", this.UP);
            }
            //->拖拽结束执行动画
            fly.call(this);//让this变为当前元素
            drop.call(this);
        }
    
        //->水平方向的动画
        function fly() {
            //->this->mark
            var _this = this, speed = this["flySpeed"];
            _this.flyTimer = window.setInterval(function () {
                //->由于我们的offsetLeft每一次获取的值都会出现四舍五入,这样如果本次增加一个小于0.5的速度值的话,下一次获取的值还是上次的值,加的速度起不到作用,我们结束动画即可
                if (Math.abs(speed) < 0.5) {//可能是负值
                    window.clearInterval(_this.flyTimer);
                    return;
                }
                //console.log("ok");//动画结束了,定时器还没有结束
                speed *= 0.98;//每一次都让速度乘以一个小于1的值,这样我们的速度就在衰减
                var curL = _this.offsetLeft + speed;// _this.offsetLeft获取的是整数(四舍五入了)??????
                var minL = 0, minT = 0, maxL = winW - markW, maxT = winH - markH;
                if (curL >= maxL) {//到达右边界
                    curL = maxL;
                    speed *= -1;
                } else if (curL <= minL) {//到达左边界
                    curL = minL;
                    speed *= -1;
                }
                //console.log(curL);
                _this.style.left = curL + "px";
            }, 10);
        }
    
        //->垂直方向
        function drop() {
            var _this = this, speed = 9.8;
            _this["dropFlag"] = 0;
            _this.dropTimer = window.setInterval(function () {
                if (_this["dropFlag"] > 1) {
                    window.clearInterval(_this.dropTimer);
                    return;
                }
                speed += 10;
                speed *= 0.98;
                var curT = _this.offsetTop + speed;
                if (curT >= winH - markH) {//到底了
                    curT = winH - markH;
                    //return;
                    speed *= -1;
                    _this["dropFlag"]++;
                } else {//不在底
                    _this["dropFlag"] = 0;
                }
                _this.style.top = curT + "px";
    
            }, 10);
        }
    </script>
    </body>
    </html>

    以上代码是页面HTML和实现动画的JS,下面是里面引用的jss里面的event.js文件:

    //->基于内置类的原型扩展一个等价于bind的方法,预先把某一个函数中的this进行处理,把一些参数值预先传递进来(事件对象也可以获取到)
    Function.prototype.myBind = function myBind(context) {
        //this->我要操作的那个函数
        var _this = this;
        var outerArg = Array.prototype.slice.call(arguments, 1);
        return function () {
            var innerArg = Array.prototype.slice.call(arguments, 0);
            _this.apply(context, outerArg.concat(innerArg));
        }
    };
        //->清除正在运行的动画
        function bind(curEle, type, fn) {
            if (curEle.addEventListener) {
                curEle.addEventListener(type, fn, false);
                return;
            }
            var tempFn = fn.myBind(curEle);
            tempFn.photo = fn;
    
            !curEle["myBind" + type] ? curEle["myBind" + type] = [] : null;
            var ary = curEle["myBind" + type];
            for (var i = 0; i < ary.length; i++) {
                if (ary[i].photo === fn) {
                    return;
                }
            }
            ary.push(tempFn);
            //curEle["myBind" + type].push(tempFn);
            curEle.attachEvent("on" + type, tempFn);
            //curEle.attachEvent("on"+type,fn.myBind(curEle));
        }
    
    
        function unbind(curEle, type, fn) {
            if (curEle.removeEventListener) {
                curEle.removeEventListener(type, fn, false);
                return;
            }
            var ary = curEle["myBind" + type];
            if (ary) {
                for (var i = 0; i < ary.length; i++) {
                    var tempFn = ary[i];
                    if (tempFn.photo === fn) {
                        curEle.detachEvent("on" + type, tempFn);
                        ary.splice(i, 1);
                        break;
                        //curEle.detachEvent("on" + type, fn.myBind(curEle));
                    }
                }
            }
        }
    
    
    
    
    
    //->自己模拟内置的事件池创建一个临时的容器,把所有需要绑定的方法先放在自己的容器中,然后值给元素的某个行为绑定一个方法run,(把这个方法需要增加到内置的事件池中)当行为触发的时候执行run方法,在run执行的过程中,我们在把通过on绑定的方法依次的按顺序执行即可;
    function on(curEle, type, fn) {
        !curEle["myEvent" + type] ? curEle["myEvent" + type] = [] : null;
        var ary = curEle["myEvent" + type];
        for (var i = 0; i < ary.length; i++) {
            if (ary[i] === fn) {
                return;//重复了就不追加了,直接return
            }
        }
        ary.push(fn);
        bind(curEle, type, run);
    }
    
    function off(curEle, type, fn) {
        var ary = curEle["myEvent" + type];
        if (ary) {
            for (var i = 0; i < ary.length; i++) {
                var curFn = ary[i];
                if (curFn === fn) {
                    ary[i] = null;
                    break;
                }
            }
        }
    }
    
    function run(e) {
        if (window.event) {
            e.target = e.srcElement;
            e.pageX = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
            e.pageY = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
            e.preventDefault = function () {
                e.returnValue = false;
            };
            e.stopPropagation = function () {
                e.cancelBubble = true;
            };
        }
        var ary = this["myEvent" + e.type];
        if (ary) {
            for (var i = 0; i < ary.length; i++) {
                var curFn = ary[i];
                if (typeof curFn === "function") {
                    curFn.call(this, e);
                    continue;
                }
                ary.splice(i, 1);
                i--;
            }
        }
    }

    通过以上的详细代码,就实现了我们的弹性势能动画

  • 相关阅读:
    Redis源代码分析(十三)--- redis-benchmark性能測试
    kvm中运行kvm
    umount.nfs device busy day virsh extend diskSpace, attachDisk
    ultravnc
    openNebula dubug
    maintenance ShellScripts
    virsh VMI deploy data serial xml
    cloud computing platform,virtual authentication encryption
    基于C 的libvirt 接口调用
    storage theory
  • 原文地址:https://www.cnblogs.com/kpengfang/p/5446547.html
Copyright © 2011-2022 走看看