JavaScript—— PC 端网页特效


  • 一、PC 端网页特效

1. 元素偏移量 offest 系列

1.1 offset 概述

offset 翻译过来就是偏移量,我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。

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

offset 系列常用属性:
请添加图片描述

1.2 offset 与 style 区别

请添加图片描述

案例:获取鼠标在盒子内的坐标

请添加图片描述

<!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>Document</title>
    <style>
        .box {
            width: 300px;
            height: 300px;
            background-color: pink;
            margin: 200px;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        var box = document.querySelector('.box');
        box.addEventListener('mousemove', function (e) {
            // console.log(e.pageX);
            // console.log(e.pageY);
            // console.log(box.offsetLeft);
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            this.innerHTML = 'x坐标是' + x + ' 坐标是' + y;
        })
    </script>
</body>

</html>

请添加图片描述

案例:模拟框拖拽

请添加图片描述
请添加图片描述

html

<body>
    <div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
    <div id="login" class="login">
        <div id="title" class="login-title">登录会员
            <span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
        </div>
        <div class="login-input-content">
            <div class="login-input">
                <!-- <label> 元素(标签)表示用户界面中某个元素的说明。 -->
                <label>用户名:</label>
                <input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
            </div>
            <div class="login-input">
                <!-- <label> 元素(标签)表示用户界面中某个元素的说明。 -->
                <label>登录密码:</label>
                <input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
            </div>
            <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a>
            </div>
        </div>
    </div>
    <!-- 遮盖层 -->
    <div id="bg" class="login-bg"></div>
</body>

css

* {
    padding: 0;
    margin: 0;
}

a {
    text-decoration: none;
    color: #000000;
}

.login-header {
    width: 100%;
    text-align: center;
    height: 30px;
    font-size: 24px;
    line-height: 30px;
    margin-top: 10px;
}

.login {
    display: none;
    /* 固定定位 */
    position: fixed;
    width: 512px;
    height: 280px;
    border: #ebebeb solid 1px;
    left: 50%;
    top: 50%;
    background: #fff;
    box-shadow: 0px 0px 20px #ddd;
    z-index: 9999;
    transform: translate(-50%, -50%);
}

.login-title {
    position: relative;
    width: 100%;
    margin-top: 10px;
    text-align: center;
    line-height: 40px;
    height: 40px;
    font-size: 18px;
    /* 设置鼠标样式 */
    cursor: move;
}

.login-title span {
    position: absolute;
    font-size: 12px;
    right: -20px;
    top: -30px;
    background: #fff;
    border: #ebebeb solid 1px;
    width: 40px;
    height: 40px;
    border-radius: 20px;
}

.login-input-content {
    margin-top: 20px;
}

.login-input input.list-input {
    float: left;
    line-height: 35px;
    height: 35px;
    width: 350px;
    border: #ebebeb solid 1px;
    text-indent: 5px;
}

.login-input {
    /* 解决外边距塌陷 */
    overflow: hidden;
    margin-bottom: 20px;
}

.login-input label {
    float: left;
    width: 90px;
    padding-right: 10px;
    text-align: right;
    line-height: 35px;
    height: 35px;
    font-size: 14px;
}

.login-button {
    width: 50%;
    margin: 30px auto 0px auto;
    line-height: 40px;
    font-size: 14px;
    border: #ebebeb 1px solid;
    text-align: center;
}

.login-button a {
    display: block;
}

/* 遮盖层 */
.login-bg {
    display: none;
    position: fixed;
    top: 0px;
    left: 0px;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, .3);
}

js

// 1. 获取元素
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector("#closeBtn");
// 2. 点击弹出层这个链接 link 让 mask 和 login 显示出来
link.addEventListener('click', function () {
    mask.style.display = 'block';
    login.style.display = 'block';
})
// 3. 点击 closeBtn 就隐藏 mask 和 login
closeBtn.addEventListener('click', function () {
    mask.style.display = 'none';
    login.style.display = 'none';
})
// 4. 开始拖拽
// (1) 当我们鼠标按下, 就获得鼠标在盒子内的坐标
title.addEventListener('mousedown', function (e) {
    var x = e.pageX - login.offsetLeft;
    var y = e.pageY - login.offsetTop;
    // (2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
    document.addEventListener('mousemove', move)
    function move(e) {
        login.style.left = e.pageX - x + 'px';
        login.style.top = e.pageY - y + 'px';
    }
    // (3) 鼠标弹起,就让鼠标移动事件移除
    document.addEventListener('mouseup', function () {
        document.removeEventListener('mousemove', move);
    })
})

