JavaScript - PC端网页特效

目录

1. 元素偏移量offset系列

1)offset系列属性

2)offset与style区别

2. 元素可视区client系列

1)client系列属性

2)立即执行函数

3. 元素滚动scroll系列

1)scroll系列属性

2)页面被卷去的头部兼容性解决方案

三大系列总结

mouseenter和mouseover的区别

mouseenter鼠标事件

4. 动画函数封装

1)动画实现原理

2)动画函数简单封装

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

4)缓动动画效果原理

5) 缓动动画多个目标值之间移动

6)动画函数添加回调函数

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

5. 节流阀


1. 元素偏移量offset系列

使用offset系列相关属性可以动态的得到该元素的位置(偏移量)、大小等。

  • 获得元素距离带有定位父元素的位置
  • 获得元素自身的大小(宽度高度)
  • 注意:返回的数值都不带单位

1)offset系列属性

    <style>
        * {
            padding: 0;
            margin: 0;
        }
        .father {
            /* position: relative; */
            width: 200px;
            height: 200px;
            background-color: pink;
            margin: 100px;
        }
        .son {
            width: 50px;
            height: 50px;
            margin: 0 50px;
            background-color: purple;
        }
        .w {
            width: 200px;
            height: 200px;
            margin: auto;
            padding: 10px;
            border: 2px solid red;
            background-color: skyblue;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son"></div>
    </div>
    <div class="w"></div>
    <script>
        var father = document.querySelector('.father');
        var son = document.querySelector('.son');
        console.log(father.offsetTop);
        console.log(father.offsetLeft);
        //父元素带有相对定位的为准,如果父元素没有定位则以body为准
        console.log(son.offsetTop);
        console.log(son.offsetLeft);

        var w = document.querySelector('.w');
        //得到元素的大小但是宽度、高度包含padding + border + width/height
        console.log(w.offsetWidth);
        console.log(w.offsetHeight);

        //返回带有定位的父亲,如果父元素没有定位则返回body
        console.log(son.offsetParent);
        //返回的是最近一级的父亲,不管父元素有无定位
        console.log(son.parentNode);
    </script>
</body>

结果为:

2)offset与style区别

    <style>
        .box {
            width: 200px;
            height: 200px;
            padding: 10px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <!-- style只能得到行内样式表中的样式值 -->
    <div class="box" style="width: 200px;"></div>
    <script>
        var box = document.querySelector('.box');
        //包含padding + border + width
        console.log(box.offsetWidth);
        //只包含width
        console.log(box.style.width);
        // 可以用style直接更改属性值
        box.style.width = '300px';
    </script>
</body>

 结果为:

2. 元素可视区client系列

client就是客户端,使用client系列的相关属性来获取元素可视区的相关信息,可以动态的得到该元素的边框大小、元素大小等。

1)client系列属性

2)立即执行函数

<body>
    <script>
        function fn() {
            console.log(1);
        }
        fn();
        //1.立即执行函数:不需要调用,能够立马执行的函数
        //2.写法:  (function() {})(); 或  (function(){} ());
        //3.可以传递参数
        //4.独立创建了一个作用域,里面所有的变量都是局部变量,所以不会有命名冲突的情况
        (function(a, b) {
            var num = 1;   //局部变量
            console.log(2);
            console.log(a + b);
        })(1, 2);

        (function(a, b) {
            console.log(3);
            console.log(a * b);
        }(1, 2));
    </script>
</body>

结果为:

3. 元素滚动scroll系列

scroll就是滚动的,使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等。

1)scroll系列属性

2)页面被卷去的头部兼容性解决方案

三大系列总结

  1. offset系列经常用于获得元素位置 offsetLeft offsetTop
  2. client系列经常用于获取元素大小 clientWidth clientHeight
  3. scroll系列经常用于获取滚动距离  scrollTop scrollLeft
  4. 页面滚动的距离通过 window.pageXoffset 获得

mouseenter和mouseover的区别

