1. 程式人生 > 其它 >JS5-PC端網頁特效

JS5-PC端網頁特效

常見offset系列屬性作用

常見client系列屬性作用

常見scroll系列屬性作用

封裝簡單動畫函式

寫出網頁輪播圖案例

offset

偏移量,使用offset相關屬性可以動態的得到該元素的位置、大小等

  • 獲得元素距離帶有定位父元素的位置
  • 獲得元素自身的大小
  • 注意:返回的數值不帶單位

offsetParent: 返回作為該元素帶有定位的父級元素,如果父級都沒有定位則返回body

offsetWidth:獲取元素的寬,包括內邊距、邊框、內容

offsetHeight:獲取元素的高,包括內邊距、邊框、內容

offsetLeft:獲取元素距離左邊位置的值,以帶有定位的父親為準,如果沒有父親或者父親沒有定位則相對body

offsetTop;獲取元素距離上面位置的值,以帶有定位的父親為準,如果沒有父親或者父親沒有定位則相對body

offset與style區別

  • offset可以得到任意樣式表的樣式值 style只能得到內嵌樣式的樣式值
  • offset得到的是數字型,不帶單位 style是字串帶單位
  • offset包含整個盒子,style得到的只是width,不包括padding和border
  • offset只能讀不能寫,而width可以賦值
  • 因此,讀屬性值一般用offset,寫屬性一般用width

案例:獲取滑鼠在盒子裡的座標

  1. 獲取滑鼠在頁面內的座標
  2. 獲取盒子在頁面內的座標
  3. 相減
var box=document.querySelector('.box');
box.addEventListener('mousemove',function(){//滑鼠移動事件
    var x=e.pageX-this.offsetLeft;
    var y=e.pageY-this.offsetTop;
    this.innerHTML='X座標是'+x+'y座標是'+y;
})

元素可視區client系列

client是客戶端,可動態得到元素邊框大小,元素大小等,與offset最大的區別就是不包含邊框

clientTop 上邊框

clientLeft 左邊框

clientWidth

clientHeight 包括padding、內容,不包括邊框,返回數值不帶單位

立即執行函式

不需要呼叫立馬能夠自己執行的函式

(function(){})()    或者  (function(){}())
  • 第二個小括號可以看做是呼叫函式,可以傳遞引數,外面括號是實參,裡面小括號是形參
  • 兩種方法使用方法一致
  • 最大的作用就是獨立建立了一個作用域,所有變數都是區域性變數,不會有命名衝突

淘寶原始碼分析

(function flexible(window, document) {
    var docEl = document.documentElement
    var dpr = window.devicePixelRatio || 1

    // adjust body font size
    function setBodyFontSize() {
        if (document.body) {
            document.body.style.fontSize = (12 * dpr) + 'px'
        } else {
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10
    function setRemUnit() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    }

    setRemUnit()

    // reset rem unit on page resize
    window.addEventListener('resize', setRemUnit)
    window.addEventListener('pageshow', function(e) {
        if (e.persisted) {
            setRemUnit()
        }
    })

    // detect 0.5px supports
    if (dpr >= 2) {
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testElement.offsetHeight === 1) {
            docEl.classList.add('hairlines')
        }
        docEl.removeChild(fakeBody)
    }
}(window, document))
  • 前進後退、a標籤、重新整理都會觸發load,但是火狐瀏覽器使用load事件時存在往返快取,後退按鈕不能重新整理頁面,可以使用pageshow事件觸發,這個事件在頁面顯示時觸發,無論頁面是否來自快取,可以根據事件物件的persisted判斷是否快取中頁面觸發的pageshow事件,這個事件要給window新增

元素滾動scroll系列

scrollTop: 返回被捲去的上側距離,返回數值不帶單位(隱藏的高度)

scrollLeft: 左側距離,同上

scrollWidth: 返回自身實際寬度,不含邊框,返回數值不帶單位,包含內容超出盒子的部分

scrollHeight:高度 同上

scroll事件:

'scroll' 滾動觸發的事件

window.pageXOffset:頁面被捲曲的頭部

相容性問題:

  1. 聲明瞭DTD,使用document.documentElement.scrollTop
  2. 未宣告DTD,使用document.body.scrollTop
  3. 新方法window.pageYOffset和window.pageXOffset,IE9開始支援

相容性方案(瞭解)

function getScroll() {
    return {
        left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
        top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
    };
}

三大系列總結

  • offset包含邊框,scroll包括文字超出部分

  • offset一般用於獲取元素位置,client常用與獲取元素大小,獲取滾動距離一般用scroll

mouseenter和mouseover

mouseover:經過自身盒子會觸發,經過子盒子還會觸發一次

mouseenter只有經過自身盒子才會觸發,因為mouseenter不會冒泡

