JavaScript实现的抛物线运动效果

原文:http://www.css88.com/archives/5355

作者的主要实现代码:

;
(function () {
    var _$ = function (_this) {
        return _this.constructor == jQuery ? _this : $(_this);
    };
// 获取当前时间
    function now() {
        return +new Date();
    }
 
// 转化为整数
    function toInteger(text) {
        text = parseInt(text);
        return isFinite(text) ? text : 0;
    }
 
    var Parabola = function (options) {
        this.initialize(options);
    };
    Parabola.prototype = {
        constructor: Parabola,
        /**
         * 初始化
         * @classDescription 初始化
         * @param {Object} options 插件配置 .
         */
        initialize: function (options) {
            this.options = this.options || this.getOptions(options);
            var ops = this.options;
            if (!this.options.el) {
                return;
            }
            this.$el = _$(ops.el);
            this.timerId = null;
            this.elOriginalLeft = toInteger(this.$el.css("left"));
            this.elOriginalTop = toInteger(this.$el.css("top"));
            // this.driftX X轴的偏移总量
            //this.driftY Y轴的偏移总量
            if (ops.targetEl) {
                this.driftX = toInteger(_$(ops.targetEl).css("left")) - this.elOriginalLeft;
                this.driftY = toInteger(_$(ops.targetEl).css("top")) - this.elOriginalTop;
            } else {
                this.driftX = ops.offset[0];
                this.driftY = ops.offset[1];
            }
            this.duration = ops.duration;
            // 处理公式常量
            this.curvature = ops.curvature;
            // 根据两点坐标以及曲率确定运动曲线函数(也就是确定a, b的值)
            //a=this.curvature
            /* 公式: y = a*x*x + b*x + c;
             */
            /*
             * 因为经过(0, 0), 因此c = 0
             * 于是:
             * y = a * x*x + b*x;
             * y1 = a * x1*x1 + b*x1;
             * y2 = a * x2*x2 + b*x2;
             * 利用第二个坐标:
             * b = (y2+ a*x2*x2) / x2
             */
            // 于是
            this.b = ( this.driftY - this.curvature * this.driftX * this.driftX ) / this.driftX;
 
            //自动开始
            if (ops.autostart) {
                this.start();
            }
        },
        /**
         * 初始化 配置参数 返回参数MAP
         * @param {Object} options 插件配置 .
         * @return {Object} 配置参数
         */
        getOptions: function (options) {
            if (typeof options !== "object") {
                options = {};
            }
            options = $.extend({}, defaultSetting, _$(options.el).data(), (this.options || {}), options);
 
            return options;
        },
        /**
         * 定位
         * @param {Number} x x坐标 .
         * @param {Object} y y坐标 .
         * @return {Object} this
         */
        domove: function (x, y) {
 
            this.$el.css({
                position: "absolute",
                left: this.elOriginalLeft + x,
                top: this.elOriginalTop + y
            });
 
            return this;
        },
        /**
         * 每一步执行
         * @param {Data} now 当前时间 .
         * @return {Object} this
         */
        step: function (now) {
            var ops = this.options;
            var x, y;
            if (now > this.end) {
                // 运行结束
                x = this.driftX;
                y = this.driftY;
                this.domove(x, y);
                this.stop();
                if (typeof ops.callback === 'function') {
                    ops.callback.call(this);
                }
            } else {
                //x 每一步的X轴的位置
                x = this.driftX * ((now - this.begin) / this.duration);
                //每一步的Y轴的位置y = a*x*x + b*x + c;   c==0;
                y = this.curvature * x * x + this.b * x;
 
                this.domove(x, y);
                if (typeof ops.stepCallback === 'function') {
                    ops.stepCallback.call(this);
                }
            }
            return this;
        },
        /**
         * 设置options
         *  @param {Object} options 当前时间 .
         */
        setOptions: function (options) {
            this.reset();
            if (typeof options !== "object") {
                options = {};
            }
            this.options = this.getOptions(options);
            this.initialize('parabola', this.options);
            return this;
        },
        /**
         * 开始
         */
        start: function () {
            var self = this;
            // 设置起止时间
            this.begin = now();
            this.end = this.begin + this.duration;
            if (this.driftX === 0 && this.driftY === 0) {
                // 原地踏步就别浪费性能了
                return;
            }
            /*timers.push(this);
             Timer.start();*/
            if (!!this.timerId) {
                clearInterval(this.timerId);
                this.stop();
            }
            this.timerId = setInterval(function () {
                var t = now();
                self.step(t);
 
            }, 13);
            return this;
        },
        /**
         * 重置
         */
        reset: function (x, y) {
            this.stop();
            x = x ? x : 0;
            y = y ? y : 0;
            this.domove(x, y);
            return this;
        },
        /**
         * 停止
         */
        stop: function () {
            if (!!this.timerId) {
                clearInterval(this.timerId);
 
            }
            return this;
        }
    };
    var defaultSetting = {
        el: null,
        //偏移位置
        offset: [0, 0],
        //终点元素,这时就会自动获取该元素的left、top,设置了这个参数,offset将失效
        targetEl: null,
        //运动的时间,默认500毫秒
        duration: 500,
        //抛物线曲率,就是弯曲的程度,越接近于0越像直线,默认0.001
        curvature: 0.001,
        //运动后执行的回调函数
        callback: null,
        // 是否自动开始,默认为false
        autostart: false,
        //运动过程中执行的回调函数
        stepCallback: null
    };
    window.Parabola = Parabola;
})();
使用:

