javaSprict BOM操作

-BOM

BOM概述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

window对象常见事件

窗口加载事件

window.onload

页面加载事件

​ window.onload 是窗口(页面加载事件),当文档内容完全加载完成会触发该事件(包括图像、脚本文件、css文件等),就调用处理函数。

​ 1.有了window.onload就可以把js代码写到元素页面的上方,因为onload是等页面内容全部加载完毕再去执行处理函数。

​ 2.window.onload 传统注册事件只能写一次,如多有多个就会以最后一个window.onload为准。

​ 3.如果使用addEventListener则没有限制。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //---------传统注册事件--------------------------------
        // window.onload = function (){
        //     var btn = document.querySelector('button');
        //     btn.addEventListener('click',function(){
        //         alert('123')
        //     })
        // }

        // window.onload = function(){
        //     alert(22)
        // }


        // --------------如果使用addEventListener则没有限制。------------------------
        // 推荐
        window.addEventListener('load', function () {

            var btn = document.querySelector('button');
            btn.addEventListener('click', function () {
                alert('123')
            })

        })

        window.addEventListener('load', function () {
            alert(22)
        })
    </script>
    <button>点击</button>
</body>

</html>
DOMContentLoaded

DOMContentLoaded 事件触发时候,仅当DOM加载完成,不包括样式表、图片、flash等。ie9以上支持。

如果页面图片很多的话,从用户访问到onload触发可能需要较长的时间交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded 事件比较合适。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>

        // --------------如果使用addEventListener则没有限制。------------------------
        // 推荐
        window.addEventListener('load', function () {

            var btn = document.querySelector('button');
            btn.addEventListener('click', function () {
                alert('123')
            })

        })

        window.addEventListener('load', function () {
            alert(22)
        })
        // -------DOMContentLoaded -----------------

        documen.addEventListener('DOMContentLoaded', function () {
            alert(33);
        })
    </script>
    <button>点击</button>
</body>

</html>
比较

load是等页面内容全部加载完毕,包含dom元素 图片 flash css 等

DOMContentLoaded 是DOM加载完毕,不包含图片 flash css 等就可以执行 加载速度比load跟快一些。

调整窗口大小事件

window.onresize = function(){};

window.addEventListener('resize',function(){
    
})

window.onresize 是调整窗口大小加载事件,当触发时候就调用的处理函数

注意:

只要窗口大小发生改变,就会触发这个事件。

我们职场利用这个事件来完成响应式布局。window.innerWidth 当前屏幕的宽度。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: cornflowerblue;
        }
    </style>
</head>

<body>

    <div></div>
    <script>

        var div = window.document.querySelector('div');
        window.addEventListener('resize', function () {
            console.log('变化了');
            console.log(window.innerWidth);
            if (window.innerWidth <= 800) {
                div.style.display = 'none';
            }
            else {
                div.style.display = 'block';
            }
        })
    </script>
</body>

</html>

定时器

window对象提供了两种定时器

  • setTimeout()
  • setInterval()
setTimeout() 定时器

只调用一次!!!

setTimeout() 方法用于设置一个定时器,该定时器到期后执行调用函数。

setTimeout() 这个函数我们也称为回调函数callback

普通函数是按照代码顺序直接调用。 而这个函数,需要等待时间,时间到了才调用这个函数。

element.onclick = function(){} 或者element.addEventListener(){‘click’,funcion(){}}; 里面的函数也是回调函数。

window.setTimeout(调用函数,[延迟毫秒数]);
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!--  -->
    <script>
        // 这个window在调用时候可以shenglue
        // 这个延迟时间默认是毫秒,但是可以省略,如果省略默认是0          
        
        //第一种写法 
        setTimeout(function () {
            alert('已经两秒了')
        }, 2000)


        //第二种写法 
        // 这个调用函数可以直接写函数 还可以 写函数名
        function boom() {
            alert('砰!')
        }
        setTimeout(boom, 3000)
        
        // 还有一种写法 不提倡
        setTimeout('boom()', 4000)

        // 页面中可能有很多定时器,所以 最好给定时器加标识符(名字)
        var timer1 = setTimeout(boom, 5000)


    </script>
