基本網頁特效(二)

動畫

動畫原理

動畫原理.png
        // 動畫原理
        // 1. 獲得盒子當前位置  
        // 2. 讓盒子在當前位置加上1個移動距離
        // 3. 利用定時器不斷重復這個操作
        // 4. 加一個結束定時器的條件
        // 5. 注意此元素需要添加定位, 才能使用element.style.left
        var div = document.querySelector('div');
        var btn = document.querySelector('button');

        btn.addEventListener("click", function () {
            var timer = setInterval(function () {
                if (div.offsetLeft > 400) {
                    clearInterval(timer);
                }
                div.style.left = div.offsetLeft + 1 + 'px';
            }, 10);
        })

動畫函數封裝

        // 給對象添加屬性的方法
        // var obj = {};
        // obj.name = 'andy';

        // 動畫函數封裝
        // 用添加對象屬性的方式,給不同對象添加不同屬性的定時器,節(jié)省內存空間
        function animate(obj, target, step){
            // 另外,在調用函數之前先清楚掉原來的定時器,以免多次點擊按鈕之后定時器累加造成動畫加速
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                if (obj.offsetLeft > target) {
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 10);
        }


        var box1 = document.querySelector('.box1');
        var box2 = document.querySelector('.box2');
        var box3 = document.querySelector('.box3');
        var btn = document.querySelector('button');

        // 調用函數

        btn.addEventListener("click", function () {
            animate(box1, 400, 1);
            animate(box2, 500, 3);
            animate(box3, 600, 5);
        })

緩動動畫

緩動動畫原理

緩動動畫原理.png
        // 緩動動畫原理:
        // 1. 讓盒子每次移動的距離慢慢變小, 速度就會慢慢落下來。
        // 2. 核心算法:(目標值 - 現在的位置) / 10 做為每次移動的距離 步長
        // 3. 停止的條件是: 讓當前盒子位置等于目標位置就停止定時器
        function animate(obj, target, speed){
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 緩動動畫需要寫在定時器里面
                var step = (target - obj.offsetLeft) / speed;
                if (obj.offsetLeft > target) {
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 10);
        }

        var box1 = document.querySelector('.box1');
        var box2 = document.querySelector('.box2');
        var box3 = document.querySelector('.box3');
        var btn = document.querySelector('button');

        // 調用函數

        btn.addEventListener("click", function () {
            animate(box1, 400, 10);
            animate(box2, 500, 20);
            animate(box3, 600, 40);
        })

緩動動畫在多個目標點之間的移動

        // 緩動動畫在多個目標點之間的移動:
        function animate(obj, target, speed){
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 緩動動畫需要寫在定時器里面
                // JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
                var step = (target - obj.offsetLeft) / speed;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (obj.offsetLeft == target) {
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 20);
        }

        var box1 = document.querySelector('.box1');
        var btn = document.querySelector('button');
        var flag = true;

        // 調用函數

        btn.addEventListener("click", function () {
            if(flag){
                animate(box1, 610, 10);
                flag = false;
            }else{
                animate(box1, 10, 10);
                flag = true;
            }
        })

點擊animate按鈕,圖片會在指定位置來回移動

添加回調函數

回調函數作為參數傳進動畫函數當中,會在動畫效果結束后執(zhí)行:

        // 緩動動畫添加回調函數:
        function animate(obj, target, callback){
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 緩動動畫需要寫在定時器里面
                // JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
                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';
            }, 20);
        }

        var box1 = document.querySelector('.box1');
        var btn = document.querySelector('button');
        var flag = true;

        // 調用函數

        btn.addEventListener("click", function () {
            if(flag){
                animate(box1, 610, function(){
                    box1.style.backgroundImage = "url('pic/Megumin.jpg')";
                });
                flag = false;
            }else{
                animate(box1, 10, function(){
                    box1.style.backgroundImage = "url('pic/Kana.jpg')";
                });
                flag = true;
            }
        })

上面的例子,緩動動畫效果結束后會更改盒子內的圖片

JS封裝

// 緩動動畫添加回調函數:
function animate(obj, target, callback) {
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
        // 緩動動畫需要寫在定時器里面
        // JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
        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();
            } */
            // 使用邏輯中斷來代替判斷語句
            callback&&callback();
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 20);
}

在使用的時候,別忘了在頭文件里引用該js文件:

    <script src='animate.js'></script>