请添加图片描述

案例:仿京东放大镜

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

html

<body>
    <div class="product_intro">
        <div class="preview_wrap">
            <div class="preview_img">
                <img src="images/s3.png" alt="">
                <div class="mask"></div>
                <div class="big">
                    <img src="images/big.jpg" alt="" class="bigImg">
                </div>
            </div>
        </div>
        <div class="fr"></div>
    </div>
</body>

css

.preview_wrap {
    float: left;
    width: 400px;
    height: 590px;
}

.preview_img {
    position: relative;
    height: 398px;
    border: 1px solid #ccc;
}

.mask {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 300px;
    height: 300px;
    background: #FEDE4F;
    /* 半透明效果 */
    opacity: .5;
    border: 1px solid #ccc;
    cursor: move;
}

.big {
    display: none;
    position: absolute;
    left: 410px;
    top: 0;
    width: 500px;
    height: 500px;
    background-color: pink;
    z-index: 999;
    border: 1px solid #ccc;
    /* 图片溢出隐藏 */
    overflow: hidden;
}

.big img {
    position: absolute;
    top: 0;
    left: 0;
}

.fr {
    float: right;
    width: 700px;
    height: 500px;
    background-color: skyblue;
}

js

// 当页面全部加载完在执行里面的js代码
window.addEventListener('load', function () {
    var preview_img = document.querySelector('.preview_img');
    var mask = document.querySelector('.mask');
    var big = document.querySelector('.big');
    // 1. 当我们鼠标经过 preview_img 就显示和隐藏 mask 遮挡层 和 big 大盒子
    preview_img.addEventListener('mouseover', function () {
        mask.style.display = 'block';
        big.style.display = 'block';
    })
    preview_img.addEventListener('mouseout', function () {
        mask.style.display = 'none';
        big.style.display = 'none';
    })
    // 2. 鼠标移动的时候,让黄色的盒子跟着鼠标来走
    preview_img.addEventListener('mousemove', function (e) {
        // (1). 先计算出鼠标在盒子内的坐标
        var x = e.pageX - this.offsetLeft;
        var y = e.pageY - this.offsetTop;
        // console.log(x, y);
        // (2) 为了实现黄色盒子的中央跟随鼠标移动 所以就减去盒子高度 300的一半 是 150 就是我们mask 的最终 left 和top值了
        // (3) 我们mask 移动的距离
        var maskX = x - mask.offsetWidth / 2;
        var maskY = y - mask.offsetHeight / 2;
        // (4) 如果x 坐标小于了0 就让他停在0 的位置
        // 遮挡层的最大移动距离
        var maskMax = preview_img.offsetWidth - mask.offsetWidth;
        if (maskX <= 0) {
            maskX = 0;
        } else if (maskX >= maskMax) {
            maskX = maskMax;
        }
        if (maskY <= 0) {
            maskY = 0;
        } else if (maskY >= maskMax) {
            maskY = maskMax;
        }
        mask.style.left = maskX + 'px';
        mask.style.top = maskY + 'px';
        // 3. 大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离
        var bigImg = document.querySelector('.bigImg');
        // 大图片最大移动距离
        var bigMax = bigImg.offsetWidth - big.offsetWidth;
        // 大图片的移动距离 X Y
        var bigX = maskX * bigMax / maskMax;
        var bigY = maskY * bigMax / maskMax;
        // 大图与鼠标移动的方向相反
        bigImg.style.left = -bigX + 'px';
        bigImg.style.top = -bigY + 'px';
    })
})

请添加图片描述

2. 元素可视区 client 系列