</body>

</html>
自动关闭广告案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 200px;
            height: 600px;
            background-color: coral;
        }
    </style>
</head>

<body>
    <div>
        这是广告
    </div>
    <script>
        var ad = document.querySelector('div');
        setTimeout(function () {
            ad.style.display = 'none';
        }, 3000)
    </script>
</body>

</html>
清除定时器clearTimeout

停止setTimeout() 定时器

window.clearTimeout(timeoutID)
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>停止定时器</button>
    <script>
        var btn = document.querySelector('button');
        var timer = setTimeout(function () {
            console.log('砰')
        }, 3000)

        btn.addEventListener('click', function () {
            clearTimeout(timer)
        })
    </script>
</body>

</html>
setInterval()定时器

可以一直循环调用!!!

window.setInterval(回调函数,[间隔的毫秒数]);

setInterval() 方法重复调用一个函数,每隔这个事件就去调用一次回调函数。

注意:

  • window可以省略。
  • 这个回调函数可以直接写函数,或者写函数名或者采取字符串’函数名’ 三种形式。
  • 间隔毫秒数默认是0,如果写,必须是毫秒,标书每隔多少毫秒就自动调用这个函数。
  • 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        setInterval(function(){
            console.log('砰!');            
        },1000)
    </script>
</body>
</html>
小米倒计时案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box {
            width: 150px;
            height: 200px;
            border: 1px #ccc solid;
            margin: 100px auto;
        }

        #box>div {
            /* border: 1px #ccc solid; */
            margin-top: 120px;
            width: 150px;
            height: 40px;
        }

        span {
            display: inline-block;
            height: 40px;
            width: 40px;
            background-color: #32332E;
            margin-left: 5px;
            text-align: center;
            line-height: 40px;
            color: cornsilk;
        }
    </style>
</head>

<body>
    <div id="box">
        <div>
            <span class="hour">1</span>
            <span class="minute">2</span>
            <span class="second">3</span>
        </div>
    </div>

    <script>
        // 1.获取元素
        // 时分秒的三个小盒子
        var hour = document.querySelector('.hour');
        var minute = document.querySelector('.minute');
        var second = document.querySelector('.second');
        var inputTime = +new Date('2020-9-1 00:00:00');//返回用户输入时间的毫秒数
        // 先调用一次倒计时函数,防止页面刷新有空白
        conutDown()
        // 开启定时器
        setInterval(conutDown, 1000)
        function conutDown() {
            var nowTime = +new Date();//返回当前时间的毫秒数          
            var times = (inputTime - nowTime) / 1000;  //times就是剩余时间总的秒数
            var h = parseInt(times / 60 / 60 % 24);//计算小时
            h = h < 10 ? '0' + h : h;
            // 把剩余时间赋值给盒子 下面同理
            hour.innerHTML = h;
            var m = parseInt(times / 60 % 60);//计算分钟
            m = m < 10 ? '0' + m : m;
            minute.innerHTML = m;
            var s = parseInt(times % 60);//计算秒数
            s = s < 10 ? '0' + s : s;
            second.innerHTML = s;
        }

    </script>

</body>

</html>
清除定时器clearInterval
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button class="begin">开始定时器</button>
    <button class="stop">停止定时器</button>

    <script>
        var begin = document.querySelector('.begin');
        var stop = document.querySelector('.stop');
        // 先定义一个全部变量方便下面使用  null是一个空对象
        var timer = null;
        begin.addEventListener('click', function () {
            timer = setInterval(function () {
                console.log('定时器开始工作');
            }, 1000)
        })

        stop.addEventListener('click', function () {
            clearInterval(timer);
        })

    </script>
</body>

