Web APIs 学习笔记(八)--- JavaScript简单动画(网页特效)

news/2024/7/19 14:20:47 标签: js

一、JavaScript动画

核心原理:

​ 通过定时器 setInterval() 不断地移动元素的位置,由于间隔时间很短,看起来像是连续动画一样的效果。

具体实现:
	1. 获得元素当前在页面中的位置。
	2. 修改元素的当前位置,使其加上要移动的距离。
	3. 利用定时器setInterval() ,设置一个短的间隔时间,不断重复 1 、2步。
	4. 设置限定条件,当到达指定位置时,结束定时器。
	5. 注意,这个移动的元素一定要有定位属性,否则无法通过 element.style.left等方法来修改位置。

二、缓动动画

​ 缓动动画就是让元素在运动过程中速度发生变化,最常用的是让速度逐渐慢下来。想要实现这种效果,需要让元素每次移动的距离逐渐减小,这样移动速度就会变慢。

​ 核心算法是: (目标值 - 现在的位置) / 10 做为每次移动的距离步长。但是要注意每次移动的距离要进行取整运算,如果移动距离是正值,即向正方向移动,则移动距离往大了取整,相反,如果移动距离是负值,即向反方向移动,则移动距离往小了取整。

三、水平移动动画函数

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

    }, 15);
}

​ 如果想要实现垂直移动动画,只需要将上面代码中的offsetLeft 改为 window.pageYOffset 即可。我们可以通过这个封装的动画函数实现网页轮播图、以及返回顶部按钮等网页常见特效。

四、节流阀

​ 节流阀的目的是为了控制动画事件的触发,使其无法连续触发,只有当上一个函数动画内容执行完毕后,才能再去执行下一个函数动画。通常应用于网页轮播图动画。

核心思路:

​ 添加一个控制变量,来实现锁住函数和再利用动画函数的回调函数,来解锁函数。

具体案例:
js">        if (flag) {
            flag = false;  // 本次动画开始 关闭节流阀  在此期间 不能开启下一次动画
            animate(ul, -num * focusWidth, function() {
                flag = true;  // 动画执行结束 打开节流阀 可以开启下一次动画
            });
            
        }

五、网页动画案例

1、网页返回顶部案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <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>
</head>
<body>
<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>

<script>
    var sliderbar = document.querySelector('.slider-bar');
    var banner = document.querySelector('.banner');
    var main = document.querySelector('.main');
    var goBack = document.querySelector('.goBack');
    // banner 到顶部的距离 用来做判断条件 修改侧边栏固定定位和绝对定位
    var bannerTop = banner.offsetTop;
    // 当侧边栏变为固定定位后的到顶部的距离
    var sliderbarTop = sliderbar.offsetTop - bannerTop;

    var mainTop = main.offsetTop;
    // 页面滚动事件 scroll
    document.addEventListener('scroll',function () {
        if(window.pageYOffset >= bannerTop){
            sliderbar.style.position = 'fixed';
            sliderbar.style.top = sliderbarTop + 'px';

        } else {
            sliderbar.style.position = 'absolute';
            sliderbar.style.top = '300px';
        }

        if(window.pageYOffset >= mainTop){
            goBack.style.display = 'block'

        } else {
            goBack.style.display = 'none'
        }
    })
    goBack.addEventListener('click',function () {
        // window.scroll(x,y);  x y 代表页面的坐标
        // 但这种方式是直接跳到页面顶部 过程不够优雅
        // window.scroll(0,0);
        // 这种方式足够优雅
        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();
                }
            }
            window.scroll(0, window.pageYOffset + step);

        }, 15);
    }
</script>
</body>
</html>

2、鼠标经过 滑出内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .sliderbar {
            position: absolute;
            right: 500px;
            top: 100px;
            width: 40px;
            height: 40px;
            text-align: center;
            line-height: 40px;
            cursor: pointer;
            color: #fff;
            background-color: green;

        }

        .con {
            position: absolute;
            right: 0;
            top: 0;
            width: 0px;
            height: 40px;
            background-color: purple;
            z-index: -1;
        }
    </style>

