在咱們工做中,js動畫用的最多的可能就是:網站的滾動banner圖片和電商網站的分層。這些動畫原理是左右或上下移動位置的改變,要完成這些改變,咱們須要瞭解動畫元素的三大位置系列:offset、scroll和client。javascript
offset是指html中定位了的元素,相對於它一樣定位了的父級元素才存在的。若是一層一層往上面找,父級元素都沒有定位,則就直接找到body。offset返回的是數字(number),而且是隻讀的,相對而言的style.left/style.top 則返回的字符串(就是帶有px單位的),能夠進行修改。咱們在作動畫的時候,最多的就是將offsetLeft賦值給style.left,要注意將加上單位‘px'。html
<script> obj.style.left = obj.offsetLeft + 'px'; </script
首先咱們來看看和offset有關的屬性:offsetWidth、offsetHeight、offsetLeft、offsetTop、offsetParenthtml5
offsetWidth/offsetHeight 獲取元素寬高,包括width/height + 2*border + 2* padding offsetLeft / offsetTop 獲取元素相對於父元素的左/上距離,父元素必須是定位的。若是父元素沒有定位,則直接相對於body元素 offsetParent 找到當前元素的定位父元素,沒有則就是body元素
和scroll相關的屬性都是在觸發onscroll事件後纔會存在的,因此和scroll相關的內容都是在document.onscroll裏面。java
scrollWidth / scrollHeight 滾動元素的寬/高 width / height + 2* padding scrollTop / scrollLeft 滾動條移動的距離(也就是滾動後隱藏的部分) window.scrollTo(x,y)移動滾動條到什麼座標,通常設置爲想要的左右
可是因爲DTD的存在(html5後就沒有DTD了)和IE瀏覽器的bug,使得scrollTop與scrollLeft存在了兼容性問題,最好是能封裝一個函數解決兼容性問題。瀏覽器
<script> function scroll() { // 火狐、google、IE9+支持 if (window.pageYOffset !== undefined) { return { top: window.pageYOffset, left: window.pageXOffset } // 存在DTD的狀況,ie低版本支持 } else if (document.compatMode == "CSS1comPat") { return { top: document.documentElement.scrollTop, left: document.documentElement.scrollLeft } } else { // 不存在DTD的狀況,google支持 return { top: document.body.scrollTop, left: document.bodyscrollLeft } } } </script>
client主要有clientX與clientY兩個屬性,是js事件event的屬性,用來判斷事件發生時,鼠標距離瀏覽器左上角的距離。通常作的動畫是和鼠標事件相關的,電商的放大鏡效果和鼠標跟隨效果。函數
閃動動畫就是直接設置值,好比left = 100,width = 100 , top = 100 ,height = 100等。這種動畫就沒有過渡效果,直接跳到目標狀態。動畫
<script> obj.onclick = function animate(){ obj.style.left = 200 + 'px'; } </script>
勻速運動是設置一個步長(step)後,而後在定時器裏面改變狀態,達到目標位置結束。網站
<script> function animate(){ var timer = null; timer = setInterval(function(){ var target = 400; var step = target > obj.offsetLeft ? 10 : -10; obj.style.left = obj.offsetLeft + step + 'px'; },25); if(Math.abs(target - obj.offsetLeft) < Math.abs(step)){ obj.style.left = target; clearInterval(timer); } } </script>
緩動運動是設置一個會改變的步長(step),而後在定時器裏面改變狀態,知道步長變成0結束,但根據改變只會接近0而不會變成0,因此須要使用Math對象的ceil與floor方法。google
<script> var timer = null; function animate(){ timer = setInterval(function(){ var target = 400; var step = target > obj.offsetLeft ? Math.ceil((target - obj.offsetLeft)/10) : Math.floor((target-obj.offsetLeft)/10); obj.style.left = obj.offsetLeft + step + 'px'; },25); if(Math.abs(target - obj.offsetLeft) < Math.abs(step)){ obj.style.left = target; clearInterval(timer); } } </script>