</html>
发送短信案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <input type="number">
    <button>点击发送短信</button>
    <script>
        var input = document.querySelector('input');
        var btn = document.querySelector('button');
        var time = 5;
        btn.addEventListener('click', function () {
            btn.disabled = true;
            var timer = setInterval(function () {
                if (time == 0) {
                    // 清除定时器
                    clearInterval(timer);
                    btn.innerHTML = '点击输入短信'
                    btn.disabled = false;
                    // 清除定时器之后要重新给time赋值
                    time = 5;
                }
                else {
                    btn.innerHTML = '还剩下' + time + '秒'
                    time = time - 1;
                }

            }, 1000)
        })
    </script>
</body>

</html>

js的执行队列

javaScript 最大的特点就是单线程,同一个事件只能做一件事情。

单线程意味着任务需要排队,会导致的问题:如果js执行时间过长,这样会造成渲染不连贯,导致加载阻塞的感觉。

同步和异步

在这里插入图片描述
在这里插入图片描述

js的执行机制

在这里插入图片描述
在这里插入图片描述

location对象

window 对象给我们提供了一个location属性 用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象

URL

统一资源定位符(url),是互联网上标准资源的地址。互联网上每个文件都有一个位置的url,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

在这里插入图片描述

location对象的属性

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button>点击</button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click',function(){
            // console.log(window.location.href);
            // 点击页面跳转
            location.href = 'https://www.bilibili.com/'           
        })
    </script>
</body>
</html>
5秒页面跳转案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>点击</button>
    <div></div>
    <script>
        var btn = document.querySelector('button');
        var div = document.querySelector('div');

        btn.addEventListener('click', function () {
            // console.log(window.location.href);
            // 点击页面跳转
            location.href = 'https://www.bilibili.com/'
        })

        
        var time = 5;
		//先在前面调用一次函数就不会有一秒的空白
        conutDown();
        setInterval(conutDown, 1000)
        function conutDown() {
            if (time == 0) {
                location.href = 'https://www.bilibili.com/'
                time = 5;
            } else {
                div.innerHTML = '在' + time + '秒后跳转到雄的页面'
                time--
            }
        }

    </script>
</body>

</html>
获取URL参数,数据在不同页面传递

https://www.bilibili.com/video/BV1k4411w7sV?p=93

在这里插入图片描述

login界面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="index.html">
        用户名:<input type="text" name="uname">
        <input type="submit" value="登陆">
    </form>
</body>
</html>

index界面代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div></div>
    <script>

        console.log(location.search);// ?uname=1750306016
        // 1.去掉?  用 substr('截取的起始位置','截取几个字符')
        var params = location.search.substr(1);
        console.log(params);
        // 2.利用 = 号 把字符串分割为数组 split('=')

    	//  字符替换为数组 split('分隔符')  与join()把数组转化为字符串相反  
		//  split('分隔符') 里面的分隔符取决于 字符串 里面用什么符号隔开
        var arr = params.split('=');
        console.log(arr);
        // 把数据写入div中
        var  div = document.querySelector('div');
        div.innerHTML = arr[1]+'你好';
    </script>
</body>

</html>
location 对象的方法

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<button>点击</button>
	<script>
		var btn = document.querySelector('button');
		btn.addEventListener('click',function(){
			// 可以记录浏览历史 所以可以实现后退功能
			// location.assign('https://www.bilibili.com/');
			
			// 不可以记录浏览历史 所以不可以实现后退功能
			// location.replace('https://www.bilibili.com/');

			// 刷新按钮
			location.reload();
		})
	</script>
</body>
</html>

navigator对象

​ navigator 对象 包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。

​ 下面的前端代码可以判断用户哪个终端打开页面:

在这里插入图片描述

代码演示视频

https://www.bilibili.com/video/BV1k4411w7sV?p=95

history 对象

​ window 对象 给我们提供了一个history 对象,与浏览器记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。

在这里插入图片描述

前进后退功能类似于下面按钮

