天天看點

跟着pink老師學前端之JavaScript特效1. 元素偏移量 offset系列2. 元素可視區client系列3. 元素滾動scroll系列4. 三大系列總結5. mouseover和mouseenter的差別6. 動畫函數封裝

1. 元素偏移量 offset系列

offset翻譯過來就是偏移量,我們可以使用offset系列相關的屬性可以動态的得到該元素的位置(偏移)、大小等。

1.1 offset系列常用屬性

傳回的數值都不帶機關

屬性 描述
element.offsetParent 傳回帶有定位的父親,否則傳回的是body
element.offsetTop 傳回元素相對帶有定位父元素上方的偏移,若沒有父親或父親不帶機關,則以body為準
element.offsetLeft 傳回元素相對帶有定位父元素左邊框的偏移,若沒有父親或父親不帶機關,則以body為準
element.offsetWidth 傳回自身包括padding、邊框、内容區的寬度
element.offsetHeight 傳回自身包括padding、邊框、内容區的高度度

注意:element.parentNode傳回的是最近一級的父元素,不管該父元素有無定位。

1.2 offset系列和style的差別

offset style
offset可以得到任意樣式表中的樣式值 style隻能得到行内樣式表中的樣式值
offset系列獲得的數值是沒有機關的 style.width獲得的是帶有機關的字元串
offsetWidth包含padding+ border+width style.width獲得不包含padding和border的值
offsetWidth 等屬性是隻讀屬性,隻能擷取不能指派 style.width是可讀寫屬性,可以擷取也可以指派
是以,我們想要擷取元素大小位置,用offset更合适 是以,我們想要給元素更改值,則需要用style改變

2. 元素可視區client系列

client翻譯過來就是用戶端,我們使用client系列的相關屬性來擷取元素可視區的相關資訊。通過client相關屬性可以動态的得到該元素的邊框大小、元素大小等。

2.1 client系列常用屬性

client相關屬性 描述
element.clientTop 傳回元素上邊框的大小
element.clientLeft 傳回元素左邊框的大小
element.clientWidth 傳回自身包括padding、内容區的寬度,不含邊框,傳回值不帶機關
element.clientHeight 傳回自身包括padding、内容區的高度,不含邊框,傳回值不帶機關

client和offset最大的差別是傳回寬度和高度時,offset包括邊框,client不包括邊框。

2.2 flexible分析案例

1. 立即執行函數

立即執行函數:不需要調用,立馬能夠自己執行的函數。

(function () {
    console.log('riki');
})();   
// or
(function sum(a, b) {
    console.log(a + b);
}(2, 3));
           

注意:

  • 第二個小括号可以看作是調用函數,也可以在裡面傳參。
  • 立即執行函數最大的作用就是獨立建立了一個作用域,裡面所有的變量全部是局部變量,不會出現命名沖突。
  • 也可以給函數起名字

2. pageshow事件

有三種情況會重新整理頁面而觸發load事件:

  1. a标簽的超連結。
  2. F5或者重新整理按鈕。
  3. 前進後退按鈕。

但是火狐中,有個特點,有個“往返緩存”,這個緩存中不僅儲存着頁面資料,還儲存了DOM和JavaScript的狀态;實際上是将整個頁面都儲存在了記憶體裡。是以此時後退按鈕不能重新整理頁面。

此時可以使用pageshow事件來觸發。這個事件在頁面顯示時觸發,無論頁面是否來自緩存。在重新加載頁面中,pageshow會在load事件觸發後觸發,根據事件對象中的persisted來判斷是否是緩存中的頁面觸發的pageshow事件,注意這個事件給window添加。

3. 元素滾動scroll系列

scroll翻譯過來就是滾動的,我們使用scroll系列的相關屬性可以動态的得到該元素的大小、滾動距離等。

3.1 scroll系列常用屬性

傳回值都不帶機關。

屬性 描述
element.scrollTop 傳回被卷去的上側距離
element.scrollLeft 傳回被卷去的左側距離
element.scrollWidth 傳回自身實際内容的寬度,不含邊框
element.scrollHeight 傳回自身實際内容的寬度,不含邊框

3.2 頁面被卷去的頭部

如果浏覽器的高(或寬)度不足以顯示整個頁面時,會自動出現滾動條。當滾動條向下滾動時,頁面上面被隐藏掉的高度,我們就稱為頁面被卷去的頭部。滾動條在滾動時會觸發onscroll事件。

