• 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--;
            }
        }
    }

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

  • 相关阅读:
    js返回上一页并刷新思路
    C#字符串拼接
    html2canvas截图问题,图片跨域导致截图空白
    VS2017未能添加对"System.Drawing.dll"的引用
    微信小程序云开发获取文件夹下所有文件
    js解析json报错Unexpected token i in JSON at position 1
    人工智能学习
    suricata的模块和插槽
    学习助手开发(二)——表单排序
    成功在Caterpillar代码中插入事件对象-20200917
  • 原文地址:https://www.cnblogs.com/kpengfang/p/5446547.html
Copyright © 2020-2023  润新知