JS基础七【JS】

PC端网页特效

1. 元素偏移量offset系列

  1. offset

offset 翻译过来就是偏移量,我们是哦那个offset系列相关属性可以动态得到该元素(偏移),大小等。

offset属性说明
element.offsetTop返回元素相对带有定位父元素上方的偏移
element.offsetLeft返回元素相对带有定位父元素左边框的偏移
element.offsetParent返回元素相对带有定位父元素,如果父级都没有定位则返回body
element.offsetWidth返回自身包括padding、边框、内容区的宽度,返回数值不带单位
element.offsetHeight返回自身包括padding、边框、内容区的高度,返回数值不带单位
  1. offset与style区别

offset:

  • offset可以得到任意样式表中的样式值
  • offset一列获得的数值是没有单位的
  • offsetWidth包含padding+border+width
  • offsetWidth等属性是只读属性,只能获取不能赋值
  • 获取元素大小位置,用offset更合适

style:

  • style可以得到行内样式值
  • style一列获得的数值是带有单位的
  • style.width获得不包含padding和border的值
  • style.width是可读写属性,可以获取也可以赋值
  • 所以,我们想要给元素更改值,则需要用style改变

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

 <style>
        .box {
            width: 200px;
            height: 300px;
            background-color: pink;
            margin-top: 50px;
            margin-left: 100px;
        }
    </style>
<div class="box"></div>
    <script>
        var box = document.querySelector('.box');
        box.addEventListener('click', function(e){
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            this.innerHTML = 'x坐标是' + x + 'y坐标是' + y;
        })
    </script>

案例二:模态框拖拽

点击登录显示登录框,点击关闭,登录框隐藏,鼠标按下移动登录框

在这里插入图片描述
案例分析:
(1)获取元素
(2)点击弹出层这个链接 link,让模态框背景mask 和模态框login 显示出来
(3)点击 span,隐藏 模态框背景mask 和 模态框login
(4)开始拖拽,当鼠标在模态框中的title区域按下,获得鼠标在盒子内的坐标;鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top的值;当鼠标在浏览器中任意地方弹起的时候(所以依然用document绑定事件),移除之前绑定的鼠标移动(mousemove)的事件(move)

<style>
        .login-header {
            width: 100%;
            text-align: center;
            height: 30px;
            font-size: 24px;
            line-height: 30px;
        }
        ul,
        li,
        ol,
        dl,
        dt,
        dd,
        div,
        p,
        span,
        h1,
        h2, 
        h3,
        h4,
        h5,
        h6,
        a {
            padding: 0px;
            margin: 0px;
        }
        .login {
            display: none;
            /*先给模态框设置隐藏*/
            position: fixed;
            /*给模态框加一个固定定位*/
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            /*以上三句话加上定位,实现login模态框在浏览器中水平垂直居中*/
            background: #ffffff;
            box-shadow: 0px 0px 20px #ddd;
            z-index: 9999;
            border: #ebebeb solid 1px;
            width: 512px;
            height: 280px;
        }
        .login-title {
            width: 100%;
            margin: 10px 0px 0px 0px;
            text-align: center;
            line-height: 40px;
            height: 40px;
            font-size: 18px;
            position: relative;
            cursor: move;
        }
        .login-input-content {
            margin-top: 20px;
        }
        .login-button {
            display: none;
            /*献给模态框设置隐藏*/
            width: 100%;
            height: 100%;
            position: fixed;
            top: 0px;
            left: 0px;
            background: rgba(0, 0, 0, .3);
        }
        a {
            text-decoration: none;
            color: #000000;
        }
        .login-button a {
            display: block;
        }
        .login-input input.list-input {
            float: left;
            line-height: 35px;
            height: 35px;
            width: 350px;
            border: 1px solid #ebebeb;
            text-indent: 5px;
        }
        .login-input {
            overflow: hidden;
            margin: 0px 0px 20px 0px;
        }
        .login-input label {
            float: left;
            width: 90px;
            padding-right: 10px;
            text-align: right;
            line-height: 35px;
            height: 35px;
            font-size: 14px;
        }
        .login-title span {
            position: absolute;
            font-size: 12px;
            right: -20px;
            top: -30px;
            background: #ffffff;
            border: 1px solid #ebebeb;
            width: 40px;
            height: 40px;
            border-radius: 20px;
            cursor: pointer;
        }
    </style>
<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>
                <input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
            </div>
            <div class="login-input">
                <label>登陆密码:</label>
                <input type="password" placeholder="请输入登陆密码" name="info[password]" id="password" class="list-input">
            </div>
        </div>
        <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">会员登录</a></div>
    </div>
    <div id="bg" class="login-bg"></div>