</head>
<body>
<div class="sliderbar">
    <span></span>
    <div class="con">问题反馈</div>
</div>

<script>
    var sliderbar = document.querySelector('.sliderbar');
    var con = document.querySelector('.con');

    function animate(obj, target, callback) {
        // console.log(callback);  callback = function() {}  调用的时候 callback()

        // 先清除以前的定时器,只保留当前的一个定时器执行
        clearInterval(obj.timer);
        if(obj.offsetWidth < target){
            obj.timer = setInterval(function() {
                // 步长值写到定时器的里面
                if (obj.offsetWidth == target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                    // 回调函数写到定时器结束里面
                    if (callback) {
                        // 调用函数
                        callback();
                    }
                }

                obj.style.width = obj.offsetWidth + 6 + 'px';

            }, 15);
        } else {
            obj.timer = setInterval(function() {
                // 步长值写到定时器的里面
                if (obj.offsetWidth == target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                    // 回调函数写到定时器结束里面
                    if (callback) {
                        // 调用函数
                        callback();
                    }
                }

                obj.style.width = obj.offsetWidth + -6 + 'px';

            }, 15);
        }
    }

    // mouseenter 鼠标经过 但是不会冒泡
    sliderbar.addEventListener('mouseenter',function () {
        animate(con,240)
    })
    // mouseleave 鼠标离开 但是不会冒泡
    sliderbar.addEventListener('mouseleave',function () {
        animate(con,0)
    })

</script>
</body>
</html>

http://www.niftyadmin.cn/n/803668.html

相关文章

lintcode-medium-Backpack II

Given n items with size Ai and value Vi, and a backpack with size m. Whats the maximum value can you put into the backpack? Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 9. 和上一题差不多&am…

Web APIs 学习笔记(九)--- 本地存储:sessionStorage 和 localStorage

一、本地存储的特性 1. 数据储存在用户本地的浏览器中。2. 存储、读取方便&#xff0c;甚至可以永久存储。3. 容量适中&#xff0c;sessionStorage 约 5MB大小、localStorage约5MB大小。4. 只能存储字符串&#xff0c;可以通过 JSON.stringify() 将其他类型数据转换成JSON字符串…

LeetCode 328. Odd Even Linked List

一开始理解错题意&#xff0c;以为是根据节点内的值是奇偶来分成不同group&#xff0c;实际上是节点所在位置的奇偶&#xff08;位置从1开始算起&#xff09;。 思路正确后仍然RE的代码&#xff1a; 1 class Solution {2 public:3 ListNode* oddEvenList(ListNode* head) {…

JavaScript进阶学习笔记(一)--- 类和对象

一、面向对象和面向过程 1、面向对象 ​ 面向对象就是把整个程序的事务分解成一个个对象&#xff0c;然后由对象之间进行分工和合作来实现功能。 2、面向过程 ​ 面向过程就是把整个程序的事务分解成一个个步骤&#xff0c;然后通过函数把这些步骤一步一步的实现&#xff0…

3.13课·········冒泡排序

抽奖活动&#xff1a; 输入n个手机号码&#xff0c;滚动号码&#xff0c;5秒钟后停止 输出中奖人号码 Console.Write("请输入手机号码个数&#xff1a;");int a int.Parse(Console.ReadLine());string [] shuzu new string [a];for (int i 0; i < a; i){Consol…

JavaScript进阶学习笔记(二)--- 构造函数和原型

一、构造函数和原型 1、实例成员和静态成员 ​ 实例成员&#xff1a;是指在构造函数内部通过this添加的成员&#xff0c;实例成员只能通过实例化的对象进行访问。 function Star(uname, age) {this.uname uname; // 这三条属性就是实例成员this.age age;this.sing functi…

51nod--1264 线段相交 (计算几何基础, 二维)

题目&#xff1a; 1264 线段相交 基准时间限制&#xff1a;1 秒 空间限制&#xff1a;131072 KB 分值: 0 难度&#xff1a;基础题 收藏 关注 给出平面上两条线段的两个端点&#xff0c;判断这两条线段是否相交&#xff08;有一个公共点或有部分重合认为相交&#xff09;。 如…