購物車飛入動畫

動畫原理

這里是利用物體在水平方向減速運(yùn)動的同時(shí)也在垂直方向加速運(yùn)動就可以實(shí)現(xiàn)拋物線運(yùn)動軌跡,所以我們可以利用Animation+Transform實(shí)現(xiàn)拋物線動畫,當(dāng)然你也可以使用Transition+Transform,為什么不推薦position的left和top,我也希望大家知道為什么

效果圖

效果圖展示

開始之前

在開始之前我們需要梳理下思路:

1、首先我們需要一個(gè)div把整個(gè)結(jié)構(gòu)給包起來;
2、一個(gè)垂直方向加速運(yùn)動的Div;
3、一個(gè)水平方向減速運(yùn)動的Div;
4、可不可以放個(gè)圖片什么的;
5、函數(shù)控制Div運(yùn)動的初始位置和結(jié)束位置;
6、運(yùn)動模式控制;
7、完成;

第一步>讓靜態(tài)的動畫騷起來:

HTML結(jié)構(gòu):

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

CSS部分:

  • 首先我們定義一個(gè)div把他們包起來:
.parabola-animation{
    width: 100%;
}
  • 嗯,還需要一個(gè)水平方向減速運(yùn)動的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);
    }
}
  • 哦,那么垂直方向加速運(yùn)動的Div也少不了的,順帶給圖片設(shè)置樣式:
.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封裝?:

為什么要這么做:**因?yàn)槲覀冃枰远x動畫的開始位置和結(jié)束位置,不然飛入,飛毛線啊!**
那么既然如此,開始吧:(WTF、難道我們還沒有開始過???)
預(yù)期的結(jié)果是點(diǎn)擊頁面上某個(gè)地方,我們的動畫從點(diǎn)擊的地方飛到指定的位置;

{
    begin: '',  //開始位置的jquery或者zepto對象$('.begin')
    end: '',     //結(jié)束位置的jquery或者zepto對象$('.end')
    img: '',    //動畫上面的圖片路徑
    callback:function(){}    //回調(diào)函數(shù)
}

上面這些是封裝需要的參數(shù):

創(chuàng)建動畫規(guī)則@keyframes:
函數(shù)名: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);
        })();
    }

這樣我們就能控制動畫的結(jié)束位置了,想想還有些刺激呢;
里面的parabola-ver-animation動畫我新增了一個(gè)10%節(jié)點(diǎn)是為了讓我們點(diǎn)擊開始元素的時(shí)候有一個(gè)向上彈跳一下的人性化操作,哎,我還是太好了;

創(chuàng)建容器和構(gòu)建HTMl代碼:
函數(shù)名: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);
        })();

計(jì)算動畫的開始位置和結(jié)束位置的參數(shù):
函數(shù)名: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);
                    }

                    //如果沒有這兩個(gè)元素中的其中一個(gè)則終止
                    if(!fly.begin.length || !fly.end.length) return vData;
                    /**
                     * beginCrood 獲取開始元素的位置
                     * endCrood   獲取結(jié)束元素的位置
                     */
                    var beginCrood = fly.begin[0].getBoundingClientRect(),
                        endCrood = fly.end[0].getBoundingClientRect();

                    /*!
                     *  購物車動畫出現(xiàn)的位置
                     *  left: 開始元素的left+width/2
                     *  top: 開始元素的top
                     *  購物車動畫結(jié)束的位置
                     *  x: 結(jié)束元素的left+width/2 再減去購物車動畫出現(xiàn)的位置的left
                     *  y: 結(jié)束元素的top+height/2 再減去購物車動畫出現(xiàn)的位置的top
                     */
                    /**
                     * 全部減去 18是因?yàn)橘徫镘噷挾群透叨榷际?5px;一半難得算(-_-),就填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);
        })();

初始化函數(shù)和方法:
函數(shù)名: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);
        })();

第三步>樣式調(diào)整(這個(gè)步驟是必須的哈):

經(jīng)過上面的設(shè)置基本上已經(jīng)完成了購物車的加入動畫了,現(xiàn)在我們把樣式調(diào)整下就是最后的版本了;

不說了直接粘代碼:

.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

感謝大家的閱讀,希望對你有所啟發(fā),這里是GIT鏈接,在Git項(xiàng)目里面的核心文件是addCar.js、至于index.js只是頁面上的一些效果,出丑出丑了,也希望能給個(gè)star,真誠從來不是假意。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 選擇qi:是表達(dá)式 標(biāo)簽選擇器 類選擇器 屬性選擇器 繼承屬性: color,font,text-align,li...
    love2013閱讀 2,422評論 0 11
  • 陽春三月,人好,物好,心情好. 差不多也是get新技能的時(shí)期. 作為一名能力者,我們將目標(biāo)鎖定到了css3 an...
    sherlock221b閱讀 2,565評論 0 10
  • 選擇qi:是表達(dá)式 標(biāo)簽選擇器 類選擇器 屬性選擇器 繼承屬性: color,font,text-align,li...
    wzhiq896閱讀 2,102評論 0 2
  • 看了很多視頻、文章,最后卻通通忘記了,別人的知識依舊是別人的,自己卻什么都沒獲得。此系列文章旨在加深自己的印象,因...
    DCbryant閱讀 1,963評論 0 4
  • 八 森林中各種元素的力量漫天飛出,一道快如閃電般的身影在林中游走。仔細(xì)看去是一個(gè)少年不過從他的眼神中看到了一種不屬...
    藍(lán)瀾閱讀 221評論 0 0

友情鏈接更多精彩內(nèi)容