3.3 仿淘寶側邊欄案例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .w {
            width: 1200px;
            margin: 10px auto;
        }

        .slider-bar {
            position: absolute;
            left: 50%;
            top: 300px;
            margin-left: 600px;
            width: 45px;
            height: 130px;
            background-color: orchid;
        }

        .header {
            height: 150px;
            background-color: hotpink;
            margin-bottom: 20px;
        }

        .banner {
            height: 300px;
            background-color: aqua;
            margin-bottom: 20px;
        }

        .main {
            height: 1000px;
            background-color: lawngreen;
        }

        span {
            display: none;
            position: absolute;
            bottom: 0;
        }
    </style>
</head>

<body>
    <div class="slider-bar">
        <span class="goBack"> <a href="#header">傳回頂部</a> </span>
    </div>
    <div id="header" class="header w">頭部區域</div>
    <div class="banner w">banner區域</div>
    <div class="main w">主體區域</div>
    <script>
        var sliderbar = document.querySelector('.slider-bar');
        var banner = document.querySelector('.banner');
        // bannerTop就是被卷去的部分高度
        var bannerTop = banner.offsetTop;
        // sliderTop是側邊欄離頂部的高度
        var sliderTop = sliderbar.offsetTop - bannerTop;
        var main = document.querySelector('.main');
        var goBack = document.querySelector('.goBack');
        var mainTop = main.offsetTop;
        document.addEventListener('scroll', function () {
            // window.pageYOffset頁面被卷去的頭部
            console.log(window.pageYOffset);
            // 當頁面被卷去的頭部大于等于banner的offsetTop時(到達banner區域),側邊欄改為固定定位
            if (window.pageYOffset >= bannerTop) {
                sliderbar.style.position = 'fixed';
                sliderbar.style.top = sliderTop + 'px';
            } else {
                sliderbar.style.position = 'absolute';
                sliderbar.style.top = 300 + 'px';
            }
            // 當頁面被卷曲的頭部大于等于主體部分的offsetTop時,側邊欄出現"傳回頂部"的子產品
            if (window.pageYOffset >= mainTop) {
                goBack.style.display = 'block';
            } else {
                goBack.style.display = 'none';
            }
        })

    </script>
</body>

</html>
           

4. 三大系列總結

  1. offset系列經常用于獲得元素位置offsetLeft、offsetTop。
  2. client經常用于擷取元素大小clientWidth、clientHeight。
  3. scroll經常用于擷取滾動距離 scrollTop 、scrollLeft。
  4. 注意頁面滾動的距離通過window.pageXoffset獲得。

5. mouseover和mouseenter的差別

二者都是滑鼠經過事件。

  1. 但是,mouseover滑鼠經過自身盒子會觸發,經過子盒子還會觸發。
  2. mouseenter隻會經過自身盒子觸發,之是以這樣,就是因為mouseenter不會冒泡。
  3. mouseenter搭配mouseleave使用,同樣不會冒泡。

6. 動畫函數封裝

6.1 動畫原理

核心原理:通過定時器setInterval()不斷移動盒子位置。

實作步驟:

  1. 獲得盒子目前位置
  2. 讓盒子在目前位置加上1個移動距離
  3. 利用定時器不斷重複這個操作
  4. 加一個結束定時器的條件
  5. 注意此元素需要添加定位,才能使用element.style.left
var div = document.querySelector('div');
var timer = setInterval(function () {
    if (div.offsetLeft >= 400) {
        clearInterval(timer);
    }
    div.style.left = div.offsetLeft + 1 + 'px';
}, 10)
           

6.2 簡單動畫函數封裝

第一個參數是對象,第二個參數是目标位置。

function animate(obj, target) {
    var timer = setInterval(function () {
        if (obj.offsetLeft >= target) {
            clearInterval(timer);
        }
        obj.style.left = obj.offsetLeft + 1 + 'px';
    }, 30)
}
           

改良版:提高了效率,給不同對象添加不同的定時器。

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)
}
           

6.3 緩動效果原理

緩動動畫就是讓元素運動速度有所變化,最常見的是讓速度慢慢停下來。

思路:

  1. 讓盒子每次移動的距離慢慢變小,速度就會慢慢落下來。
  2. 核心算法:(目标值-現在的位置)/ 10做為每次移動的距離步長。
  3. 停止條件:目前位置等于目标位置就停止定時器。
function animate(obj, target) {
    // 目的是讓元素隻能有一個定時器,防止定時器效果累加
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
        // 步長值寫在定時器裡面
        // 把步長值改為整數,盡量避免小數的出現
        // 前進:向上取整
        // 後退:向下取整
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 30)
}
           

6.4 回調函數

等動畫執行完畢後,再執行另一個函數的動作。

function animate(obj, target, callback) {
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
        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();
            }
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 30)
}
           

繼續閱讀