在这里插入图片描述

	var btn = document.querySelector('button');
		btn.addEventListener('click',function(){
			history.forward();
	})

PC端页面特效

元素偏移量offset系列

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

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

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		body {
			margin: 0;
			padding: 0;
		}

		.father {
			/* 定位 */
			position: relative;
			width: 100px;
			height: 100px;
			background-color: coral;
			margin: 100px;
		}

		.son {
			width: 50px;
			height: 50px;
			background-color: cornflowerblue;
			margin: 40px;
		}

		.w {
			width: 200px;
			height: 200px;
			background-color: rgb(76, 223, 142);
			margin: 0 auto 200px;
			padding: 20px;
			border: 2px solid #000;
		}
	</style>
</head>
<body>
	<div class="father">
		<div class="son"></div>
		<div class="w"></div>
	</div>
	<script>

		var father = document.querySelector('.father')
		var son = document.querySelector('.son')
		var w = document.querySelector('.w')
		// 1.获得元素的偏移量 位置 返回不带单位的数值
		console.log(father.offsetTop);
		console.log(father.offsetLeft);

		// 它以带有定位的父亲为准 如果没有父亲或者父亲没有定位 则以 body 为准
		console.log(son.offsetLeft);

		// 2.可以得到元素的大小 宽度 和高度 是包含 padding + border + width 
		console.log(w.offsetWidth);
		console.log(w.offsetHeight);

		// 3. 返回带有定位的父亲 否则返回的是body
		console.log(son.offsetParent);
		//返回父亲 返回的是最近一级的父亲 不管父亲有没有定位
		console.log(son.parentNode);

	</script>
</body>

</html>
offset与style的区别

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		.box{
			width: 200px;
			height: 200px;
			background-color: rgb(85, 161, 228)
		}
	</style>
</head>
<body>
	<div class="box"></div>
	<script>
		var box = document.querySelector('.box');
		console.log(box.offsetWidth);
		console.log(box.style.width);
		
	</script>
</body>
</html> 
获取鼠标在盒子内的坐标案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            width: 300px;
            height: 300px;
            background-color: burlywood;
            margin: 100px auto;
        }
    </style>
</head>
<body>
    <div class="box"></div>
    <script>
        // 鼠标在页面的坐标(e.pageX,e.pageY)
        // 盒子到页面的距离(box.offsetLeft,box.offsetTop)
        var box = document.querySelector('.box')
        box.addEventListener('mousemove', function (e) {
            //    console.log(e.pageX)
            //    console.log(e.pageY);
            //    console.log(box.offsetLeft);
            //    console.log(box.offsetTop);
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            // console.log(x);
            // console.log(y);
            box.innerHTML = 'x的坐标是:'+x+'y的坐标是:'+y;
        })
    </script>
</body>

</html>
案例:模态框拖拽

有bug未解决 鼠标点击时候模态框会跳开

<style>
	.con {
		padding: 200px 0 0 200px;
	}

	.box {
		width: 300px;
		box-sizing: border-box;
		position: relative;
	}

	.box img {
		width: 100%;
	}

	.mask {
		display: none;
		position: absolute;
		width: 100px;
		height: 100px;
		top: 0;
		left: 0;
		background-color: yellow;
		opacity: .5;
		cursor: move;
		/* transform: translate(-50%, -50%); */
	}

	.big {
		display: none;
		width: 600px;
		height: 600px;
		position: absolute;
		left: 550px;
		top: 200px;
		background-color: pink;
		border: solid 2px black;
		overflow: hidden;
		z-index: 999;
	}

	.big img {
		width: 1000px;
		display: block;
		position: absolute;
		top: 0;
		left: 0;
	}
</style>
<div class="con">
	<div class="box">
		<img src="/js进阶BOM/案例/timg.jpg" alt="">
		<!-- 遮挡层 -->
		<div class="mask"></div>
	</div>
	<div class="big">
		<img src="/js进阶BOM/案例/timg.jpg" alt="" class="bigimg">
	</div>
