Web APls

2022.4.3 学习笔记

目录

5.4 动画函数封装

5.4.1 动画实现原理

5.4.2 动画函数简单封装

5.4.3 动画函数给不同元素记录不同定时器

5.4.4 缓动效果原理

5.4.5 动画函数多个目标值之间移动

5.4.6 动画函数添加回调函数

5.4.7 动画函数封装到单独JS文件里面

5.5 常见网页特效案例

5.5.1 节流阀


5.4 动画函数封装

5.4.1 动画实现原理

核心原理:通过定时器 setInterval() 不断移动盒子位置。

实现步骤:

1. 获得盒子当前位置

2. 让盒子在当前位置加上1个移动距离(即步长为1)

3. 利用定时器不断重复这个操作

4. 加一个结束定时器的条件

5. 注意此元素需要添加定位,才能使用element.style.left

5.4.2 动画函数简单封装

注意函数需要传递2个参数动画对象移动到的距离

5.4.3 动画函数给不同元素记录不同定时器

如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。

核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性

5.4.4 缓动效果原理

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来

思路:

1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。

2. 核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长

3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器

4. 注意步长值需要取整

5.4.5 动画函数多个目标值之间移动

可以让动画函数向左移动——当我们点击按钮时候,判断步长是正值还是负值

1. 如果是正值,则步长往大取整

2. 如果是负值,则步长向小取整

5.4.6 动画函数添加回调函数

回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。

回调函数写的位置:结束定时器的位置

5.4.7 动画函数封装到单独JS文件里面

因为以后经常使用这个动画函数,可以单独封装到一个JS文件里面,使用的时候引用这个JS文件即可。

1. 单独新建一个JS文件。

2. HTML文件引入 JS 文件。

animate.js:
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();
            // }
            callback && callback();
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';

    }, 15);
}
<script src="animate.js"></script>

案例:引用animate.js,鼠标移入弹出侧边栏

        

1. css样式:

<style>

        .sliderbar {

            position: fixed;

            right: 0;

            bottom: 100px;

            width: 40px;

            height: 40px;

            text-align: center;

            line-height: 40px;

            cursor: pointer;

            color: #fff;

        }     

        .con {

            position: absolute;

            left: 0;

            top: 0;

            width: 200px;

            height: 40px;

            background-color: purple;

            z-index: -1;

        }

</style>

<script src="animate.js"></script>  //引入animate.js

2.html结构:

<div class="sliderbar">

        <span>←</span>

        <div class="con">问题反馈</div>

</div>

3.js代码:

<script>

        // 1. 获取元素

        var sliderbar = document.querySelector('.sliderbar');

        var con = document.querySelector('.con');

        // 当我们鼠标经过 sliderbar 就会让 con这个盒子滑动到左侧

        // 当我们鼠标离开 sliderbar 就会让 con这个盒子滑动到右侧

        sliderbar.addEventListener('mouseenter', function() {

            // animate(obj, target, callback);

            animate(con, -160, function() {

                // 当我们动画执行完毕,就把 ← 改为 →

                sliderbar.children[0].innerHTML = '→';

            });

        })

        sliderbar.addEventListener('mouseleave', function() {

            // animate(obj, target, callback);

            animate(con, 0, function() {

                sliderbar.children[0].innerHTML = '←';

            });:

        })

</script>

5.5 常见网页特效案例

案例1:PC端轮播图

轮播图也称为焦点图,是网页中比较常见的网页特效。

功能需求:

1. 鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。

2. 点击右侧按钮一次,图片往左播放一张,以此类推, 左侧按钮同理。

3. 图片播放的同时,下面小圆圈模块跟随一起变化。

4. 点击小圆圈,可以播放相应图片。

5. 鼠标不经过轮播图, 轮播图也会自动播放图片。

6. 鼠标经过,轮播图模块, 自动播放停止。