mouseenter鼠标事件

  • 当鼠标移动到元素上时就会触发mouseenter时间
  • mouseover鼠标经过自身盒子会触发,经过子盒子还会触发;mouseenter只会经过自身盒子触发
  • 是因为mouseenter不会冒泡
  • 跟mouseenter搭配,鼠标离开mouseleave,同样不会冒泡
    <style>
        .father {
            width: 300px;
            height: 300px;
            background-color: pink;
        }
        .son {
            width: 100px;
            height: 100px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son"></div>
    </div>
    <script>
        var father = document.querySelector('.father');
        //mouseover会冒泡
        //当鼠标经过father时输出一次 1 
        //当鼠标经过son时通过冒泡 会再返回father 因此再输出一次 1
        father.addEventListener('mouseover',function() {
            console.log(1);
        })
    </script>
</body>

结果为:

    <style>
        .father {
            width: 300px;
            height: 300px;
            background-color: pink;
        }
        .son {
            width: 100px;
            height: 100px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son"></div>
    </div>
    <script>
        var father = document.querySelector('.father');
        //mouseenter不会冒泡 
        //当鼠标经过father时输出一次 1 
        //当鼠标经过son时由于不会冒泡 因此不输出1
        father.addEventListener('mouseenter',function() {
            console.log(1);
        })
    </script>
</body>

结果为:

4. 动画函数封装

1)动画实现原理

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

实现步骤:

  1. 获得盒子当前位置
  2. 让盒子在当前位置加上1个移动距离
  3. 利用定时器不断重复这个操作
  4. 加一个结束定时器的条件
  5. 此元素还需要添加定位,才能使用element.style.left
    <style>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        // 1.获得盒子当前位置
        // 2.让盒子在当前位置加上1个移动距离
        // 3.利用定时器不断重复这个操作
        // 4.加一个结束定时器的条件
        // 5.此元素还需要添加定位,才能使用element.style.left
        var div = document.querySelector('div');
        var timer = setInterval(function() {
            if(div.offsetLeft >= 600) {
                //停止动画,本质:停止定时器
                clearInterval(timer);
            }
            div.style.left = div.offsetLeft + 5 + 'px';
        },30);
        
    </script>
</body>

结果为:

2)动画函数简单封装

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

    <style>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        span {
            display: block;
            position: absolute;
            left: 0;
            top: 150px;
            width: 200px;
            height: 200px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <div></div>
    <span></span>
    <script>
        //简单动画函数封装 动画对象obj 目标位置target
        function animation(obj, target) {
            var timer = setInterval(function() {
            if(obj.offsetLeft >= target) {
                //停止动画,本质:停止定时器
                clearInterval(timer);
            }
            obj.style.left = obj.offsetLeft + 1 + 'px';
        },30);
        }
        
        var div = document.querySelector('div');
        var span = document.querySelector('span');
        animation(div, 600);
        animation(span, 500);
    </script>
</body>

结果为:

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

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

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

    <style>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        span {
            display: block;
            position: absolute;
            left: 0;
            top: 150px;
            width: 200px;
            height: 200px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <button>点击按钮之后span才走</button>
    <div></div>
    <span>span</span>
    <script>
        //var obj = {}
        //obj.name = '';
        //简单动画函数封装 动画对象obj 目标位置target
        function animation(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 div = document.querySelector('div');
        var span = document.querySelector('span');
        animation(div, 600);
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            //当我们不断点击按钮,这个动画的移动速度会越来越快
            //解决方案:让元素只有一个定时器
            animation(span, 500);
        })
        
    </script>
</body>

结果为:

4)缓动动画效果原理

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

匀速动画:盒子当前的位置 + 固定的值

缓动动画:盒子当前的位置 + 变化的值(目标值 - 现在的位置)/ 10

思路:

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
  2. 核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
  3. 停止的条件是:让当前盒子位置等于目标位置就停止计时器 
  4. 注意步长需要取整

    <style>
        span {
            display: block;
            position: absolute;
            left: 0;
            top: 150px;
            width: 200px;
            height: 200px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <button>点击按钮之后span才走</button>
    <span>span</span>
    <script>
        // 1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
        // 2.核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
        // 3.停止的条件是:让当前盒子位置等于目标位置就停止计时器 
        function animation(obj, target) {
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                //核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
                var step = Math.ceil((target - obj.offsetLeft) / 10);
                if(obj.offsetLeft == target) {
                    //停止动画,本质:停止定时器
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            },15);
        }
        var btn = document.querySelector('button');
        var span = document.querySelector('span');
        btn.addEventListener('click', function() {
            animation(span, 600);
        })
    </script>
</body>

 结果为:

5) 缓动动画多个目标值之间移动

    <style>
        span {
            display: block;
            position: absolute;
            left: 0;
            top: 150px;
            width: 200px;
            height: 200px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <button class="btn500">点击按钮之后走到500px</button>
    <button class="btn800">点击按钮之后走到800px</button>
    <span>span</span>
    <script>
        // 1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
        // 2.核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
        // 3.停止的条件是:让当前盒子位置等于目标位置就停止计时器 
        function animation(obj, target) {
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                //核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
                var step = (target - obj.offsetLeft) / 10;
                //步长需要取整 8.1 -> 9  -8.1 -> -8 
                step = step > 0? Math.ceil(step) : Math.floor(step);
                if(obj.offsetLeft == target) {
                    //停止动画,本质:停止定时器
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            },15);
        }
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');
        var span = document.querySelector('span');
        btn500.addEventListener('click', function() {
            animation(span, 500);
        });
        btn800.addEventListener('click', function() {
            animation(span, 800);
        });
    </script>
</body>

结果为:

6)动画函数添加回调函数

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

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

    <style>
        span {
            display: block;
            position: absolute;
            left: 0;
            top: 150px;
            width: 200px;
            height: 200px;
            background-color: purple;
        }
    </style>
</head>
<body>
    <button class="btn500">点击按钮之后走到500px</button>
    <button class="btn800">点击按钮之后走到800px</button>
    <span>span</span>
    <script>
        function animation(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';
            },15);
        }
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');
        var span = document.querySelector('span');
        btn500.addEventListener('click', function() {
            animation(span, 500,function() {
                span.style.backgroundColor = 'skyblue';
            });
        });
        btn800.addEventListener('click', function() {
            animation(span, 800, function() {
                span.style.backgroundColor = 'red';
            });
        });
    </script>
</body>

结果为:

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

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

  1. 单独新建一个JS文件

5. 节流阀

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

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

核心实现思路:

  • 利用回调函数,添加一个变量来控制,锁住函数和解锁函数
  • 开始设置一个变量 var flag = true;
  • if(flag){ falg = false; do something }    //关闭水龙头
  • 利用回调函数,动画执行完毕,flag = true,打开水龙头

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值