<script>
        //1.获取元素
        var login = document.querySelector('.login');
        var mask = document.querySelector('.login-bg');
        var link = document.querySelector('#link');
        var title = document.querySelector('#title');
        var span = document.querySelector('span');
        //2. 点击弹出层这个链接 link,让模态框背景mask 和模态框login 显示出来
        link.addEventListener('click', function(){
            mask.style.display = 'block';
            login.style.display = 'block';
        })
        //3. 点击 span,隐藏 模态框背景mask 和 模态框login
        span.addEventListener('click', function(){
            mask.style.display = 'none';
            login.style.display = 'none';
            e.stopPropagation();
            //解决了添加鼠标按下事件(mousedown)后,由于默认是冒泡,会导致点击login模态框的子集span也可以移动模态框的BUG
        })
        //4. 开始拖拽
        //(1) 当鼠标在模态框中的title区域按下,获得鼠标在盒子内的坐标
        title.addEventListener('mousedown', function(e){
            //(2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top的值
            var x = e.pageX - login.offsetLeft;
            var y = e.pageY - login.offsetTop;
            document.addEventListener('mousemove', move);
            //只有按下后才能拖动鼠标(mousemove),所以mousemove要写在mousedown里面
            //在页面中任意地方都可以移动鼠标,所以用document绑定事件
            function move(e){
                login.style.left = e.pageX - x + 'px';
                login.style.top = e.pageY - y + 'px';
                //注意:e.pageX, e.pageY, e.offsetLeft, e.offsetTop返回的值都没有单位,所以要用拼接字符串加上单位
            }
            //(3) 当鼠标在浏览器中任意地方弹起的时候(所以依然用document绑定事件),移除之前绑定的鼠标移动(mousemove)的事件(move)
            document.addEventListener('mouseup', function(){
                document.removeEventListener('mousemove', move);
            })
        })
    </script>

2. 元素可视区client系列

client翻译过来就是客户端,我们是哦那个client系列的相关来获取元素的可视区的相关信息
通过client系列的相关属性可以动态的得到该元素的边框大小,元素大小

client系列属性说明
element.clientTop返回元素上边框的大小
element.clientLeft返回元素左边框的大小
element.clientWidth返回自身包括padding内容区的宽度,不包含边框,返回的数值不带单位
element.clientHeight返回自身包括padding内容区的高度,不包含边框,返回的数值不带单位

立即执行函数:

不需要调用,立马能够自己执行的函数

(function(){})()或者
(function(){}());

例:

	(function(){
		console.log(2)
	})()  //第二个小括号可以看作是调用函数,也可以传递参数进来
	(function(a, b){
		console.log(a + b)
	}(1, 2));//3
	多个立即执行函数之间用’;‘隔开

立即执行函数最大的作用就是:独立创建了一个作用域

3. 元素滚动scroll系列

scroll系列属性说明
element.scrollTop返回被卷去的上侧距离,返回数值不带单位
element.scrollLeft返回被卷去的左侧距离,返回数值不带单位
element.scrollWidth返回自身实际宽度,不含边框,返回数值不带单位
element.scrollHeight返回自身实际高度,不含边框,返回数值不带单位

页面被卷曲的头部:可以通过window.pageYOffset获得
如果被卷去是左侧,则window.pageXOffset获得
声明了DTD,使用document.documentElement.scrollTop
未声明DTD,使用document.body.scrollTop

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

<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>
<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.offsetTop 就是被卷去头部的大小 一定要写到滚动的外面
        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(){
            //window.pageYOffset 页面被卷去的头部
           console.log(window.pageYOffset);
           //3. 当我们页面被卷去的头部大于等于170 此时 侧边栏就要改为固定定位
            if(window.pageYOffset >= bannerTop){
                sliderbar.style.position = 'fixed';
                sliderbar.style.top = sliderbarTop + 'px';


            }else {
                sliderbar.style.position = 'absolute';

            }
            //4. 当我们页面滚动到main盒子,就是显示 goback 模块
            if(window.pageYOffset >= mainTop){
                goBack.style.display = 'block';


            }else {
                goBack.style.display = 'none';

            }
        })
    </script>

4. mouseenter 和 mouseover 事件区别

(1)mouseover鼠标经过自身盒子会触发,经过子盒子还会触发
(2)mouseenter只会经过自身盒子触发

5. 动画函数封装

  1. 动画原理实现
    核心原理:通过定时器setInterval()不断移动盒子位置
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <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 >= 400) {
                // 停止动画 本质是停止定时器
                clearInterval(timer);
            }
            div.style.left = div.offsetLeft + 1 + 'px';
        }, 30);
    </script>
</body>

</html>
  1. 动画函数简单封装
<!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>
        //简单动画函数封装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';
            }, 30);
        }
        var div = document.querySelector('div');
        var span = document.querySelector('span');
        var btn = document.querySelector('button');
        //调用函数
        animate(div, 300);
        //animate(span, 200);
        btn.addEventListener('click', function(){
            animate(span, 200);
        })

    </script>
</body>
</html>
  1. animate.js
function animate(obj, target, 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);
}
  1. 缓动效果
<!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 class="btn500">点击夏雨荷到500</button>
    <button class="btn800">点击夏雨荷到800</button>
    
    <span>夏雨荷</span>
    <script>
        //简单动画函数封装obj目标对象 target 目标位置
        //给不同的元素指定了不同的定时器
        function animate(obj, target, 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';
            }, 30);
        }
        //var div = document.querySelector('div');
        var span = document.querySelector('span');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');

        //调用函数
        //animate(div, 300);
        //animate(span, 200);
        btn500.addEventListener('click', function(){
            animate(span, 500);
        })
        btn800.addEventListener('click', function(){
            //调用函数
            animate(span, 800, function(){
                //alert('你好吗');
                span.style.backgroundColor = 'red';
            });
        })
        //匀速动画 就是 盒子是当前的位置 + 固定的值 10
        //缓动动画就是 盒子当前的位置 + 变化的值((目标值-现在的位置)/ 10)
    </script>
</body>
</html>
  1. 动画函数
<!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>

6. 节流阀

目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让时间无法连续触发。
核心思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

//开始设置一个变量
var flag = true;
if(flag){
	flag = false;
	do something;
}
//关闭水龙头,利用回调函数,动画执行完毕
flag = true //打开水龙头
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值