购物车飞入动画

动画原理

这里是利用物体在水平方向减速运动的同时也在垂直方向加速运动就可以实现抛物线运动轨迹,所以我们可以利用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,真诚从来不是假意。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 2,306评论 0 11
  • 阳春三月,人好,物好,心情好. 差不多也是get新技能的时期. 作为一名能力者,我们将目标锁定到了css3 an...
    sherlock221b阅读 2,511评论 0 10
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    wzhiq896阅读 1,737评论 0 2
  • 看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印象,因...
    DCbryant阅读 1,857评论 0 4
  • 八 森林中各种元素的力量漫天飞出,一道快如闪电般的身影在林中游走。仔细看去是一个少年不过从他的眼神中看到了一种不属...
    蓝澜阅读 180评论 0 0