</div>

<!-- 
	案例分析:
	1、整个案例可以分为三个功能模块
	2、鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏两个盒子功能
	3、黄色的遮挡层跟随鼠标功能
	4、移动黄色遮挡层,大图片跟随移动功能
	5、获得鼠标在盒子的坐标
	6、把数值给遮挡层作为left和top值
	7、此时用到鼠标移动事件,但是还是在小图片盒子内移动
	8、遮挡层不能超出雄安盒子范围
	9、如果小于0,就把坐标设置为0q
	10、求大图片的移动距离公式
		遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离
 -->
<script>
	window.addEventListener('load', function () {
		var box = document.querySelector('.box');
		var mask = document.querySelector('.mask');
		var big = document.querySelector('.big');
		//  鼠标经过box时 大盒子 big 和遮挡层 mask 显示
		box.addEventListener('mouseover', function () {
			mask.style.display = 'block';
			big.style.display = 'block';
		})
		box.addEventListener('mouseout', function () {
			mask.style.display = 'none';
			big.style.display = 'none';
		})
		box.addEventListener('mousemove', function (e) {
			// 先计算出鼠标在盒子内的坐标
			var x = e.pageX - this.offsetLeft;
			var y = e.pageY - this.offsetTop;
			// 遮挡层mask距离盒子边框的距离  或者说mask 移动的距离
			var maskX = x - mask.offsetWidth / 2;
			var maskY = y - mask.offsetHeight / 2;
			// 遮挡层最大移动距离 
			var maskMax = box.offsetWidth - mask.offsetWidth;
			var maskMaxY = box.offsetHeight - mask.offsetHeight;
			// 如果x坐标小于0,就让mask停在0的位置
			if (maskX <= 0) {
				maskX = 0;
			} else if (maskX >= maskMax) {
				maskX = maskMax;
			}
			// Y坐标
			if (maskY <= 0) {
				maskY = 0;
			} else if (maskY >= maskMaxY) {
				maskY = maskMaxY;
			}
			mask.style.left = maskX + 'px';
			mask.style.top = maskY + 'px';
			// 大图
			var bigimg = document.querySelector('.bigimg');
			// 大图可移动距离等于图片 - (大盒)容器宽度
			var bigmax = bigimg.offsetWidth - big.offsetWidth;
			var bigmaxY = bigimg.offsetHeight - big.offsetHeight;
			console.log(bigimg.offsetWidth);
			console.log(bigmax);
			// 大图的移动距离,根据公式: 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离
			var bigX = maskX * bigmax / maskMax;
			var bigY = maskY * bigmaxY / maskMaxY;

			bigimg.style.left = -bigX + 'px';
			bigimg.style.top = -bigY + 'px';
		})
	})
</script>
案例:仿京东放大镜效果
<style>
	.con {
		padding: 200px 0 0 200px;
	}

	.box {
		width: 300px;
		box-sizing: border-box;
		position: relative;
	}

	.box img {
		width: 100%;
	}

	.mask {
		display: none;
		position: absolute;
		width: 100px;
		height: 100px;
		top: 0;
		left: 0;
		background-color: yellow;
		opacity: .5;
		cursor: move;
		/* transform: translate(-50%, -50%); */
	}

	.big {
		display: none;
		width: 600px;
		height: 600px;
		position: absolute;
		left: 550px;
		top: 200px;
		background-color: pink;
		border: solid 2px black;
		overflow: hidden;
		z-index: 999;
	}

	.big img {
		width: 1000px;
		display: block;
		position: absolute;
		top: 0;
		left: 0;
	}
</style>
<div class="con">
	<div class="box">
		<img src="/js进阶BOM/案例/timg.jpg" alt="">
		<!-- 遮挡层 -->
		<div class="mask"></div>
	</div>
	<div class="big">
		<img src="/js进阶BOM/案例/timg.jpg" alt="" class="bigimg">
	</div>
</div>