動畫函式封裝

動畫實現原理

通過定時器setInterval()不斷移動盒子位置

  1. 獲取盒子當前位置
  2. 在盒子當前位置上加移動距離
  3. 利用定時器不斷重複操作
  4. 加一個結束定時器的條件
  5. 此元素一定要加定位,因為要使用element.left實現移動

動畫函式簡單封裝

需要傳遞兩個引數,動畫物件和移動的距離

可以實現某個物件右移移動到某個位置

function animate(obj,target){
	clearInterval(obj.timer)//
    obj.timer=setInterval(function(){
        if(obj.offsetLeft>=target){
            clearInterval(obj.timer);
        }
        obj.style.left=obj.offsetLeft+1+'px';
    },30);
}
  • var timer=每次開闢空間浪費資源,且使用obj.timer避免不同調用使用相同的變數timer,因此通過新增屬性實現給不同元素新增不同定時器
  • 注意要先清除原來的定時器,只保留當前定時器,避免多次觸發動畫時建立很多定時器造成不正常現象

緩動動畫

讓元素的運動速度有所變化,最常見的是讓速度慢慢減下來

思路:

  1. 讓盒子每次移動的距離慢慢變小
  2. (目標值-現在的位置)/10 作為每次移動的距離步長即可
  3. 停止的條件:讓當前盒子位置等於目標位置時停止定時器

把每次+1的步長改為慢慢變小的值 即

function animate(obj,target){
	clearInterval(obj.timer)//
    obj.timer=setInterval(function(){
    	var step=target-obj.offsetLeft)/10;//計算步長,要注意不要出現小號,還要考慮負值
    	step>0?Math.ceil(step):Math.floor(step)
        if(obj.offsetLeft==target){//修改為等於號
            clearInterval(obj.timer);
        }
        obj.style.left=obj.offsetLeft+step+'px';
    },30);
}

為了實現在多個目標間移動,需要考慮步長正負

動畫函式添加回調函式(重要)

回撥函式原理:函式可以作為一個引數,將這個引數傳到另一個函式裡,當那個函式執行完之後再執行傳進去的這個函式,這個過程稱為回撥

操作方法:輸入新增一個函式作為引數,函式執行寫在計時器停止的內容裡,即可實現執行完動畫後執行回撥函式

if(callback){

callback()}

如下程式碼即可實現運動完畢後盒子變顏色

function animate(obj, target, callback) {
            // console.log(callback);  callback = function() {}  呼叫的時候 callback()

            // 先清除以前的定時器,只保留當前的一個定時器執行
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                // 步長值寫到定時器的裡面
                // 把我們步長值改為整數 不要出現小數的問題
                // var step = Math.ceil((target - obj.offsetLeft) / 10);
                var step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (obj.offsetLeft == target) {
                    // 停止動畫 本質是停止定時器
                    clearInterval(obj.timer);
                    // 回撥函式寫到定時器結束裡面
                    if (callback) {
                        // 呼叫函式
                        callback();
                    }
                }
                // 把每次加1 這個步長值改為一個慢慢變小的值  步長公式:(目標值 - 現在的位置) / 10
                obj.style.left = obj.offsetLeft + step + 'px';

            }, 15);
        }
        var span = document.querySelector('span');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');

        btn500.addEventListener('click', function() {
            // 呼叫函式
            animate(span, 500);
        })
        btn800.addEventListener('click', function() {
                // 呼叫函式
                animate(span, 800, function() {
                    // alert('你好嗎');
                    span.style.backgroundColor = 'red';
                });
            })

返回頂部

window.scroll(0, 0);//x,y不跟單位直接寫數字就好
  1. 快速滾動到頂端

  2. 編寫垂直運動的動畫函式,點選後目標設為0(y座標)

goBack.addEventListener('click', function () {
            animate(window, 0);//視窗動畫,物件是window
        });
        function animate(obj, target, callback) {
            // console.log(callback);  callback = function() {}  呼叫的時候 callback()

            // 先清除以前的定時器,只保留當前的一個定時器執行
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 步長值寫到定時器的裡面
                // 把我們步長值改為整數 不要出現小數的問題
                // var step = Math.ceil((target - obj.offsetLeft) / 10);

                var step = (target - window.pageYOffset) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (window.pageYOffset == target) {
                    // 停止動畫 本質是停止定時器
                    clearInterval(obj.timer);
                    // 回撥函式寫到定時器結束裡面
                    callback && callback();//如果有引數傳入才會呼叫callback
                }
                // 把每次加1 這個步長值改為一個慢慢變小的值  步長公式:(目標值 - 現在的位置) / 10
                // obj.style.left = obj.offsetLeft + step + 'px';
                window.scroll(0, window.pageYOffset + step);

            }, 15);
        }