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源码下载

  • 相关阅读:
    Scrapy 概览笔记
    Python 依赖版本控制 (requirements.txt 文件生成和使用)
    Python 虚拟空间的使用
    macOS 所有版本 JDK 安装指南 (with Homebrew)
    鉴权那些事
    Java 位运算符和 int 类型的实现
    ASP.NET Core 入门教程 5、ASP.NET Core MVC 视图传值入门
    如何做好一次知识或技术分享
    ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门
    ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/4802738.html
Copyright © 2011-2022 走看看