<!-- 
	案例分析:
	1、整个案例可以分为三个功能模块
	2、鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏两个盒子功能
	3、黄色的遮挡层跟随鼠标功能
	4、移动黄色遮挡层,大图片跟随移动功能
	5、获得鼠标在盒子的坐标
	6、把数值给遮挡层作为left和top值
	7、此时用到鼠标移动事件,但是还是在小图片盒子内移动
	8、遮挡层不能超出雄安盒子范围
	9、如果小于0,就把坐标设置为0q
	10、求大图片的移动距离公式
		遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离
 -->
<script>
	window.addEventListener('load', function () {
		var box = document.querySelector('.box');
		var mask = document.querySelector('.mask');
		var big = document.querySelector('.big');
		//  鼠标经过box时 大盒子 big 和遮挡层 mask 显示
		box.addEventListener('mouseover', function () {
			mask.style.display = 'block';
			big.style.display = 'block';
		})
		box.addEventListener('mouseout', function () {
			mask.style.display = 'none';
			big.style.display = 'none';
		})
		box.addEventListener('mousemove', function (e) {
			// 先计算出鼠标在盒子内的坐标
			var x = e.pageX - this.offsetLeft;
			var y = e.pageY - this.offsetTop;
			// 遮挡层mask距离盒子边框的距离  或者说mask 移动的距离
			var maskX = x - mask.offsetWidth / 2;
			var maskY = y - mask.offsetHeight / 2;
			// 遮挡层最大移动距离 
			var maskMax = box.offsetWidth - mask.offsetWidth;
			var maskMaxY = box.offsetHeight - mask.offsetHeight;
			// 如果x坐标小于0,就让mask停在0的位置
			if (maskX <= 0) {
				maskX = 0;
			} else if (maskX >= maskMax) {
				maskX = maskMax;
			}
			// Y坐标
			if (maskY <= 0) {
				maskY = 0;
			} else if (maskY >= maskMaxY) {
				maskY = maskMaxY;
			}
			mask.style.left = maskX + 'px';
			mask.style.top = maskY + 'px';
			// 大图
			var bigimg = document.querySelector('.bigimg');
			// 大图可移动距离等于图片 - (大盒)容器宽度
			var bigmax = bigimg.offsetWidth - big.offsetWidth;
			var bigmaxY = bigimg.offsetHeight - big.offsetHeight;
			console.log(bigimg.offsetWidth);
			console.log(bigmax);
			// 大图的移动距离,根据公式: 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离
			var bigX = maskX * bigmax / maskMax;
			var bigY = maskY * bigmaxY / maskMaxY;

			bigimg.style.left = -bigX + 'px';
			bigimg.style.top = -bigY + 'px';
		})
	})
</script>

元素可视区client系列

我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以得改元素的边框大小、元素大小等。

在这里插入图片描述

立即执行函数

(function(){})()

​ 主要作用:创建一个独立作用域 避免命名冲突问题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 立即执行函数:需要调用立马能够自己执行的函数。
        // 两种写法  
        // (function(){})();
        // // 或者
        // (function(){}());

        (function (a, b) {
            console.log(a);
            console.log(a + b);

            console.log(2);
            //第二个小括号可以看做是调用函数 里面可以添加实参
        })(1, 3);

        // 如果有多个立即执行函数中间一定要用分号隔开
        // 也可以给函数添加名字
        (function sum(a, b) {
            console.log(a + b);

        }(2, 3))

        // 立即执行函数最大的作用就是 独立创造了一个作用域 里面所有的变量都是局部变量
    </script>
</body>

</html>

元素滚动scroll系列

scroll系列的相关属性可以动态的得到该元素的大小滚动距离

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 100px;
            height: 100px;
            background-color: brown;
            overflow: auto;
        }
    </style>
</head>
<body>
    <div>
        11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
    </div>
    <script>
        var div = document.querySelector('div');
        div.addEventListener('scroll',function(){
            
            console.log(div.scrollLeft);
            
        })
    </script>