window.addEventListener('load', function() {

    // 1. 获取元素

    var arrow_l = document.querySelector('.arrow-l');

    var arrow_r = document.querySelector('.arrow-r');

    var focus = document.querySelector('.focus');

    var focusWidth = focus.offsetWidth;

    // 2. 鼠标经过focus 就显示隐藏左右按钮

    focus.addEventListener('mouseenter', function() {

        arrow_l.style.display = 'block';

        arrow_r.style.display = 'block';

        clearInterval(timer);

        timer = null; // 清除定时器变量

    });

    focus.addEventListener('mouseleave', function() {

        arrow_l.style.display = 'none';

        arrow_r.style.display = 'none';

        timer = setInterval(function() {

            //手动调用点击事件

            arrow_r.click();

        }, 2000);

    });

    // 3. 动态生成小圆圈  有几张图片,我就生成几个小圆圈

    var ul = focus.querySelector('ul');

    var ol = focus.querySelector('.circle');

    // console.log(ul.children.length);

    for (var i = 0; i < ul.children.length; i++) {

        // 创建一个小li

        var li = document.createElement('li');

        // 记录当前小圆圈的索引号 通过自定义属性来做

        li.setAttribute('index', i);

        // 把小li插入到ol 里面

        ol.appendChild(li);

        // 4. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件

        li.addEventListener('click', function() {

            // 干掉所有人 把所有的小li 清除 current 类名

            for (var i = 0; i < ol.children.length; i++) {

                ol.children[i].className = '';

            }

            // 留下我自己  当前的小li 设置current 类名

            this.className = 'current';

            // 5. 点击小圆圈,移动图片 当然移动的是 ul

            // ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值

            // 当我们点击了某个小li 就拿到当前小li 的索引号

            var index = this.getAttribute('index');

            // 当我们点击了某个小li 就要把这个li 的索引号给 num  

            num = index;

            // 当我们点击了某个小li 就要把这个li 的索引号给 circle  

            circle = index;

            // num = circle = index;

            console.log(focusWidth);

            console.log(index);

            animate(ul, -index * focusWidth);

        })

    }

    // 把ol里面的第一个小li设置类名为 current

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

    // 6. 克隆第一张图片(li)放到ul 最后面

    var first = ul.children[0].cloneNode(true);

    ul.appendChild(first);

    // 7. 点击右侧按钮, 图片滚动一张

    var num = 0;

    // circle 控制小圆圈的播放

    var circle = 0;

    // flag 节流阀

    var flag = true;

    arrow_r.addEventListener('click', function() {

        if (flag) {

            flag = false; // 关闭节流阀

            // 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0

            if (num == ul.children.length - 1) {

                ul.style.left = 0;

                num = 0;

            }

            num++;  

            animate(ul, -num * focusWidth, function() {

                flag = true; // 打开节流阀

            });

            // 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放

            circle++;

            // 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原

            if (circle == ol.children.length) {

                circle = 0;

            }

            // 调用函数

            circleChange();

        }

    });

    // 9. 左侧按钮做法

    arrow_l.addEventListener('click', function() {

        if (flag) {

            flag = false;

            if (num == 0) {

                num = ul.children.length - 1;

                ul.style.left = -num * focusWidth + 'px';

            }

            num--;

            animate(ul, -num * focusWidth, function() {

                flag = true;

            });

            // 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放

            circle--;

            // 如果circle < 0  说明第一张图片,则小圆圈要改为第4个小圆圈(3)

            // if (circle < 0) {

            //     circle = ol.children.length - 1;

            // }

            circle = circle < 0 ? ol.children.length - 1 : circle;

            // 调用函数

            circleChange();

        }

    });

    function circleChange() {

        // 先清除其余小圆圈的current类名

        for (var i = 0; i < ol.children.length; i++) {

            ol.children[i].className = '';

        }

        // 留下当前的小圆圈的current类名

        ol.children[circle].className = 'current';

    }

    // 10. 自动播放轮播图

    var timer = setInterval(function() {

        //手动调用点击事件

        arrow_r.click();

    }, 2000);

})