client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
请添加图片描述
请添加图片描述
Tips:
client 宽度 和我们 offsetWidth 最大的区别就是 不包含边框

案例:淘宝flexible.js 源码分析

立即执行函数: 不需要调用,立马能够自己执行的函数
(function() { })() 或者 (function(){ }())
【第二个小括号可以看做是调用函数】
主要作用:创建一个独立的作用域。避免了命名冲突问题
请添加图片描述

(function flexible(window, document) {
    // 获取的html 的根元素
    var docEl = document.documentElement
        // dpr 物理像素比
    var dpr = window.devicePixelRatio || 1

    // adjust body font size  设置我们body 的字体大小
    function setBodyFontSize() {
        // 如果页面中有body 这个元素 就设置body的字体大小
        if (document.body) {
            document.body.style.fontSize = (12 * dpr) + 'px'
        } else {
            // 如果页面中没有body 这个元素,则等着 我们页面主要的DOM元素加载完毕再去设置body
            // 的字体大小
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10    设置我们html 元素的文字大小
    function setRemUnit() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    }

    setRemUnit()

    // reset rem unit on page resize  当我们页面尺寸大小发生变化的时候,要重新设置下rem 的大小
    window.addEventListener('resize', setRemUnit)
        // pageshow 是我们重新加载页面触发的事件
    window.addEventListener('pageshow', function(e) {
        // e.persisted 返回的是true 就是说如果这个页面是从缓存取过来的页面,也需要从新计算一下rem 的大小
        if (e.persisted) {
            setRemUnit()
        }
    })

    // detect 0.5px supports  有些移动端的浏览器不支持0.5像素的写法
    if (dpr >= 2) {
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testElement.offsetHeight === 1) {
            docEl.classList.add('hairlines')
        }
        docEl.removeChild(fakeBody)
    }
}(window, document))

3. 元素滚动 scroll 系列

3.1 元素 scroll 系列属性

scroll 翻译过来就是滚动的意思,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
请添加图片描述
请添加图片描述

3.2 页面被卷去的头部

如果浏览器的高(或宽)度不足以品示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。

3.3 案例:仿淘宝固定右侧侧边栏

1.原先侧边栏是绝对定位
2.当页面滚动到一定位置,侧边栏改为固定定位
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>Document</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>
        // 1. 获取元素
        var sliderbar = document.querySelector('.slider-bar');
        var banner = document.querySelector('.banner');
        // banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
        var bannerTop = banner.offsetTop;
        // 当我们侧边栏固定定位之后应该变化的数值
        var sliderbarTop = parseInt(sliderbar.offsetTop - bannerTop);
        // 获取 main 主体元素
        var main = document.querySelector('.main');
        var goBack = document.querySelector('.goBack');
        var mainTop = main.offsetTop;
        //2. 页面滚动事件 scroll
        document.addEventListener('scroll', function () {
            // 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';
            }
        })
    </script>
</body>

</html>

请添加图片描述

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

请添加图片描述

三大系列总结

请添加图片描述
他们主要用法:

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

mouseenter 和 mouseover 的区别

mouseenter 鼠标事件

  • 当鼠标移动到元素上时就会触发 mouseenter 事件
  • 类似 mouseover,它们两者之间的差别是
  • mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter 只会经过自身盒子触发
  • 之所以这样,就是因为mouseenter 不会冒泡
  • 跟mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡

4. 动画函数封装

4.1 动画实现原理

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

  1. 获得盒子当前位置
  2. 让盒子在当前位置加上1个移动距离
  3. 利用定时器不断重复这个操作
  4. 加一个结束定时器的条件
  5. 汪意此元素需要添加定位,才能使用elernent.style.left
<!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>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div></div>
    <script>
        var div = document.querySelector('div');
        var timer = setInterval(function () {
            if (div.offsetLeft >= 400) {
                // 停止动画 本质是停止定时器
                clearInterval(timer);
            }
            div.style.left = div.offsetLeft + 1 + 'px';
        }, 50);
    </script>
</body>

</html>

请添加图片描述

4.2 动画函数简单封装

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