</body>
</html>

在这里插入图片描述

淘宝右侧侧边栏案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body,
        html {
            margin: 0;
            padding: 0;
        }

        .header {
            width: 95%;
            height: 300px;
            background-color: cadetblue;
            margin: 0px auto
        }

        .article {
            width: 95%;
            height: 1000px;
            background-color: rgb(80, 225, 230);
            margin: 10px auto
        }

        .footer {
            width: 95%;
            height: 200px;
            background-color: rgb(24, 137, 141);
            margin: 10px auto
        }

        .aside {
            position: absolute;
            width: 40px;
            height: 100px;
            background-color: chartreuse;
            right: 10px;
            top: 310px;

        }

        .aside div {
            width: 100%;
            background-color: darkorange;
            margin: 50px auto;
            display: none;
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div class="header">头部</div>
    <div class="aside">
        <div id="backtop">返回顶部</div>
    </div>
    <div class="article">正文</div>
    <div class="footer">尾部</div>

    <!-- 
        案例分析
        1.需要页面滚动元素 scroll 因为是页面滚动 所以事件源是document。
        2.滚动到某个位置,就是判断页面被卷去的上部值
        3.页面被卷去的头部,可以通过window.pageYOffset 获得 去过 被卷去的是左侧 window.pageXOffset
        4.注意:元素被卷去的头部是element.scrollTop,如果是页面被卷去的头部则是window.pageYOffset
        
    -->
    <script>
        // 获取元素
        var aside = document.querySelector('.aside');
        var backtop = document.querySelector('#backtop')

        var header = document.querySelector('.header')
        console.log(header);
        // 头部的高度
        console.log(header.offsetHeight);

        // 页面滚动事件
        document.addEventListener('scroll', function () {
            // 页面被卷去的头部
            console.log(window.pageYOffset);
            // 3.当我们页面被卷去的头部大于300px 此时侧边栏改为固定定位

            if (window.pageYOffset >= header.offsetHeight) {
                aside.style.position = 'fixed'
                aside.style.top = 0 + 'px'
                backtop.style.display = 'block'

            }
            else {
                aside.style.position = 'absolute'
                aside.style.top = header.offsetHeight + 'px'
                backtop.style.display = 'none'
            }

        })
        backtop.addEventListener('click', function () {
            window.pageYOffset = 0;
        })
    </script>
</body>

</html>

三大系列总结

在这里插入图片描述

他们的主要用法:

1.offset系列经常用于获取元素位置 offsetLeft offsetTop

2.client经常用于获取元素大小 clientWidth clientHight

3.scroll经常用于获取滚动距离 scrollTop scrollLeft

4.注意页面的滚动距离通过window.pageXOffset 获得

动画原理

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

实现步骤:

  1. 获得盒子当前的位置
  2. 让盒子在当前位加上1和移动距离
  3. 利用定时器不断重复这个动作
  4. 加一个结束定时器的条件。
  5. 注意元素需要添加定位,才能使用element.style.left
动画函数封装

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

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

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

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

<!DOCTYPE html>
<html lang="en">

<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <style>
       div {
           position: absolute;
           left: 0;
           width: 200px;
           height: 200px;
           background-color: blueviolet;
       }

       span {
           position: absolute;
           left: 0;
           width: 100px;
           height: 100px;
           background-color: rgb(83, 155, 113);
       }

       button {
           margin-top: 300px;
       }
   </style>
</head>

<body>

   <div></div>
   <span></span>
   <button>点击方块移动</button>
   <!-- 
       动画原理
       1. 获得盒子当前的位置
       2. 让盒子在当前位加上1和移动距离
       3. 利用定时器不断重复这个动作
       4. 加一个结束定时器的条件。
       5. 注意元素需要添加定位,才能使用element.style.left
    -->

   <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';
           }, 1)
       }

       var div = document.querySelector('div');
       var span = document.querySelector('span')
       // 调用函数

       var button = document.querySelector('button');
       // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器
       // 解决方案就是让元素只有一个定时器执行
       button.addEventListener('click', function () {
           animate(div, 200)
           animate(span, 600)
       })
   </script>
