美文网首页web 前端
购物车飞入动画

购物车飞入动画

作者: 飞球大的波波 | 来源:发表于2017-05-05 16:23 被阅读1068次

    动画原理

    这里是利用物体在水平方向减速运动的同时也在垂直方向加速运动就可以实现抛物线运动轨迹,所以我们可以利用Animation+Transform实现抛物线动画,当然你也可以使用Transition+Transform,为什么不推荐position的left和top,我也希望大家知道为什么

    效果图

    效果图展示

    开始之前

    在开始之前我们需要梳理下思路:

    1、首先我们需要一个div把整个结构给包起来;
    2、一个垂直方向加速运动的Div;
    3、一个水平方向减速运动的Div;
    4、可不可以放个图片什么的;
    5、函数控制Div运动的初始位置和结束位置;
    6、运动模式控制;
    7、完成;

    第一步>让静态的动画骚起来:

    HTML结构:

    <div class="parabola-animation">
            <div class="parabola-box-hor">
                <div class="parabola-box-ver">
                    ![](/static/img/good_1.png)
                </div>
            </div>
        </div>
    

    CSS部分:

    • 首先我们定义一个div把他们包起来:
    .parabola-animation{
        width: 100%;
    }
    
    • 嗯,还需要一个水平方向减速运动的Div:
    .parabola-box-hor{
        position: fixed;
        top: 0;
        left: 0;
        z-index: 99;
        -webkit-animation: parabola-hor-animation 1s ease-out infinite;
        animation: parabola-hor-animation 1s ease-out infinite;
    }
    @keyframes parabola-hor-animation{
        0%{
            -webkit-transform: translate(0, 0);
                    transform: translate(0, 0);
        }
        100%{
            -webkit-transform: translate(200px, 0);
                    transform: translate(200px, 0);
        }
    }
    
    • 哦,那么垂直方向加速运动的Div也少不了的,顺带给图片设置样式:
    .parabola-box-ver{
        position: absolute;
        top: 50px;
        left: 20px;
        width: 35px;
        height: 35px;
        border-radius: 50%;
        overflow: hidden;
        -webkit-animation: parabola-ver-animation 1s ease-in infinite;
        animation: parabola-ver-animation 1s ease-in infinite;
    }
    .parabola-box-ver>img{
        width: 100%;
        height: 100%;
        vertical-align: middle;
    }
    @keyframes parabola-ver-animation{
        0%{
            -webkit-transform: translate(0, 0);
                    transform: translate(0, 0);
        }
        100%{
            -webkit-transform: translate(0, 200px);
                    transform: translate(0, 200px);
        }
    }
    

    第二步>JS封装?:

    为什么要这么做:**因为我们需要自定义动画的开始位置和结束位置,不然飞入,飞毛线啊!**
    那么既然如此,开始吧:(WTF、难道我们还没有开始过???)
    预期的结果是点击页面上某个地方,我们的动画从点击的地方飞到指定的位置;

    {
        begin: '',  //开始位置的jquery或者zepto对象$('.begin')
        end: '',     //结束位置的jquery或者zepto对象$('.end')
        img: '',    //动画上面的图片路径
        callback:function(){}    //回调函数
    }
    

    上面这些是封装需要的参数:

    创建动画规则@keyframes:
    函数名:creatRule

        var addCar = function(opt){
            return (function(){
                var parabola = function(opt){
                    this.init(opt);
                };
                parabola.prototype = {
                    init: function(){
                        console.log('您再等一等嘛,大爷');
                    },
                    creatRule:function(coord){
                        var cssAnimation = document.createElement('style');
                        cssAnimation.type="text/css";
                        var rules = "\
                                @-webkit-keyframes parabola-hor-animation{\
                                    0%{\
                                        -webkit-transform: translate(0px, 0px);\
                                                transform: translate(0px, 0px);\
                                    }\
                                    10%{\
                                        -webkit-transform: translate(0px, 0px);\
                                                transform: translate(0px, 0px);\
                                    }\
                                    100%{\
                                        -webkit-transform: translate("+coord.x+"px, 0px);\
                                                transform: translate("+coord.x+"px, 0px);\
                                    }\
                                }\
                                @keyframes parabola-hor-animation{\
                                    0%{\
                                        -webkit-transform: translate(0px, 0px);\
                                                transform: translate(0px, 0px);\
                                    }\
                                    10%{\
                                        -webkit-transform: translate(0px, 0px);\
                                                transform: translate(0px, 0px);\
                                    }\
                                    100%{\
                                        -webkit-transform: translate("+coord.x+"px, 0px);\
                                                transform: translate("+coord.x+"px, 0px);\
                                    }\
                                }\
                                @-webkit-keyframes parabola-ver-animation{\
                                    0%{\
                                        -webkit-transform: translate(0px, 0px);\
                                                transform: translate(0px, 0px);\
                                    }\
                                    10%{\
                                        -webkit-transform: translate(0px, "+coord.os+"px);\
                                                transform: translate(0px, "+coord.os+"px);\
                                    }\
                                    100%{\
                                        -webkit-transform: translate(0px,"+coord.y+"px);\
                                                transform: translate(0px,"+coord.y+"px);\
                                    }\
                                }\
                                @keyframes parabola-ver-animation{\
                                    0%{\
                                        -webkit-transform: translate(0px, 0px);\
                                                transform: translate(0px, 0px);\
                                    }\
                                    10%{\
                                        -webkit-transform: translate(0px, "+coord.os+"px);\
                                                transform: translate(0px, "+coord.os+"px);\
                                    }\
                                    100%{\
                                        -webkit-transform: translate(0px,"+coord.y+"px);\
                                                transform: translate(0px,"+coord.y+"px);\
                                    }\
                                }\
                            ";
                        cssAnimation.innerHTML = rules;
                        return cssAnimation;
                    }
                }
                return new parabola(opt);
            })();
        }
    

    这样我们就能控制动画的结束位置了,想想还有些刺激呢;
    里面的parabola-ver-animation动画我新增了一个10%节点是为了让我们点击开始元素的时候有一个向上弹跳一下的人性化操作,哎,我还是太好了;

    创建容器和构建HTMl代码:
    函数名:creatHtml

        var addCar = function(opt){
            return (function(){
                var parabola = function(opt){
                    this.init(opt);
                };
                parabola.prototype = {
                    init: ...,
                    creatRule:...,
                    creatHtml : function(site,img){
                        var imgHtml = img == '' ? '' : '![]('+img+')';
    
                        var html = '<div class="parabola-box-hor">\
                                        <div class="parabola-box-ver">\
                                            '+imgHtml+'\
                                        </div>\
                                    </div>';
    
                        var parentBox = document.createElement('div');
                        parentBox.innerHTML = html;
                        parentBox.setAttribute('class','parabola-animation');
    
                        var frag = document.createDocumentFragment();
                        frag.appendChild(parentBox);
    
                        var verBox = frag.querySelector('.parabola-box-ver'),
                            horBpx = frag.querySelector('.parabola-box-hor');
                        verBox.style.left = site.left + 'px';
                        verBox.style.top = site.top + 'px';
    
                        if(site.cubic) {
                            verBox.setAttribute("class",'parabola-box-ver top');
                            horBpx.setAttribute("class",'parabola-box-hor top');
                        }
                        return frag;
                    }
                }
                return new parabola(opt);
            })();
    

    计算动画的开始位置和结束位置的参数:
    函数名:calculatedValue

        var addCar = function(opt){
            return (function(){
                var parabola = function(opt){
                    this.init(opt);
                };
                parabola.prototype = {
                    init: ...,
                    creatRule:...,
                    creatHtml : ...,
                    calculatedValue:function(opt){
                        var fly = {
                            begin:'',
                            end: '',
                            img : '',
                            callback:function(){
                                console.log('动画完成');
                            }
                        },
                        vData = {
                            site:{
                                left: 0,
                                top: 0 ,
                                cubic: false
                            },
                            img: '',
                            coord:{
                                x: 0 ,
                                y: 0 ,
                                os: 0
                            },
                            callback: function(){}
                        },
                        _this = this ;
    
                        if( typeof opt == 'object'){
                            fly = $.extend(true, fly, opt);
                        }
    
                        //如果没有这两个元素中的其中一个则终止
                        if(!fly.begin.length || !fly.end.length) return vData;
                        /**
                         * beginCrood 获取开始元素的位置
                         * endCrood   获取结束元素的位置
                         */
                        var beginCrood = fly.begin[0].getBoundingClientRect(),
                            endCrood = fly.end[0].getBoundingClientRect();
    
                        /*!
                         *  购物车动画出现的位置
                         *  left: 开始元素的left+width/2
                         *  top: 开始元素的top
                         *  购物车动画结束的位置
                         *  x: 结束元素的left+width/2 再减去购物车动画出现的位置的left
                         *  y: 结束元素的top+height/2 再减去购物车动画出现的位置的top
                         */
                        /**
                         * 全部减去 18是因为购物车宽度和高度都是35px;一半难得算(-_-),就填18
                         */
                        vData.site.left = beginCrood.left + parseInt(beginCrood.width/2,10) -18;
                        vData.site.top = beginCrood.top -18;
                        vData.coord.x = endCrood.left + parseInt(endCrood.width/2,10) - vData.site.left -18;
                        vData.coord.y = endCrood.top + parseInt(endCrood.height/2,10) - vData.site.top -18;
                        vData.coord.os = -50;
                        vData.img = fly.img;
                        vData.callback = fly.callback;
                        if(beginCrood.top > endCrood.top) vData.site.cubic = true;
                        
                        return vData;
                    }
                }
                return new parabola(opt);
            })();
    

    初始化函数和方法:
    函数名:init

            var addCar = function(opt){
            return (function(){
                var parabola = function(opt){
                    this.init(opt);
                };
                parabola.prototype = {
                    init: function(opt){
                        var flyO = this.calculatedValue(opt),
                            flyDom = this.creatHtml(flyO.site,flyO.img),
                            flyRule = this.creatRule(flyO.coord);
    
                        document.getElementsByTagName('head')[0].appendChild(flyRule);
                        document.body.appendChild(flyDom);
                        $('.parabola-animation').on('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend','.parabola-box-ver',function(){
                            var _pfly = $('.parabola-animation');
                            if(_pfly.length) _pfly.remove();
                            flyO.callback();
                        });
                    },
                    creatRule:...,
                    creatHtml : ...,
                    calculatedValue:...
                }
                return new parabola(opt);
            })();
    

    第三步>样式调整(这个步骤是必须的哈):

    经过上面的设置基本上已经完成了购物车的加入动画了,现在我们把样式调整下就是最后的版本了;

    不说了直接粘代码:

    .parabola-animation{
        width: 100%;
    }
    .parabola-box-hor{
        position: fixed;
        top: 0;
        left: 0;
        z-index: 99;
        -webkit-animation: parabola-hor-animation 1s ease-out 1;
        animation: parabola-hor-animation 1s ease-out 1;
    }
    .parabola-box-hor.top{
        -webkit-animation-timing-function: ease-in;
                animation-timing-function: ease-in;
    }
    .parabola-box-ver{
        position: fixed;
        top: 50px;
        left: 20px;
        width: 35px;
        height: 35px;
        border-radius: 50%;
        overflow: hidden;
        -webkit-animation: parabola-ver-animation 1s ease-in 1;
        animation: parabola-ver-animation 1s ease-in 1;
    }
    .parabola-box-ver.top{
        -webkit-animation-timing-function: ease-out;
                animation-timing-function: ease-out;
    }
    .parabola-box-ver>img{
        width: 100%;
        height: 100%;
        vertical-align: middle;
    }
    

    End

    感谢大家的阅读,希望对你有所启发,这里是GIT链接,在Git项目里面的核心文件是addCar.js、至于index.js只是页面上的一些效果,出丑出丑了,也希望能给个star,真诚从来不是假意。

    相关文章

      网友评论

        本文标题:购物车飞入动画

        本文链接:https://www.haomeiwen.com/subject/eovjtxtx.html