跟着pink老师学前端之JavaScript特效

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

你可能感兴趣的:(前端基础学习,javascript)