動畫原理
這里是利用物體在水平方向減速運(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">

</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 == '' ? '' : '';
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,真誠從來不是假意。