求求仔细看看源码!!

5.5.1 节流阀

防止轮播图按钮连续点击造成播放过快。

节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。

核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

开始设置一个变量 var flag = true;

If(flag) {flag = false; do something} 关闭水龙头

利用回调函数 动画执行完毕, flag = true 打开水龙头

补充:

滚动窗口至文档中的特定位置。

window.scroll(x, y);

注意,里面的x和y 不跟单位,直接写数字

案例2:仿淘宝返回顶部

1. css样式:

<style>

        .slider-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;

        }

    </style>

2. html结构:

    <div class="slider-bar">

        <span class="goBack">返回顶部</span>

    </div>

    <div class="header w">头部区域</div>

    <div class="banner w">banner区域</div>

    <div class="main w">主体部分</div>

3. js代码:

<script>

        //1. 获取元素

        var sliderbar = document.querySelector('.slider-bar');

        var banner = document.querySelector('.banner');

        // banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面

        var bannerTop = banner.offsetTop

            // 当我们侧边栏固定定位之后应该变化的数值

        var sliderbarTop = sliderbar.offsetTop - bannerTop;

        // 获取main 主体元素

        var main = document.querySelector('.main');

        var goBack = document.querySelector('.goBack');

        var mainTop = main.offsetTop;

        // 2. 页面滚动事件 scroll

        document.addEventListener('scroll', function() {

                // console.log(11);

                // window.pageYOffset 页面被卷去的头部

                // console.log(window.pageYOffset);

                // 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位

                if (window.pageYOffset >= bannerTop) {

                    sliderbar.style.position = 'fixed';

                    sliderbar.style.top = sliderbarTop + 'px';

                } else {

                    sliderbar.style.position = 'absolute';

                    sliderbar.style.top = '300px';

                }

                // 4. 当我们页面滚动到main盒子,就显示 goback模块

                if (window.pageYOffset >= mainTop) {

                    goBack.style.display = 'block';

                } else {

                    goBack.style.display = 'none';

                }

            })

            // 3. 当我们点击了返回顶部模块,就让窗口滚动的页面的最上方

        goBack.addEventListener('click', function() {

            // 里面的x和y 不跟单位的 直接写数字即可

            // window.scroll(0, 0);

            // 因为是窗口滚动 所以对象是window

            animate(window, 0);  //页面垂直滚动回到最上方

        });

        // 页面垂直滚动的动画函数

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

                    // 回调函数写到定时器结束里面

                    // if (callback) {

                    //     // 调用函数

                    //     callback();

                    // }

                    callback && callback();

                }

                // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10

                // obj.style.left = window.pageYOffset + step + 'px';

                window.scroll(0, window.pageYOffset + step);

            }, 15);

        }

</script>

案例3:筋头云案例

鼠标经过某个小li, 筋斗云跟这到当前小li位置

鼠标离开这个小li, 筋斗云复原为原来的位置

鼠标点击了某个小li, 筋斗云就会留在点击这个小li 的位置

js代码:

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

    <script>

        window.addEventListener('load', function() {

            // 1. 获取元素

            var cloud = document.querySelector('.cloud');

            var c_nav = document.querySelector('.c-nav');

            var lis = c_nav.querySelectorAll('li');

            // 2. 给所有的小li绑定事件

            // 这个current 做为筋斗云的起始位置

            var current = 0;

            for (var i = 0; i < lis.length; i++) {

                // (1) 鼠标经过把当前小li 的位置做为目标值

                lis[i].addEventListener('mouseenter', function() {

                    animate(cloud, this.offsetLeft);

                });

                // (2) 鼠标离开就回到起始的位置

                lis[i].addEventListener('mouseleave', function() {

                    animate(cloud, current);

                });

                // (3) 当我们鼠标点击,就把当前位置做为目标值

                lis[i].addEventListener('click', function() {

                    current = this.offsetLeft;

                });

            }

        })

</script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值