</body>

</html>
缓动动画原理

缓动动画就是让元素的运动速度有所变化。

思路:

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

后退有点bug

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 200px;
            height: 200px;
            background-color: blueviolet;
        }

        span {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: rgb(83, 155, 113);
        }

        button {
            margin-top: 300px;
        }
    </style>
</head>

<body>

    <div></div>
    <span></span>
    <button class="button600">点击方块移动600</button>
    <button class="button1000">点击方块移动1000</button>

    <script>
        // 简单动画函数的封装 obj目标函数 target目标对象
        function animate(obj, target) {
            // 解决方案就是让元素只有一个定时器执行
            // 先清除以前的定时器只保留一个定时器执行
            clearInterval(obj.timer)
            //↓↓↓↓↓ 给不同元素指定了不同的定时器
            obj.timer = setInterval(function () {
                // 步长值写到定时器里面
                // 把步长值改为整数不要出现小数的距离
                // var step = Math.ceil((target - obj.offsetLeft) / 10);
                // 判断div是前进还是后退 时候 步长值是向上取整还是向下取整
                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 div = document.querySelector('div');
        var span = document.querySelector('span')
        // 调用函数

        var btn600 = document.querySelector('.button600');
        var btn1000 = document.querySelector('.button1000');

        // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器
        // 解决方案就是让元素只有一个定时器执行
        btn600.addEventListener('click', function () {
            animate(div, 200)

        })
        btn1000.addEventListener('click', function () {
            animate(div, 600)

        })


    </script>
</body>

</html>
动画函数添加回调函数

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

​ 回调函数写的位置:定时器结束的位置

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 200px;
            height: 200px;
            background-color: blueviolet;
        }

        button {
            margin-top: 300px;
        }
    </style>
</head>

<body>

    <div></div>

    <button class="button600">点击方块移动600</button>
    <button class="button1000">点击方块移动1000</button>

    <script>

        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';
            }, 15)
        }

        var div = document.querySelector('div');
        var span = document.querySelector('span')
        // 调用函数

        var btn600 = document.querySelector('.button600');
        var btn1000 = document.querySelector('.button1000');

        // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器
        // 解决方案就是让元素只有一个定时器执行
        btn600.addEventListener('click', function () {
            // 回调函数
            animate(div, 200, function () {
                div.style.backgroundColor = 'pink';
            })

        })
        btn1000.addEventListener('click', function () {
            animate(div, 600)

        })
    </script>
</body>

</html>
动画函数封装到单独js文件里面

独立新建一个js文件。

html文件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 200px;
            height: 200px;
            background-color: blueviolet;
        }
    </style>
    <script src="/js进阶BOM/js/animate.js"></script>

</head>

<body>
    <div></div>
    <script>
        var div = document.querySelector('div');
        div.addEventListener('click', function () {
            animate(div, 400);
        })
    </script>
</body>

</html>

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();
            }
        }
        // 
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15)
}

mouseenter和mouseover的区别

mouseenter鼠标事件

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

常见网页特效案例

            div.style.backgroundColor = 'pink';
        })

    })
    btn1000.addEventListener('click', function () {
        animate(div, 600)

    })
</script>
```
动画函数封装到单独js文件里面

独立新建一个js文件。

html文件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 200px;
            height: 200px;
            background-color: blueviolet;
        }
    </style>
    <script src="/js进阶BOM/js/animate.js"></script>

</head>

<body>
    <div></div>
    <script>
        var div = document.querySelector('div');
        div.addEventListener('click', function () {
            animate(div, 400);
        })
    </script>
</body>

</html>

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();
            }
        }
        // 
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15)
}

mouseenter和mouseover的区别

mouseenter鼠标事件

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

常见网页特效案例

网页轮播图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值