輪播圖效果

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link  rel="stylesheet">

    <style>
        /*清除元素默認的內外邊距  */
        * {
            margin: 0;
            padding: 0;
        }



        a {
            text-decoration: none;
        }

        .main {
            width: 610px;
            margin: 0 auto;
            margin-top: 60px;
        }

        .focus {
            position: relative;
            width: 600px;
            height: 300px;
            border: red 2px solid;

            overflow: hidden;
        }

        img {
            width: 600px;
        }

        li {
            list-style: none;
        }

        ul {
            position: absolute;
            top: 0;
            left: 0;
            width: 600%;
        }

        ul li {
            float: left;
        }

        .arrow-l,
        .arrow-r {
            display: none;
            position: absolute;
            top: 50%;
            margin-top: -20px;
            width: 24px;
            height: 40px;
            background: rgba(0, 0, 0, .3);
            text-align: center;
            line-height: 40px;
            color: #fff;
            font-family: 'icomoon';
            font-size: 18px;
            z-index: 2;
        }

        .arrow-r {
            right: 0;
        }

        .circle {
            position: absolute;
            bottom: 10px;
            left: 50px;
        }

        .circle li {
            float: left;
            width: 8px;
            height: 8px;
            /*background-color: #fff;*/
            border: 2px solid rgba(255, 255, 255, 0.5);
            margin: 0 3px;
            border-radius: 50%;
            /*鼠標經過顯示小手*/
            cursor: pointer;
        }

        .current {
            background-color: #fff;
        }
    </style>
    <script src='animate.js'></script>

</head>

<body>
    <div class="main">
        <div class="focus">
            <!-- 左側按鈕 -->
            <a href="javascript:;" class="arrow-l">←</a>
            <!-- 右側按鈕 -->
            <a href="javascript:;" class="arrow-r">→</a>
            <!-- 核心的滾動區(qū)域 -->
            <ul>
                <li>
                    <a href="#"><img
                            src="https://patchwiki.biligame.com/images/blhx/8/87/1axukjehcwyowqeh8f4xobkbvjyija7.jpg"
                            alt=""></a>
                </li>
                <li>
                    <a href="#"><img
                            src="https://patchwiki.biligame.com/images/blhx/5/5d/aqs86t38ezjjwl1qjlgz9lylsdcojle.jpg"
                            alt=""></a>
                </li>
                <li>
                    <a href="#"><img
                            src="https://patchwiki.biligame.com/images/blhx/6/66/ntqh7jf5f4ce20qopr5192qxgadbw2x.jpg"
                            alt=""></a>
                </li>
                <li>
                    <a href="#"><img
                            src="https://patchwiki.biligame.com/images/blhx/f/f4/izxkrqb9iey4ooqws4dimq8r0yttx7b.jpg"
                            alt=""></a>
                </li>
                <li>
                    <a href="#"><img
                            src="https://patchwiki.biligame.com/images/blhx/3/33/0kz6xpi03oisfing6l3w4547hag1kpr.jpg"
                            alt=""></a>
                </li>
            </ul>
            <!-- 小圓圈 -->
            <ol class="circle">
            </ol>
        </div>
    </div>

    <script>
        // 網頁輪播圖
        // 需求:
        // 1. 鼠標經過輪播圖模塊,左右按鈕顯示,離開即隱藏兩個按鈕
        // 2. 點擊右側按鈕一次,圖片往左播放一次,反之則向右播放一張
        // 3. 圖片播放時,下面的小圓點跟隨一起變化
        // 4. 點擊小圓點,可以播放對應的圖片
        // 5. 鼠標不經過輪播圖模塊,會自動播放圖片
        // 6. 鼠標經過時,自動播放停止

        // 獲取元素
        var box = document.querySelector('.focus');
        var arrow_l = document.querySelector('.arrow-l');
        var arrow_r = document.querySelector('.arrow-r');

        var pic = document.querySelector('img');
        var ul = document.querySelector('ul');
        var ol = document.querySelector('.circle');

        var num = 0;
        var dot = 0;
        var flag = true;   // 節(jié)流閥

        // 顯示/隱藏箭頭
        box.addEventListener('mouseenter', function () {
            arrow_l.style.display = 'block'
            arrow_r.style.display = 'block'
            clearInterval(timer);
            timer = null;    // 清楚定時器變量
        });

        box.addEventListener('mouseleave', function () {
            arrow_l.style.display = 'none'
            arrow_r.style.display = 'none'
            timer = setInterval(function () {
                arrow_r.click();
            }, 2000);
        });

        // 動態(tài)生成小圓圈
        // console.log(pic.length);
        for (var i = 0; i < ul.children.length; i++) {
            var li = document.createElement('li');
            li.setAttribute('index', i);
            ol.append(li);

            // 小圓圈的排他算法
            li.addEventListener('click', function () {
                for (var j = 0; j < ol.children.length; j++) {
                    ol.children[j].className = '';
                }
                this.className = 'current';

                // 對應圖片跳轉
                var index = this.getAttribute('index');
                // console.log(index);
                animate(ul, -index * pic.clientWidth);

                num = index;
                dot = index;
            })

        }
        ol.children[0].className = 'current';

        /*     ol.addEventListener('click',function(e){
                   for(var i = 0; i < ul.children.length; i++){
                       ol.children[i].className = '';
                   }
                   e.target.className = 'current';
                   console.log(e.target);
               }) */

        // 這里雖然想到用事件委托,雖然點擊圓點也能實現相應效果
        // 但是如果不小心點到圓點之間的間隔,e.target會判定是ol,所有小圓點都會消失

        // 將第一張圖片復制到最后面,利用視覺差來做出循環(huán)效果
        // 因為克隆是在小圓點生成之后,所以不會影響小圓點的總數量
        var firstPic = ul.children[0].cloneNode(true);    // 完全克隆
        ul.appendChild(firstPic);

        // 點擊箭頭跳轉圖片
        arrow_r.addEventListener('click', function () {
            if (flag) {
                flag = false;   // 關閉節(jié)流閥
                // 圖片無縫滾動
                if (num == ul.children.length - 1) {
                    ul.style.left = 0;
                    num = 0;
                }
                num++;
                animate(ul, -num * pic.clientWidth, function () {
                    flag = true;    // 打開節(jié)流閥
                });

                dot++;
                if (dot == ol.children.length) {
                    dot = 0;
                }
                circleChange();
            }
        });


        arrow_l.addEventListener('click', function () {
            if (flag) {
                flag = false;
                if (num == 0) {
                    num = ul.children.length - 1;
                    ul.style.left = -num * pic.clientWidth + 'px';
                }

                num--;
                animate(ul, -num * pic.clientWidth, function(){
                    flag = true;
                });

                dot--;
                dot = dot < 0 ? ol.children.length - 1 : dot;
                circleChange();
            }
        });

        // 更改圓點位置
        function circleChange() {
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            ol.children[dot].className = 'current';
        };


        // 自動輪播功能
        var timer = setInterval(function () {
            // 手動調用事件
            arrow_r.click();
        }, 2000);
    </script>