var bool = new Parabola({
        el: "#boll",
        offset: [500, 100],
        curvature: 0.005,
        duration: 3000,
        callback: function () {
            alert("完成后回调")
        },
        stepCallback: function (x, y) {
            console.log(x, y);
            $("<div>").appendTo("body").css({
                "position": "absolute",
                "top": this.elOriginalTop + y,
                "left": this.elOriginalLeft + x,
                "background-color": "#CDCDCD",
                "width": "5px",
                "height": "5px",
                "border-radius": "5px"
            });
        }
    });
demo地址: http://www.css88.com/demo/parabola/index.html
demo内容:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>抛物线运动效果</title>
    <style type="text/css">
        .boll {
            width: 50px;
            height: 50px;
            background-color: #ff3333;
            position: absolute;
            top: 380px;
            left: 100px;
            -moz-border-radius: 50px;
            -webkit-border-radius: 50px;
            border-radius: 50px;
        }

        .target {
            width: 50px;
            height: 50px;
            background-color: #CDCDCD;
            position: absolute;
            top: 180px;
            left: 600px;
            -moz-border-radius: 50px;
            -webkit-border-radius: 50px;
            border-radius: 50px;
        }
    </style>
    <script type="text/javascript" src="http://www.css88.com/jqapi-1.9/js/jquery.min.js"></script>
    <script type="text/javascript" src="js/parabola.js"></script>
</head>

<body>
<div class="btns" style="margin-top:20px">
    <a href="http://www.css88.com/archives/5355" target="_blank">回到JavaScript实现的抛物线运动效果</a>
</div>
    <div class="btns" style="margin-top:20px">
    <a href="#" class="btnA btn-danger" id="reset" rel="popover" title="A Title" style="">reset</a>
    <a href="#" class="btnA btn-danger" id="run" rel="popover" title="A Title" style="">run</a>
    <a href="#" class="btnA btn-danger" id="stop" rel="popover" title="A Title" style="">stop</a>
    <a href="#" class="btnA btn-danger" id="setOptions" rel="popover" title="A Title" style="">setOptions</a>
</div>
<div id="boll" class="boll"></div>
<div id="target" class="target"></div>
<script type="text/javascript">
    var bool = new Parabola({
        el: "#boll",
        offset: [500, 100],
        curvature: 0.005,
        duration: 3000,
        callback:function(){
            alert("完成后回调")
        },
        stepCallback:function(x,y){
            console.log(x,y);
            $("<div>").appendTo("body").css({
                "position": "absolute",
                "top": this.elOriginalTop + y,
                "left":this.elOriginalLeft + x,
                "background-color":"#CDCDCD",
                "width":"5px",
                "height":"5px",
                "border-radius": "5px"
            });
        }
    });
    $("#reset").click(function (event) {
        event.preventDefault();
        bool.reset()
    });
    $("#run").click(function (event) {
        event.preventDefault();
        bool.start();
    });
    $("#stop").click(function (event) {
        event.preventDefault();
        bool.stop();
    });
    $("#setOptions").click(function (event) {
        event.preventDefault();
        bool.setOptions({
            targetEl: $("#target"),
            curvature: 0.001,
            duration: 1000
        });
    });
</script>
</body>
</html>

另外一个仿天猫的抛物线效果,原作者地址: https://github.com/amibug/fly
demo:  http://codepen.io/hzxs1990225/full/ogLaVp

<script src="jquery.js"></script>
<script src="dist/jquery.fly.min.js"></script>
<script>
jQuery(function($) {
  $('#fly').fly({
    start:{
      left: 11,  //开始位置(必填)#fly元素会被设置成position: fixed
      top: 600,  //开始位置(必填)
    },
    end:{
      left: 500, //结束位置(必填)
      top: 130,  //结束位置(必填)
      width: 100, //结束时高度
      height: 100, //结束时高度
    },
    autoPlay: false, //是否直接运动,默认true
    speed: 1.1, //越大越快,默认1.2
    vertex_Rtop:100, //运动轨迹最高点top值,默认20
    onEnd: function(){} //结束回调
  });
  $('#fly').play(); //autoPlay: false后,手动调用运动
  $('#fly').destory(); //移除dom
});
</script>
IE10以下,引入src/requestAnimationFrame.js
(function () {
  var lastTime = 0;
  var vendors = ['webkit', 'moz'];
  for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
    window.cancelAnimationFrame =
      window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
  }

  if (!window.requestAnimationFrame){
    window.requestAnimationFrame = function (callback, element) {
      var currTime = new Date().getTime();
      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
      var id = window.setTimeout(function () {
          callback(currTime + timeToCall);
        },
        timeToCall);
      lastTime = currTime + timeToCall;
      return id;
    };
  }
  if (!window.cancelAnimationFrame){
    window.cancelAnimationFrame = function (id) {
      clearTimeout(id);
    };
  }
}());



你可能感兴趣的:(js抛物线)