<!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>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }

        span {
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>

<body>
    <div></div>
    <span>夏雨荷</span>
    <script>
        // 简单动画函数封装obj目标对象 target 目标位置
        function animate(obj, target) {
            var timer = setInterval(function () {
                if (div.offsetLeft >= target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(timer);
                }
                obj.style.left = obj.offsetLeft + 1 + 'px';
            }, 50);
        }
        var div = document.querySelector('div');
        var span = document.querySelector('span');
        // 调用函数
        animate(div, 300);
        animate(span, 200);

    </script>
</body>

</html>

请添加图片描述

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

如果多个元素都使用这个动画函数,每次都要 var 声明定时器,容易浪费内存资源而且定时器的名字都一样,容易引起歧义。 我们可以给不同的元素使用不同的定时器(自三专门用自己的定时器)。
核心原理: 利用Js是一门动态语言,可以很方便的给当前对象添加属性。

<!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>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }

        span {
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>

<body>
    <button>点击夏雨荷才走</button>
    <div></div>
    <span>夏雨荷</span>
    <script>
        // var obj = {};
        // obj.name = 'andy';
        // 简单动画函数封装obj目标对象 target 目标位置
        // 给不同的元素指定了不同的定时器
        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';
            }, 50);
        }
        var div = document.querySelector('div');
        var span = document.querySelector('span');
        var btn = document.querySelector('button');
        // 调用函数
        animate(div, 300);
        btn.addEventListener('click', function () {
            animate(span, 200);
        })
    </script>
</body>

</html>

请添加图片描述

4.4 缓动效果原理

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

  1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
  2. 核心算法:(目标值 - 现在的位置)/ 10 做为每次移动的距离步长
  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>Document</title>
    <style>
        span {
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>

<body>
    <button>点击夏雨荷才走</button>
    <span>夏雨荷</span>
    <script>
        function animate(obj, target) {
            // 先清除以前的定时器,只保留当前的一个定时器执行
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 步长值写到定时器的里面
                var step = (target - obj.offsetLeft) / 10;
                if (obj.offsetLeft == target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 15);
        }
        var span = document.querySelector('span');
        var btn = document.querySelector('button');
        // 调用函数
        btn.addEventListener('click', function () {
            animate(span, 500);
        })
        // 匀速动画 就是 盒子是当前的位置 +  固定的值 10
            // 缓动动画就是  盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
    </script>
</body>

</html>

请添加图片描述
上面的代码还有一个 bug,目标对象并不是在我们定的 500px 停下来的。 这是因为计算步长值公式的原因,只要涉及到除法,就可能会出现除不尽的情况,然后就会出现小数。所以我们需要把步长值改为整数。

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

可以让动画函数从 800 移动到 500。
当我们点击按钮时候,判断步长是正值还是负值

  1. 如果是正值,则步长 往大了取整
  2. 如果是负值,则步长 向小了取整
<!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>Document</title>
    <style>
        span {
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>

<body>
    <button class="btn500">点击夏雨荷到500</button>
    <button class="btn800">点击夏雨荷到800</button>
    <span>夏雨荷</span>
    <script>
        function animate(obj, target) {
            // 先清除以前的定时器,只保留当前的一个定时器执行
            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);
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 15);
        }
        var span = document.querySelector('span');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');
        // 调用函数
        btn500.addEventListener('click', function () {
            animate(span, 500);
        })
        btn800.addEventListener('click', function () {
            animate(span, 800);
        })
    </script>
</body>

</html>

请添加图片描述

4.6 动画函数添加回调函数

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

<!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>Document</title>
    <style>
        span {
            position: absolute;
            left: 0;
            top: 200px;
            display: block;
            width: 150px;
            height: 150px;
            background-color: purple;
        }
    </style>
</head>

<body>
    <button class="btn500">点击夏雨荷到500</button>
    <button class="btn800">点击夏雨荷到800</button>
    <span>夏雨荷</span>
    <script>
        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();
                    }
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 15);
        }
        var span = document.querySelector('span');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');
        // 调用函数
        btn500.addEventListener('click', function () {
            animate(span, 500);
        })
        btn800.addEventListener('click', function () {
            animate(span, 800, function () {
                // alert('你好吗');
                span.style.backgroundColor = 'red';
            });
        })
    </script>