</body>
</html>

說明一下什么是節(jié)流閥:


節(jié)流閥.png

返回頂部動畫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link  rel="stylesheet">
    <style>
        .slide-bar {
            position: absolute;
            left: 50%;
            top: 300px;
            margin-left: 600px;
            width: 45px;
            height: 130px;
            background-color: pink;
        }

        .w {
            width: 1200px;
            margin: 10px auto;
        }

        .header {
            height: 150px;
            background-color: purple;
        }

        .banner {
            height: 250px;
            background-color: skyblue;
        }

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

        span {
            display: none;
            position: absolute;
            bottom: 0;
        }

        .goBack {
            display: none;
        }
    </style>
</head>

<body>
    <div class="slide-bar">
        <a class="goBack">Top</a>
    </div>
    <div class="header w">Header</div>
    <div class="banner w">Bannner</div>
    <div class="main w">Main</div>

    <script>
        // 仿淘寶側邊固定欄
        var slide_bar = document.querySelector('.slide-bar');
        var banner = document.querySelector('.banner');

        var bannerTop = banner.offsetTop;
        var slideBarTop = slide_bar.offsetTop - bannerTop;

        var main = document.querySelector('.main');
        var btn = document.querySelector('.goBack');
        var mainTop = main.offsetTop;

        // 頁面滾動事件
        document.addEventListener('scroll', function () {
            // window.pageYOffset 頁面被卷去的頭部
            console.log(window.pageYOffset);
            // 當頁面卷到banner欄時,固定slideBar在頁面的顯示位置,
            if (window.pageYOffset >= bannerTop) {
                slide_bar.style.position = 'fixed'
                slide_bar.style.top = slideBarTop + 'px';
            } else {
                slide_bar.style.position = 'absolute';
                slide_bar.style.top = '300px';
            }

            // 當頁面卷到main盒子時,顯示top模塊
            if (window.pageYOffset >= mainTop) {
                btn.style.display = 'block';
            } else {
                btn.style.display = 'none';
            }
        });

        slide_bar.addEventListener('click',function(){
            animate(window, 0);
        })


        // 緩動動畫添加回調函數:
        function animate(obj, target, callback) {
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 緩動動畫需要寫在定時器里面
                // JavaScript中需要避免出現小數,否則會導致移動距離出現偏差
                var step = (target - window.pageYOffset) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (window.pageYOffset == target) {
                    clearInterval(obj.timer);
                    // 回調函數寫在清除定時器的判斷條件里
                    /* if (callback) {
                        callback();
                    } */
                    // 使用邏輯中斷來代替判斷語句
                    callback && callback();
                }
                // obj.style.left = obj.offsetLeft + step + 'px';
                window.scroll(0, window.pageYOffset + step);
            }, 20);
        }
    </script>
</body>
</html>

其實只需要把動畫的目標地點從水平更改為垂直就行了

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容