動(dòng)畫
- 定義:運(yùn)動(dòng)的圖片(讓圖片或者圖畫動(dòng)起來(lái))华烟。
- 原理:未來(lái)位置等于當(dāng)前位置加上步長(zhǎng)(盒子的位置 = 盒子本身所在位置 + 步長(zhǎng))。
- 位置獲取和賦值方式:用
style.left賦值
,用offsetLeft獲取值
请毛;style.left獲取值不方便粘我,只能獲取行內(nèi)式,如果沒(méi)有就返回""坝橡,容易出現(xiàn)NaN泻帮,即使有值也是包含px的字符串;offsetLeft獲取值特別方便驳庭,而且獲取到的值是現(xiàn)成的number類型刑顺,方便計(jì)算,因?yàn)樗侵蛔x的不能賦值饲常,所以一般用style.left賦值蹲堂。
動(dòng)畫的種類
閃現(xiàn)(很少使用)
<body>
<button>閃動(dòng)</button>
<div></div>
<script src="../05-jQuery/jquery-1.11.1.js"></script>
<script type="text/javascript">
var btn = $("button");
var divs = $("div");
$(btn[0]).click(function () {
divs[0].style.left = "500px";
});
</script>
</body>
勻速(重點(diǎn)
)
<body>
<button>勻動(dòng)到200</button>
<button>勻動(dòng)到400</button>
<div></div>
<script>
var btn200 = document.getElementsByTagName("button")[0];
var btn400 = document.getElementsByTagName("button")[1];
var div = document.getElementsByTagName("div")[0];
var timer = null;
btn200.onclick = function () {
animation(200);
};
btn400.onclick = function () {
animation(400);
};
function animation(distance) {
timer = setInterval(function () {
div.style.left = div.offsetLeft + 10 + "px";
if (div.offsetLeftd == distance){
clearInterval(timer);
}
},30);
}
</script>
</body>
- 系列bug:
- 定時(shí)器:多次使用定時(shí)器之后,動(dòng)畫會(huì)越來(lái)越快:
- 解決方案:
在使用定時(shí)器之前贝淤,先清除定時(shí)器
柒竞。
- 解決方案:
- 不能返回:
- 解決方案:判斷目標(biāo)位置和當(dāng)前位置的大小,如果目標(biāo)位置大播聪,步進(jìn)就為正朽基,否則就為負(fù)布隔。
- 如果目標(biāo)位置和當(dāng)前位置的距離小于步進(jìn),就不再進(jìn)行運(yùn)動(dòng)稼虎,但是會(huì)出現(xiàn)抖動(dòng)現(xiàn)象:
- 解決方案:直接令當(dāng)前位置等于目標(biāo)位置衅檀。
- 一個(gè)盒子只能有一個(gè)定時(shí)器,這樣的話霎俩,不會(huì)出現(xiàn)定時(shí)器沖突哀军;
- 將定時(shí)器本身綁定成為盒子的一個(gè)屬性,不會(huì)和其它盒子定時(shí)器產(chǎn)生沖突
<head>
<meta charset="UTF-8">
<title>勻速運(yùn)動(dòng)</title>
<style type="text/css">
body{
margin:0;
padding:0;
}
.box1{
margin:0;
position: relative;
}
.box2{
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
}
.box3{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
margin-top: 130px;
}
</style>
</head>
<body>
<div class="box1">
<!--勻速運(yùn)動(dòng)-->
<button>勻動(dòng)到200</button>
<button style="left: 50px">勻動(dòng)到400</button>
<div class="box2"></div>
<div class="box3"></div>
</div>
<script>
var btn200 = document.getElementsByTagName("button")[0];
var btn400 = document.getElementsByTagName("button")[1];
var box2 = document.getElementsByTagName("div")[1];
var box3 = document.getElementsByClassName("box3")[0];
btn200.onclick = function () {
animation(box2,200);
};
btn400.onclick = function () {
animation(box3,400);
};
function animation(ele,distance) {
//1.使用定時(shí)器之前必須先清除打却,排除多次點(diǎn)擊越來(lái)越快的bug
clearInterval(ele.timer); //將定時(shí)器作為元素的屬性杉适,這樣一個(gè)盒子綁定一個(gè)自己的定時(shí)器,排除了其它盒子定時(shí)器的干擾
//2.為了能讓div可以從后往前走柳击,要先進(jìn)行判斷目標(biāo)位置和當(dāng)前位置的大小猿推,如果目標(biāo)位置大,步進(jìn)就正捌肴,否則就負(fù)
var speed = distance>box2.offsetLeft?10:(-10);
ele.timer = setInterval(function () {
var val = distance - ele.offsetLeft; //此句位置至關(guān)重要蹬叭,不能和下一句倒換位置,必須要先獲取目標(biāo)位置和當(dāng)前位置的距離
ele.style.left = ele.offsetLeft + speed + "px"; //此時(shí)盒子會(huì)進(jìn)行運(yùn)動(dòng)
//3.到達(dá)目標(biāo)位置后哭靖,再次點(diǎn)擊會(huì)出現(xiàn)抖動(dòng)現(xiàn)象具垫。解決方案,判斷目標(biāo)位置和當(dāng)前位置距離是否小于步進(jìn)试幽,如果小于就讓兩者相等筝蚕,并立刻清除定時(shí)器
if (Math.abs(val)<Math.abs(speed)){
ele.style.left = distance + "px";
clearInterval(ele.timer);
}
},30);
}
</script>
</body>
- 練習(xí):
- 滑動(dòng)輪播;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>練習(xí)</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.box{
border: 1px solid #999;
width: 490px;
height: 170px;
margin: 60px auto 0;
padding:5px;
}
.inner{
position: relative;
width: 490px;
height: 179px;
overflow: hidden;
}
ul{
width: 500%;
position: absolute;
}
li{
list-style: none;
float: left;
}
.square{
position: absolute;
right: 10px;
top: 140px;
}
.square span{
display: inline-block;
width: 18px;
height: 18px;
background-color: #aaa;
text-align: center;
line-height: 18px;
cursor: pointer;
}
.inner .current{
background-color: darkorange;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">
<ul>
<li>![](images/01.jpg)</li>
<li>![](images/02.jpg)</li>
<li>![](images/03.jpg)</li>
<li>![](images/04.jpg)</li>
<li>![](images/05.jpg)</li>
</ul>
<div class="square">
<span class="current">1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
</div>
</div>
</div>
<script>
window.onload = function () {
//獲取事件源和相關(guān)元素
var inner = document.getElementsByClassName("inner")[0];
var spans = inner.children[1].children;
var ul = inner.children[0];
//獲取窗口寬度
var scrollWidth = inner.offsetWidth;
for(var i=0; i<spans.length; i++){
spans[i].index = i;
spans[i].onmouseover = function () {
//使用排它思想點(diǎn)亮盒子
for(var j=0; j<spans.length; j++){
spans[j].className = "";
}
this.className = "current";
//移動(dòng)盒子
console.log(ul);
animation(ul,-this.index*scrollWidth);
}
}
function animation(ele,target) {
clearInterval(ele.timer);
var speed = target>ele.offsetLeft ? 10:-10;
ele.timer = setInterval(function () {
var val = target - ele.offsetLeft;
ele.style.left = ele.offsetLeft + speed + "px";
if (Math.abs(val)<Math.abs(speed)){
ele.style.left = target + "px";
clearInterval(ele.timer);
}
},1);
}
};
</script>
</body>
</html>
- 左右焦點(diǎn)圖铺坞;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>練習(xí)</title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 490px;
height: 170px;
margin: 60px auto;
border: 1px solid #aaa;
padding: 5px;
}
.inner{
width: 490px;
height: 170px;
position: relative;
overflow: hidden;
}
ul{
width: 500%;
position: absolute;
}
li{
list-style: none;
float: left;
}
.rl{
display: none;
}
.rl span{
position: absolute;
width: 30px;
height: 30px;
top: 70px;
color: #fff;
font-size: 30px;
line-height: 30px;
text-align: center;
background: #000 ;
left: 10px;
cursor: pointer;
opacity: 0.7;
}
.rl .right{
right: 10px;
left: auto;
}
</style>
</head>
<body>
<div class="box">
<div class="inner">
<ul>
<li>![](images/01.jpg)</li>
<li>![](images/02.jpg)</li>
<li>![](images/03.jpg)</li>
<li>![](images/04.jpg)</li>
<li>![](images/05.jpg)</li>
</ul>
<div class="rl">
<span class="left"><</span>
<span class="right">></span>
</div>
</div>
</div>
<script>
window.onload = function () {
//1.獲取事件源及相關(guān)元素
var box = document.getElementsByClassName("box")[0];
var inner = document.getElementsByClassName("inner")[0];
var ul = document.getElementsByTagName("ul")[0];
var rl = document.getElementsByClassName("rl")[0];
var left = document.getElementsByClassName("left")[0];
var right = document.getElementsByClassName("right")[0];
//獲取窗口寬度
var scrollW = inner.offsetWidth;
//2.左右按鈕的顯示和隱藏
box.onmouseover = function () {
rl.style.display = "block";
};
box.onmouseout = function () {
rl.style.display = "none";
};
//3.點(diǎn)擊左右按鈕
//定義一個(gè)計(jì)數(shù)器
var index = 0;
//點(diǎn)擊左邊按鈕
left.onclick = function () {
index --;
//如果現(xiàn)實(shí)第一個(gè)圖片時(shí)起宽,再點(diǎn)擊左邊按鈕時(shí)仍讓其顯示第一個(gè)圖片
if (index < 0){
index = 0;
}
animation(ul,- index * scrollW);
};
//點(diǎn)擊右邊按鈕
right.onclick = function () {
index ++;
//如果當(dāng)前圖片已經(jīng)是最后一個(gè),再點(diǎn)擊右邊按鈕時(shí)始終讓它展示最后一個(gè)
if (index > ul.children.length - 1){
index = ul.children.length - 1;
}
animation(ul,- index * scrollW)
};
//動(dòng)畫封裝
function animation(ele,target) {
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置步進(jìn)大小
var speed = target>ele.offsetLeft ? 10:-10;
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//先獲取元素目標(biāo)位置和當(dāng)前位置的距離val
var val = target - ele.offsetLeft;
ele.style.left = ele.offsetLeft + speed + "px";
//如果val小于步進(jìn)济榨,就使元素位置等于目標(biāo)位置坯沪,并清除定時(shí)器
if (Math.abs(val) < Math.abs(speed)){
ele.style.left = target + "px";
clearInterval(ele.timer);
}
},10);
}
}
</script>
</body>
</html>
- 帶有定時(shí)器的輪播圖。
緩動(dòng)(重點(diǎn)
)
現(xiàn)象:開(kāi)始走很快擒滑,越走越慢腐晾,步長(zhǎng)越來(lái)越小,類似電梯停止丐一。
好處:
有非常逼真的緩動(dòng)效果藻糖,實(shí)現(xiàn)的動(dòng)畫效果更細(xì)膩;
如果不清除定時(shí)器库车,物體永遠(yuǎn)跟著目標(biāo)在移動(dòng)巨柒。
緩動(dòng)動(dòng)畫公式:
動(dòng)畫原理 = 盒子位置 + 步長(zhǎng)(步長(zhǎng)越來(lái)越小);
盒子位置 = 盒子本身位置+(目標(biāo)位置-盒子本身位置)/ 10洋满;
公式:position = position + (target - position) / 10;
<body>
<button class="animate1">緩動(dòng)到400</button>
<div class="huanDong"></div>
<script>
var btn = document.getElementsByClassName("animate1")[0];
var div1 = document.getElementsByClassName("huanDong")[0];
btn.onclick = function () {
var timer = setInterval(function () {
div1.style.left = div1.offsetLeft + (400 - div1.offsetLeft) / 10 + "px";
if (div1.offsetLeft == 400){
clearInterval(timer);
}
},30);
};
</script>
</body>
但是有個(gè)現(xiàn)象晶乔,動(dòng)畫會(huì)永遠(yuǎn)執(zhí)行下去,不會(huì)停止牺勾。舉個(gè)例子:把一桶水正罢,倒進(jìn)另一通,每次倒一半驻民,永遠(yuǎn)倒不完腺怯;還有個(gè)原因就是
offsetLeft
會(huì)將獲取值四舍五入
之后再進(jìn)行計(jì)算。疑問(wèn):
原理:數(shù)學(xué)算法川无。其他運(yùn)動(dòng)形式其他算法。
為什么是10虑乖?:更符合我們的計(jì)算懦趋,邏輯,審美疹味,人體工程學(xué)仅叫。
(實(shí)際工作中,領(lǐng)導(dǎo)給我們什么技術(shù)糙捺,我們就直接用诫咱,空余時(shí)間研究源碼和原理)。
動(dòng)畫封裝問(wèn)題:
小數(shù)只能給定樣式洪灯,最好不要參與計(jì)算坎缭。(offsetLeft會(huì)將獲取值四舍五入取整后計(jì)算);
如果正向運(yùn)動(dòng)签钩,步長(zhǎng)是大于0掏呼;如果反向運(yùn)動(dòng),步長(zhǎng)就小于0铅檩。大于0向上取整憎夷,小于0向下取整。大于0的時(shí)候向上取整能夠取到1昧旨,小于零時(shí)向下取整才能取到-1(會(huì)在9和-9距離的時(shí)候出現(xiàn)問(wèn)題)拾给。
<body>
<button class="bigger">緩動(dòng)到400</button>
<button class="smaller">緩動(dòng)到200</button>
<button class="zero">緩動(dòng)到0</button>
<div class="huanDong"></div>
<script>
var btn1 = document.getElementsByClassName("bigger")[0];
var btn2 = document.getElementsByClassName("smaller")[0];
var btn3 = document.getElementsByClassName("zero")[0];
var div1 = document.getElementsByClassName("huanDong")[0];
btn1.onclick = function () {
animation(div1,400);
};
btn2.onclick = function () {
animation(div1,200);
};
btn3.onclick = function () {
animation(div1,0);
};
function animation(ele,target) {
//清除定時(shí)器
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//計(jì)算步長(zhǎng)
var step = (target - ele.offsetLeft) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
//移動(dòng)位置
ele.style.left = ele.offsetLeft + step + "px";
//如果距離小于步長(zhǎng)就將目標(biāo)位置賦值給盒子,并清除定時(shí)器
if (Math.abs(target - ele.offsetLeft)<=Math.abs(step)){
ele.style.left = target + "px";
clearInterval(ele.timer);
}
},30);
}
</script>
</body>
- 案例:
- 筋斗云(光標(biāo)移動(dòng)到對(duì)應(yīng)標(biāo)簽時(shí)兔沃,筋斗云圖片也移動(dòng)到對(duì)應(yīng)位置蒋得,在沒(méi)有點(diǎn)擊的情況下如果移開(kāi)光標(biāo)筋斗云到最初位置;如果點(diǎn)擊了某個(gè)標(biāo)簽粘拾,移開(kāi)光標(biāo)時(shí)窄锅,筋斗云仍然停留在點(diǎn)擊的標(biāo)簽處)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>筋斗云練習(xí)</title>
<style>
*{
margin: 0;
padding: 0;
}
body{
background-color: rgba(0,0,0,0.2);
}
.tab{
width: 600px;
height: 42px;
border-radius: 8px;
background: #fff url("images/wifi.png") right center no-repeat;
margin: 160px auto;
position: relative;
}
ul{
list-style: none;
position: absolute;
}
li{
float: left;
width: 83px;
height: 42px;
text-align: center;
line-height: 42px;
cursor: pointer;
}
span[class=cloud]{
position: absolute;
width: 83px;
height: 42px;
background: url("images/cloud.gif");
}
</style>
</head>
<body>
<div class="tab">
<span class="cloud"></span>
<ul>
<li>家鄉(xiāng)文化</li>
<li>沿海風(fēng)光</li>
<li>文人騷客</li>
<li>特色景點(diǎn)</li>
<li>特產(chǎn)美食</li>
</ul>
</div>
<script>
//入口函數(shù)
window.onload = function () {
//獲取事件源和一些相關(guān)的元素
var tab = document.getElementsByClassName("tab")[0];
var lis = document.getElementsByTagName("li");
var liW = lis[0].offsetWidth;
var cloud = document.getElementsByClassName("cloud")[0];
//書寫事件代碼
//定義一個(gè)計(jì)數(shù)器,移除光標(biāo)和點(diǎn)擊光標(biāo)時(shí)會(huì)用到
var count = 0;
for(var i=0; i<lis.length; i++){
lis[i].index = i;
//綁定鼠標(biāo)進(jìn)入事件
lis[i].onmouseover = function () {
//cloudAnimate(cloud,this.index * liW);
cloudAnimate(cloud,this.offsetLeft);
};
//鼠標(biāo)點(diǎn)擊事件
lis[i].onclick = function () {
count = this.index;
cloudAnimate(cloud,count * liW);
}
}
//鼠標(biāo)離開(kāi)事件
tab.onmouseout = function () {
cloudAnimate(cloud,count * liW);
};
//定義動(dòng)畫函數(shù)
function cloudAnimate(ele,target) {
//清空定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//計(jì)算步長(zhǎng)
var step = (target - ele.offsetLeft) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
//動(dòng)畫原理
ele.style.left = ele.offsetLeft + step + "px";
//如果距離小于等于步長(zhǎng),就將目標(biāo)位置直接賦值入偷,并清除定時(shí)器
if (Math.abs(target - ele.offsetLeft) <= Math.abs(step)){
ele.style.left = target + "px";
clearInterval(ele.timer);
}
},10);
}
};
</script>
</body>
</html>
冒泡
事件冒泡: 當(dāng)一個(gè)元素上的事件被觸發(fā)的時(shí)候追驴,比如說(shuō)鼠標(biāo)點(diǎn)擊了一個(gè)按鈕,同樣的事件將會(huì)在那個(gè)元素的所有祖先元素中被觸發(fā)其骄。這一過(guò)程被稱為事件冒泡逼肯;這個(gè)事件從原始元素開(kāi)始一直冒泡到DOM樹(shù)的最上層。(BUG)葫辐。(好比如:本來(lái)應(yīng)該一人做事一人當(dāng)昆箕,結(jié)果纤泵,我做錯(cuò)了事情带射,你去告訴我媽)
事件傳播階段:
事件傳播的三個(gè)階段:捕獲灿里、冒泡、目標(biāo)階段;
事件捕獲階段:事件從最上一級(jí)標(biāo)簽開(kāi)始往下查找校焦,直到捕獲到事件目標(biāo)(target)【從上往下】报亩;
事件冒泡階段:事件從事件目標(biāo)開(kāi)始,往上冒泡直到頁(yè)面的最上一級(jí)標(biāo)簽【從下往上】遍烦。
什么是冒泡:子元素事件被觸動(dòng)俭嘁,父盒子的同樣的事件也會(huì)被觸動(dòng)。
冒泡順序:
IE6.0:div->body->html->document服猪;
其它瀏覽器:div->body->html->document->window供填。
不是所有的事件都能冒泡,以下事件不能冒泡:blur罢猪、focus近她、load、unload膳帕、onmouseenter粘捎、onmouseleave。
取消冒泡就是取消這種機(jī)制危彩。
阻止冒泡
- w3c的方法是:
- 火狐攒磨、谷歌、IE11:
event.stopPropagation()
汤徽; - IE10以下:
event.cancelBubble = true
娩缰; - 兼容代碼如下:
var event = event || window.event;
if(event && event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
獲取當(dāng)前對(duì)象
- IE678:
event.srcElement
(事件源); - 火狐谒府、谷歌等:
event.target
(事件源)拼坎;,誰(shuí)觸動(dòng)事件完疫,誰(shuí)就會(huì)被放進(jìn)target中泰鸡; - 兼容寫法獲取元素ID:
var event = event || window.event;
var targetId = event.target ? event.target.id:event.srcElement.id;
addEventListenner(參數(shù)1,參數(shù)2壳鹤,參數(shù)3)
調(diào)用者是:事件源盛龄;
參數(shù)1:事件去掉on;
參數(shù)2 :調(diào)用的函數(shù)
參數(shù)3:可有可無(wú)芳誓。默認(rèn)false讯嫂,false情況下,支持冒泡兆沙,true支持捕獲欧芽。
案例
-
點(diǎn)擊空白隱藏模態(tài)框
- Document事件的綁定,無(wú)論綁定什么事件葛圃,只要事件被出發(fā)千扔,傳遞過(guò)來(lái)的應(yīng)該是指定的元素本身憎妙,而不是document。
-
事件委托
- 先綁定曲楚,后創(chuàng)建的元素(沒(méi)有事件)厘唾;
- 組織冒泡,組織自己向父系盒子冒泡龙誊,所有的泡冒泡到組織的位置停止向上冒泡抚垃;
- event.target是在事件被觸動(dòng)的時(shí)候把事件源綁定到event的target屬性中。而之前的target是我們自定義的一個(gè)變量觸動(dòng)趟大。
補(bǔ)充
獲取行內(nèi)式和內(nèi)嵌式屬性的值
行內(nèi)式:
div.style.width
鹤树,只能獲取行內(nèi)式屬性的值,有單位px
逊朽,只包含盒子的width
罕伯,不包含padding和border;內(nèi)嵌式:
div.offsetWidth
叽讳,沒(méi)有單位追他,包含width、padding岛蚤、border邑狸。獲取行內(nèi)式和內(nèi)嵌式屬性的值:
window.getComputedStyle(div,null)
獲取到的值是對(duì)象類型:
var w = window.getComputedStyle(div,null).width;
var color = window.getComputedStyle(div, null)["backgroundColor"];
- 獲取到的值有單位`px`,只包含`width`涤妒,不包含padding和border单雾;
-
div.currentStyle.width
只支持IE678:
console.log(div.currentStyle.width);
console.log(div.currentStyle.padding);
- 兼容方式獲取元素某個(gè)樣式
function getStyle(ele, attr) {
if(window.getComputedStyle){
return window.getComputedStyle(ele,null).attr;
}else {
return ele.currentStyle[attr];
}
}
緩動(dòng)的高級(jí)封裝
單個(gè)屬性封裝
- 利用通過(guò)兼容方式獲取元素某個(gè)屬性的值:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>緩動(dòng)封裝-單個(gè)屬性</title>
<style>
div{
width: 100px;
height: 100px;
border: 5px solid #ddd;
margin-top: 10px;
background-color: pink;
position: absolute;
}
</style>
</head>
<body>
<button>緩動(dòng)到400</button>
<button>長(zhǎng)度變成300</button>
<div></div>
<script>
//入口函數(shù)
window.onload = function () {
//獲取事件源
var btns = document.getElementsByTagName("button");
var area = document.getElementsByTagName("div")[0];
//綁定事件
btns[0].onclick = function () {
animate(area,"left",400);
};
btns[1].onclick = function () {
animate(area,"width",300);
};
//緩動(dòng)動(dòng)畫封裝
function animate(ele,attr,target) {
//獲取元素屬性的值
var currentP = parseInt(getStyle(ele,attr)) || 200;
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//計(jì)算步長(zhǎng)
var step = (target - currentP) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
//動(dòng)畫原理
currentP = currentP + step;
ele.style[attr] = currentP + "px";
//清除定時(shí)器
if (Math.abs(target - currentP) <= Math.abs(step)){
ele.style[attr] = target + "px";
clearInterval(ele.timer);
}
},30);
}
//獲取某個(gè)屬性的值
function getStyle(ele, attr) {
if (window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else {
return ele.currentStyle[attr];
}
}
}
</script>
</body>
</html>
多個(gè)屬性封裝
- 單次運(yùn)動(dòng):
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多個(gè)屬性</title>
<style>
div{
width: 100px;
height: 100px;
position: absolute;
right: 0;
background-color: palevioletred;
border: 5px solid #ccc;
}
</style>
</head>
<body>
<button>點(diǎn)擊運(yùn)動(dòng)</button>
<div></div>
<script>
window.onload = function () {
//獲取事件源和相關(guān)元素
var btn = document.getElementsByTagName("button")[0];
var div = document.getElementsByTagName("div")[0];
//綁定事件
btn.onclick = function () {
//通過(guò)JSON修改盒子多個(gè)屬性的值
var json = {"left":200,"width":200,"height":200,"top":50};
animate(div,json);
};
//封裝動(dòng)畫
function animate(ele,json) {
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//設(shè)置一個(gè)標(biāo)志,記錄是否符合清除定時(shí)器的條件
var bool = true;
//遍歷json
for (var k in json){
//獲取元素屬性值
var currentP = parseInt(getStyle(ele,k)) || 200;
//計(jì)算步長(zhǎng)
var step = (json[k] - currentP) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
currentP = currentP + step;
ele.style[k] = currentP + "px";
//記錄狀態(tài)
if (Math.abs(json[k] - currentP) > Math.abs(step)){
bool = false;
}
}
//判斷是否符合清除定時(shí)器的條件
if (bool){
for (var k in json){
ele.style[k] = json[k] + "px";
}
clearInterval(ele.timer);
}
},30);
}
//獲取元素屬性值
function getStyle(ele, attr) {
if (window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else {
return ele.currentStyle[attr];
}
}
}
</script>
</body>
</html>
- 往返運(yùn)動(dòng):方法一
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多個(gè)屬性</title>
<style>
div{
width: 100px;
height: 100px;
position: absolute;
left: 30px;
top: 40px;
background-color: palevioletred;
border: 5px solid #ccc;
}
</style>
</head>
<body>
<button>點(diǎn)擊運(yùn)動(dòng)</button>
<div></div>
<script>
window.onload = function () {
//獲取事件源和相關(guān)元素
var btn = document.getElementsByTagName("button")[0];
var div = document.getElementsByTagName("div")[0];
//綁定事件
btn.onclick = function () {
//通過(guò)JSON修改盒子多個(gè)屬性的值
var json1 = {"width":200,"height":200,"left":100,"top":150};
var json2 = {"width":100,"height":100,"left":30,"top":40};
animate(div,json1,json2);
};
//封裝動(dòng)畫
function animate(ele,json,fn) {
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//設(shè)置一個(gè)標(biāo)志届腐,記錄是否符合清除定時(shí)器的條件
var bool = true;
//遍歷json
for (var k in json){
//獲取元素屬性值
var currentP = parseInt(getStyle(ele,k)) || 200;
//計(jì)算步長(zhǎng)
var step = (json[k] - currentP) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
currentP = currentP + step;
ele.style[k] = currentP + "px";
//記錄狀態(tài)
if (Math.abs(json[k] - currentP) > Math.abs(step)){
bool = false;
}
}
//判斷是否符合清除定時(shí)器的條件
if (bool){
for (var k in json){
ele.style[k] = json[k] + "px";
}
clearInterval(ele.timer);
if (fn){
animate(ele,fn);
}
}
},30);
}
//獲取元素屬性值
function getStyle(ele, attr) {
if (window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else {
return ele.currentStyle[attr];
}
}
}
</script>
</body>
</html>
- 往返運(yùn)動(dòng):方法二
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多個(gè)屬性</title>
<style>
div{
width: 100px;
height: 100px;
position: absolute;
left: 30px;
top: 40px;
background-color: palevioletred;
border: 5px solid #ccc;
}
</style>
</head>
<body>
<button>點(diǎn)擊運(yùn)動(dòng)</button>
<div></div>
<script>
window.onload = function () {
//獲取事件源和相關(guān)元素
var btn = document.getElementsByTagName("button")[0];
var div = document.getElementsByTagName("div")[0];
//綁定事件
btn.onclick = function () {
//通過(guò)JSON修改盒子多個(gè)屬性的值
var json1 = {"width":200,"height":200,"left":100,"top":150};
var json2 = {"width":100,"height":100,"left":30,"top":40};
// animate(div,json1,json2);
animate(div,json1,function () {
animate(div,json2,function () {
animate(div,json1,function () {
animate(div,json2,function () {
animate(div,json1);
});
});
});
});
};
//封裝動(dòng)畫
function animate(ele,json,fn) {
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//設(shè)置一個(gè)標(biāo)志,記錄是否符合清除定時(shí)器的條件
var bool = true;
//遍歷json
for (var k in json){
//獲取元素屬性值
var currentP = parseInt(getStyle(ele,k)) || 200;
//計(jì)算步長(zhǎng)
var step = (json[k] - currentP) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
currentP = currentP + step;
ele.style[k] = currentP + "px";
//記錄狀態(tài)
if (Math.abs(json[k] - currentP) > Math.abs(step)){
bool = false;
}
}
//判斷是否符合清除定時(shí)器的條件
if (bool){
for (var k in json){
ele.style[k] = json[k] + "px";
}
clearInterval(ele.timer);
if (fn){
// animate(ele,fn);
fn();
}
}
},30);
}
//獲取元素屬性值
function getStyle(ele, attr) {
if (window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else {
return ele.currentStyle[attr];
}
}
}
</script>
</body>
</html>
案例:
- 手風(fēng)琴蜂奸;
- 360開(kāi)機(jī)動(dòng)畫犁苏。
緩動(dòng)框架存在的問(wèn)題:
- 有很多屬性依然無(wú)法獲取值和賦值:
- border-radius:1px 2px 3px 4px;
- 渲染有問(wèn)題,可以通過(guò)拆解來(lái)解決扩所,解決方法如下:
div.style.borderBottomLeftRadius = "30px";
div.style.borderTopRightRadius = "30px";
-
opacity:0.5;
(沒(méi)有單位的)- 火狐围详、谷歌、IE9+祖屏,
opacity:0.5;
助赞,內(nèi)容一起透明,取值范圍:0~1
袁勺,但是賦值的時(shí)候一般用百分制雹食,但最后賦值時(shí)候再除以一百,因?yàn)樾?shù)有精度問(wèn)題期丰,防止中途需要運(yùn)算群叶,使誤差變大吃挑; - IE678(一般不研究),
filter:alpha(opacity=50);
街立,取值范圍:0~100
舶衬。
- 火狐围详、谷歌、IE9+祖屏,
- background:rgba(0,0,0,0.3);
-
z-index:1;
...等等。
增加了透明度和層級(jí)之后的封裝
/**
* Created by YJW on 2017/8/11.
*/
//勻速運(yùn)動(dòng)動(dòng)畫
function conSpeedAnimate(ele,distance) {
//1.使用定時(shí)器之前必須先清除赎离,排除多次點(diǎn)擊越來(lái)越快的bug
clearInterval(ele.timer); //將定時(shí)器作為元素的屬性
//2.為了能讓div可以從后往前走逛犹,要先進(jìn)行判斷目標(biāo)位置和當(dāng)前位置的大小,如果目標(biāo)位置大梁剔,步進(jìn)就正虽画,否則就負(fù)
var speed = distance>ele.offsetLeft ? 10:-10;
ele.timer = setInterval(function () {
var val = distance - ele.offsetLeft; //測(cè)試發(fā)現(xiàn):此句位置至關(guān)重要,不能和下一句倒換位置
ele.style.left = ele.offsetLeft + speed + "px";
//3.到達(dá)目標(biāo)位置后憾朴,再次點(diǎn)擊會(huì)出現(xiàn)抖動(dòng)現(xiàn)象狸捕。解決方案,判斷目標(biāo)位置和當(dāng)前位置距離是否小于步進(jìn)众雷,如果小于就讓兩者相等灸拍,并立刻清除定時(shí)器
if (Math.abs(val)<Math.abs(speed)){
ele.style.left = distance + "px";
clearInterval(ele.timer);
}
},10);
}
//緩動(dòng)動(dòng)畫
function slowMovingAnimateX(ele,targetX) {
//清空定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//計(jì)算步長(zhǎng)
var stepX = (targetX - ele.offsetLeft) / 10;
stepX = stepX>0 ? Math.ceil(stepX):Math.floor(stepX);
//動(dòng)畫原理
ele.style.left = ele.offsetLeft + stepX + "px";
//如果距離小于等于步長(zhǎng),就將目標(biāo)位置直接賦值砾省,并清除定時(shí)器
if (Math.abs(targetX - ele.offsetLeft) <= Math.abs(stepX)){
ele.style.left = targetX + "px";
clearInterval(ele.timer);
}
},10);
}
function slowMovingAnimateY(ele,targetY) {
//清空定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//計(jì)算步長(zhǎng)
var stepY = (targetY - ele.offsetTop) / 10;
stepY = stepY>0 ? Math.ceil(stepY):Math.floor(stepY);
//動(dòng)畫原理
ele.style.top = ele.offsetTop + stepY + "px";
//如果距離小于等于步長(zhǎng)鸡岗,就將目標(biāo)位置直接賦值愁铺,并清除定時(shí)器
if (Math.abs(targetY - ele.offsetTop) <= Math.abs(stepY)){
ele.style.top = targetY + "px";
clearInterval(ele.timer);
}
},10);
}
//對(duì)scroll()函數(shù)進(jìn)行封裝
function scroll(){
//如果window.pageYOffset存在妥曲,返回值為0~無(wú)窮大逊躁,如果不存在返回undefined吱型。
if (window.pageYOffset !== undefined){
var json = {
"top":window.pageYOffset,
"left":window.pageXOffset
}
return json;
} else if (document.compatMode === CSS1Compat) {
return {
"top":document.documentElement.scrollTop,
"left":document.documentElement.scrollLeft
}
} else {
return {
"top":document.body.scrollTop,
"left":document.body.scrollLeft
}
}
}
// function scroll() {
// return {
// "top" : window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop,
// "left" : window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft
// }
// }
//對(duì)clientWidth進(jìn)行封裝(獲取盒子/body浙滤、html可視區(qū)域的寬高)
function client() {
if (window.innerWidth !== undefined){
return{
"width":window.innerWidth,
"height":window.innerHeight
}
}else if (document.compatMode === "CSS1Compat"){
return{
"width":document.documentElement.clientWidth,
"height":document.documentElement.clientHeight
}
}else {
return{
"width":document.body.clientWidth,
"height":document.body.clientHeight
}
}
}
//盒子的隱藏和顯示
function show(div) {
div.style.display = "block";
}
function hide(div) {
div.style.display = "none";
}
//獲取鼠標(biāo)在盒子中的位置
function positionXY(event, div) {
//獲取鼠標(biāo)的位置
event = event || window.event;
var pagex = event.pageX || event.clientX + scroll().left;
var pagey = event.pageY || event.clientY + scroll().top;
//獲取鼠標(biāo)在盒子中的位置耸别,并讓鼠標(biāo)處在遮蓋中間位置
var positionX = pagex - content.offsetLeft;
var positionY = pagey - content.offsetTop;
return{
"positionX":positionX,
"positionY":positionY
}
}
//緩動(dòng)動(dòng)畫高級(jí)封裝--單個(gè)屬性
function animate(ele,attr,target) {
//獲取元素屬性的值
var currentP = parseInt(getStyle(ele,attr)) || 0;
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//計(jì)算步長(zhǎng)
var step = (target - currentP) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
//動(dòng)畫原理
currentP = currentP + step;
ele.style[attr] = currentP + "px";
//清除定時(shí)器
if (Math.abs(target - currentP) <= Math.abs(step)){
ele.style[attr] = target + "px";
clearInterval(ele.timer);
}
},30);
}
//封裝緩動(dòng)動(dòng)畫----設(shè)置多個(gè)屬性
function animate(ele,json,fn) {
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//設(shè)置一個(gè)標(biāo)志幔摸,記錄是否符合清除定時(shí)器的條件
var bool = true;
//遍歷json
for (var k in json){
//獲取元素屬性值
var currentP = parseInt(getStyle(ele,k)) || 0;
//計(jì)算步長(zhǎng)
var step = (json[k] - currentP) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
currentP = currentP + step;
ele.style[k] = currentP + "px";
//記錄狀態(tài)
if (Math.abs(json[k] - currentP) > Math.abs(step)){
bool = false;
}
}
//判斷是否符合清除定時(shí)器的條件
if (bool){
for (var k in json){
ele.style[k] = json[k] + "px";
}
clearInterval(ele.timer);
if (fn){
// animate(ele,fn);
fn();
}
}
},30);
}
//緩動(dòng)動(dòng)畫封裝----增加了透明度和層級(jí)
function animate(ele,json,fn) {
//清除定時(shí)器
clearInterval(ele.timer);
//設(shè)置定時(shí)器
ele.timer = setInterval(function () {
//設(shè)置一個(gè)標(biāo)志拒迅,記錄是否符合清除定時(shí)器的條件
var bool = true;
//遍歷json
for (var k in json){
//獲取元素屬性值
var currentP;
// 如果是opacity獲取值之后需要進(jìn)行特殊處理
if (k === "opacity"){
currentP = getStyle(ele,k)*100 || 10;
console.log(getStyle(ele,k));
}else {
console.log(getStyle(ele, k) + " -- " + k);
currentP = parseInt(getStyle(ele,k)) || 0;
}
//計(jì)算步長(zhǎng)
var step = (json[k] - currentP) / 10;
step = step>0 ? Math.ceil(step):Math.floor(step);
currentP = currentP + step;
//如果是opacity需要特殊賦值處理
if (k === "opacity"){
ele.style[k] = currentP / 100;
//兼容IE678
ele.style["filter"] = "alpha(opacity=" + currentP + ")";
}else if (k === "z-index"){
ele.style[k] = json[k];
}else {
ele.style[k] = currentP + "px";
}
//記錄狀態(tài)
if (Math.abs(json[k] - currentP) > Math.abs(step)){
bool = false;
}
}
//判斷是否符合清除定時(shí)器的條件
if (bool){
for (var k in json){
ele.style[k] = json[k] + "px";
}
clearInterval(ele.timer);
if (fn){
fn();
}
}
},30);
}
//兼容方式獲取元素屬性值
function getStyle(ele, attr) {
if(window.getComputedStyle){
return window.getComputedStyle(ele,null).attr;
}else {
return ele.currentStyle[attr];
}
}
案例
- 旋轉(zhuǎn)輪播圖件舵;