</body>

</html>

请添加图片描述

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

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

  1. 单独新建一个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();
            }
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15);
}
<!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>Document</title>
    <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>
</head>

<body>
    <div class="sliderbar">
        <span></span>
        <div class="con">问题反馈</div>
    </div>
    <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>
</body>

</html>

请添加图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《JavaScript网页特效范例宝典源码》是一本收集了各种JavaScript网页特效的源码的书籍。该书提供了丰富多样的特效示例,包括动画、轮播图、导航菜单、弹出框等等。这些特效可以很好地应用于网页设计和开发中,使网页更加生动和有吸引力。 书中的源码是经过作者精心编写和整理的,旨在帮助读者理解和应用JavaScript特效。每个特效示例都附有详细的注释和使用说明,非常适合JavaScript初学者和有一定基础的开发者参考学习。 使用这本书,读者可以学习如何利用JavaScript创建各种实用的特效效果。例如,通过阅读源码可以了解如何实现一个平滑滚动的页面效果,或者如何制作一个鼠标点击特效。这些示例可以帮助读者掌握基本的JavaScript编程概念和技巧,提高其网页设计和开发的能力。 此外,这本书还提供了源码的下载链接,读者可以通过下载源码进行实践和调试,加深对特效实现原理的理解。 总的来说,《JavaScript网页特效范例宝典源码》是一本实用的JavaScript编程参考书,对于想要提升网页设计能力和运用JavaScript特效的读者来说,是一本不可多得的好书。阅读并实践这本书中的特效示例,可以让你的网页更加出彩,给用户留下深刻的印象。 ### 回答2: JavaScript网页特效范例宝典源码是一个收集和分享JavaScript网页特效代码的资源库。这个宝典源码包含了许多经典和创新的JavaScript特效,如轮播图、动画效果、页面交互等等。 在这个宝典源码中,你可以找到各种各样的网页特效示例,以及实现这些效果的代码。这些示例涵盖了不同的主题和领域,包括个人网站、企业网站、电子商务网站等等。 源码的使用非常简单。你可以浏览源码库,找到你感兴趣的特效示例,然后复制相关的代码到你自己的网页中即可实现相应的特效。每个特效示例都有相应的注释和说明,方便你理解和修改源码。 使用这个宝典源码,你可以快速地为你的网页增加一些令人印象深刻的交互效果。无论是为了提升用户体验,增加网页的吸引力,还是为了展示你的创意和技术实力,这个宝典源码都能够帮助你轻松实现。 总之,JavaScript网页特效范例宝典源码是一个有用的资源库,为网页设计师和开发者提供了丰富的JavaScript特效示例和相应的代码。通过使用这个源码,你可以为你的网页增加更多的互动和创意。 ### 回答3: JavaScript网页特效范例宝典源码是一个收集了各种JavaScript网页特效效果的宝典,它提供了丰富多样的源码示例,供开发人员在网页设计和开发过程中参考和使用。 这个宝典中的源码包含了许多经典的JavaScript特效,比如图片轮播、动画效果、菜单交互、弹出框等。每个特效都附带了详细的注释和说明,开发人员可以根据自己的需要进行修改和定制。 通过学习和使用这些源码示例,开发人员可以快速掌握JavaScript的应用技巧和网页特效的实现方法。无论是初学者还是有一定经验的开发人员,都可以从宝典中找到适合自己的参考案例。 值得一提的是,JavaScript网页特效范例宝典源码的适用范围非常广泛,无论是个人网站、企业网站还是各类应用程序都可以应用其中的特效效果,使网页更加生动、优雅和具有交互性。这些特效可以提升用户体验,增加网站的吸引力和用户留存率。 总之,JavaScript网页特效范例宝典源码是一个非常实用的资源,对于想要提升网页设计和开发能力的开发人员来说是不可或缺的。通过研究和运用这些源码示例,可以帮助开发人员更好地理解和运用JavaScript,为网页增加丰富的交互效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值