zoukankan      html  css  js  c++  java
  • javascript仿天猫加入购物车动画效果

    javascript仿天猫加入购物车动画效果

      注意:首先需要声明的是:代码原思路不是我写的,是在网上找的这种效果,自己使用代码封装了下而已;代码中都有注释,我们最主要的是理解抛物线的思路及在工作中完成这样的任务,最近需要做类似于天猫加入购物车动画效果,所以就在网上搜索了下,就看到类似的效果,就把代码截下来自己封装了下~~

      如果想要了解抛物线的细节,我建议大家先 看下 张鑫旭 讲解的抛物线的文章,再来看如下JS代码,可能理解更深点~~

    http://www.zhangxinxu.com/wordpress/2013/12/javascript-js-%E5%85%83%E7%B4%A0-%E6%8A%9B%E7%89%A9%E7%BA%BF-%E8%BF%90%E5%8A%A8-%E5%8A%A8%E7%94%BB/

    首先我们来理解的是: 既然是抛物运动,那么 运动的元素肯定需要 "绝对定位";配置的参数有如下:(依赖于Jquery或者zepto.js

     配置项  含义
     el  需要运动的元素 {object | string}  默认为null 
     offset  运动的元素在 X轴,Y轴的偏移位置
     targetEl  终点目标元素 这时就会自动获取该元素的left、top值,来表示移动元素在X,Y轴的偏移位置;设置了这个参数,offset将失效
     duration  运动时间,默认为500毫秒
     curvature  抛物线曲率,就是弯曲的程度,越接近于0越像直线,默认0.001
     callback  运动完成后执行的回调函数
     autostart  是否自动开始运动,默认为false
     stepCallback  运动过程中执行的回调函数,this指向该对象,接受x,y参数,分别表示X,Y轴的偏移位置。

     JSFiddler效果如下:

    JS抛物线运动效果

    下面是所有的JS代码:

    /*
     * 实现抛物线函数 Parabola
     * 切记既然是抛物线运动,那么运动的元素需要绝对定位
     * 具体了解抛物线 可以看张鑫旭的文章 
     * http://www.zhangxinxu.com/wordpress/2013/12/javascript-js-%E5%85%83%E7%B4%A0-%E6%8A%9B%E7%89%A9%E7%BA%BF-%E8%BF%90%E5%8A%A8-%E5%8A%A8%E7%94%BB/
     */
    var Parabola = function(opts){
        this.init(opts);
    };
    Parabola.prototype = {
        constructor: Parabola,
        /*
         * @fileoverview 页面初始化
         * @param opts {Object} 配置参数
         */
        init: function(opts){
            this.opts =  $.extend(defaultConfig, opts || {});
            // 如果没有运动的元素 直接return
            if(!this.opts.el) {
                return;
            }
            // 取元素 及 left top
            this.$el = $(this.opts.el);
            this.$elLeft = this._toInteger(this.$el.css("left"));
            this.$elTop = this._toInteger(this.$el.css("top"));
            // 计算x轴,y轴的偏移量
            if(this.opts.targetEl) {
                this.diffX = this._toInteger($(this.opts.targetEl).css("left")) - this.$elLeft;
                this.diffY = this._toInteger($(this.opts.targetEl).css("top")) - this.$elTop;
            }else {
                this.diffX = this.opts.offset[0];
                this.diffY = this.opts.offset[1];
            }
            // 运动时间
            this.duration = this.opts.duration;
            // 抛物线曲率
            this.curvature = this.opts.curvature;
            
            // 计时器
            this.timerId = null;
            /*
             * 根据两点坐标以及曲率确定运动曲线函数(也就是确定a, b的值)
             * 公式: 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.diffY - this.curvature * this.diffX * this.diffX) / this.diffX;
    
             // 是否自动运动
             if(this.opts.autostart) {
                 this.start();
             }
        },
        /*
         * @fileoverview 开始
         */
        start: function(){
            // 开始运动
            var self = this;
            // 设置起始时间 和 结束时间
            this.begin = (new Date()).getTime();
            this.end = this.begin + this.duration;
            
            // 如果目标的距离为0的话 就什么不做
            if(this.diffX === 0 && this.diffY === 0) {
                return;
            }
            if(!!this.timerId) {
                clearInterval(this.timerId);
                this.stop();
            }
            // 每帧(对于大部分显示屏)大约16~17毫秒。默认大小是166.67。也就是默认10px/ms
            this.timerId = setInterval(function(){
                var t = (new Date()).getTime();
                self.step(t);
            },16);
            return this;
        },
        /*
         * @fileoverview 执行每一步
         * @param {string} t 时间
         */
        step: function(t){
            var opts = this.opts;
            var x,
                y;
            // 如果当前运行的时间大于结束的时间
            if(t > this.end) {
                // 运行结束
                x = this.diffX;
                y = this.diffY;
                this.move(x,y);
                this.stop();
                // 结束后 回调
                if(typeof opts.callback === 'function') {
                    opts.callback.call(this);
                }
            }else {
                // 每一步x轴的位置
                x = this.diffX * ((t - this.begin) / this.duration);
                // 每一步y轴的位置 y = a * x *x + b*x + c; c = 0
                y = this.curvature * x * x + this.b * x;
                // 移动
                this.move(x,y);
                if(typeof opts.stepCallback === 'function') {
                    opts.stepCallback.call(this,x,y);
                }
            }
            return this;
        },
        /*
         * @fileoverview 给元素定位
         * @param {x,y} x,y坐标
         * @return this
         */
        move: function(x,y) {
            this.$el.css({
                "position":'absolute',
                "left": this.$elLeft + x + 'px',
                "top": this.$elTop + y + 'px'
            });
            return this;
        },
        /*
         * 获取配置项
         * @param {object} options配置参数
         * @return {object} 返回配置参数项
         */
        getOptions: function(options){
            if(typeof options !== "object") {
                options = {};
            }
            options = $.extend(defaultConfig, options || {});
            return options;
        },
        /*
         * 设置options
         * @param options
         */
        setOptions: function(options) {
            this.reset();
            if(typeof options !== 'object') {
                options = {};
            }
            options = $.extend(this.opts,options);
            this.init(options);
            return this;
        },
        /*
         * 重置
         */
        reset: function(x,y) {
            this.stop();
            x = x ? x : 0;
            y = y ? y : 0;
            this.move(x,y);
            return this;
        },
        /*
         * 停止
         */
        stop: function(){
            if(!!this.timerId){
                clearInterval(this.timerId);
            }
            return this;
        },
        /*
         * 变成整数
         * isFinite() 函数用于检查其参数是否是无穷大。
         */
        _toInteger: function(text){
            text = parseInt(text);
            return isFinite(text) ? text : 0;
        }
    };
    var defaultConfig = {
        //需要运动的元素 {object | string}
        el: null,
    
        // 运动的元素在 X轴,Y轴的偏移位置
        offset: [0,0],
    
        // 终点元素 
        targetEl: null,
    
        // 运动时间,默认为500毫秒
        duration: 500,
    
        // 抛物线曲率,就是弯曲的程度,越接近于0越像直线,默认0.001
        curvature: 0.01,
        
        // 运动后执行的回调函数
        callback: null,
    
        // 是否自动开始运动,默认为false
        autostart: false,
        
        // 运动过程中执行的回调函数,this指向该对象,接受x,y参数,分别表示X,Y轴的偏移位置。
        stepCallback: null
    };

    HTML代码如下:

    <div class="btns" style="margin-top:20px">
        <a href="#" id="reset">重置</a>
        <a href="#" id="run">开始运动</a>
        <a href="#" id="stop">停止运动</a>
        <a href="#" id="setOptions">设置配置参数</a>
    </div>
    <div id="boll" class="boll"></div>
    <div id="target" class="target"></div>

    JS初始化如下方式:

    var bool = new Parabola({
        el: "#boll",
        offset: [500, 100],
        duration: 500,
        curvature: 0.005,
        callback:function(){
            alert("完成后回调")
        },
        stepCallback:function(x,y){
                    
            $("<div>").appendTo("body").css({
                "position": "absolute",
                "top": this.$elTop + y + 'px',
                "left":this.$elLeft + x + 'px',
                "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
        });
    });

    JS源码下载

  • 相关阅读:
    Activity的singleTask启动模式
    蓝图Tips
    UE4 C++ Tips
    UE4的抛物线
    透明材质
    在UE4 C++构造函数里的常规操作
    UE4的反射关键词
    UE4字符串的各种转换
    UE4Launch遇到的问题
    在UE4C++中的宏
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/4802738.html
Copyright © 2011-2022 走看看