元素偏移量 offset 系列
1.1 offset概述
offset翻译就是偏移量,使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
● 获得元素举例带有定位父元素的位置
● 获得元素自身的大小(宽度高度)
● 注意:返回的数值都不带单位
offset系列常用属性
offset系列属性 | 作用 |
---|---|
element.offsetParent | 返回作为该元素带有定位的父级元素 如果父级都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素做边框的偏移 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
<!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>
* {
margin: 0;
padding: 0;
}
.father {
width: 300px;
height: 300px;
margin: 30px 0 0 30px;
background-color: tomato;
}
.son {
width: 100px;
height: 100px;
background: violet;
}
.w {
width: 200px;
height: 200px;
background-color: skyblue;
margin: 0 auto 200px;
padding: 10px;
border: 15px solid red;
}
</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');
var w = document.querySelector('.w');
//可以得到元素的偏移位置 返回的不带单位的数值
console.log(father.offsetTop);
console.log(father.offsetLeft);
//以带有定位的父级为准,如果没有父级或者父级没有定位,则以body为准
console.log(son.offsetLeft);
//可以得到元素的大小、宽度和高度,包含padding+border+width
console.log(w.offsetWidth);
console.log(w.offsetHeight);
//返回带有定位的父级,否则返回的是body
console.log(son.offsetParent);
console.log(son.parentNode);
//以上俩者区别offsetParent返回带有定位的父级,如父级没定位则返回的是body,parentNode返回最近一级的父级,不管父级是否有定位。
</script>
</body>
</html>
1.2 offset和style的区别
offset
● offset可以得到任意样式表中的样式值
● offset系列获得的数值是没有单位的
● offsetWidth包含padding+border+width
● offsetWidth等属性是只读属性,只能获取不能赋值
● 想要获取元素大小位置,用offset更合适
style
● 只能得到行内样式表中的样式值
● style.width获得的是带有单位的字符串
● style.width获得的不包含padding和border的值
● style.widht是可读写属性,可以获取也可以赋值
● 想要给元素更改值,需要用style改变
2. 元素可视区client系列
client翻译就是客户度,使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
2.1client系列属性
client系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括padding、内容区的高度,不含边框,返回数值不带单位 |
2.2 淘宝flexible.js源码解析
立即执行函数(function(){})()或者(function(){}()),第一种较常用
主要作用:创建一个独立的作用域。避免了命名冲突问题。
元素滚动scroll系列
3.1元素scroll系列属性
scroll翻译就是滚动的,使用scroll协力的相关属性可以动态的得到该元素的大小、滚动的距离等。
scroll系列属性 | 作用 |
---|---|
element.scrollTop | 返回被卷上去的上侧距离,返回数值不带单位 |
element.scrollLeft | 返回被卷上去的左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身实际的高度,不含边框,返回数值不带单位 |
<!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 {
width: 200px;
height: 200px;
overflow: auto;
}
</style>
</head>
<body>
<div>我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容</div>
<script>
//scroll系列
var div = document.querySelector('div');
console.log(div.scrollHeight);
console.log(div.clientHeight);
//scroll滚动事件当滚动条件发生变化会触发的事件
div.addEventListener('scroll', function() {
console.log(div.scrollTop);
})
</script>
</body>
</html>
mousesenter和mouseover的区别
mouseenter鼠标事件
● 当鼠标移动到院上上时就会触发mouseenter事件
● 类似mouseover,它们俩者之间的差别是:
mouseover鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会经过自身盒子触发。原因是mouseenter不会冒泡。跟mouseenter搭配鼠标离开mouseleave同样不会冒泡
动画函数封装
4.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 {
width: 100px;
height: 100px;
background-color: purple;
position: relative;
}
</style>
</head>
<body>
<div></div>
<script>
//动画原理
//1、获得盒子当前位置
//2、让盒子在当前位置机上1个移动距离
//3、利用定时器不断重复这个操作
//5、加结束定时器的条件
//6、注意此元素需要添加定位,才能使用element.style.left
var div = document.querySelector('div');
var timer = setInterval(function() {
if (div.offsetLeft >= 400) {
//停止动画 本质是停止定时器
clearInterval(timer);
}
div.style.left = div.offsetLeft + 10 + 'px';
}, 30);
</script>
</body>
</html>
4.2 动画函数简单封装
注意函数需要专递2个参数,动画对象和移动到的距离。
<!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;
top: 0;
left: 0;
width: 200px;
height: 200px;
background-color: salmon;
}
span {
position: absolute;
top: 200px;
left: 0;
width: 300px;
height: 300px;
background: skyblue;
}
</style>
</head>
<body>
<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 + 5 + 'px';
}, 30)
}
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 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;
top: 0;
left: 0;
width: 200px;
height: 200px;
background-color: salmon;
}
span {
position: absolute;
top: 200px;
left: 0;
width: 300px;
height: 300px;
background: skyblue;
}
</style>
</head>
<body>
<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 + 5 + 'px';
}, 30)
}
var div = document.querySelector('div');
var span = document.querySelector('span');
//调用函数
animate(div, 300);
animate(span, 200)
</script>
</body>
</html>
4.4 缓动效果原理
缓动动画就是让元素匀速速度有所变化,最常见的是让速度慢慢停下来
思路:
1、让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
2、核心算法:(目标值-现在的位置)/10(10可随意更改);
3、停止的条件是:让当前盒子位置等于目标位置就停止定时器。
<!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;
top: 0;
left: 0;
width: 200px;
height: 200px;
background-color: salmon;
}
span {
position: absolute;
top: 200px;
left: 0;
width: 100px;
height: 100px;
background: skyblue;
}
</style>
</head>
<body>
<button>点击走起</button>
<button>再点击再走起</button>
<span></span>
<script>
//缓动动画函数封装obj目标对象 targe目标位置
//思路:
// 1、让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
// 2、核心算法:(目标值-现在的位置)/10 作为每次移动的距离 步长
// 3、停止的条件是:让当前盒子位置等于目标位置就停止定时器
function animate(obj, target) {
clearInterval(obj.timer)
obj.timer = setInterval(function() {
//步长值写到定时器的里面
//由于(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)
}
//缓动动画 把每次加1步长值改为一个慢慢变小的值 步长公式:(目标值-现在的位置)/10
obj.style.left = obj.offsetLeft + step + 'px';
//匀速动画
//obj.style.left = obj.offsetLeft + 10 + 'px';
},
15)
}
var btn = document.querySelectorAll('button');
var span = document.querySelector('span');
//调用函数
btn[0].addEventListener('click', function() {
animate(span, 500)
});
btn[1].addEventListener('click', function() {
animate(span, 800)
});
//匀速动画 就是 盒子是当前的位置 + 固定的值
//缓动动画 就是 盒子当前的位置 + 变化的值(目标值-现在的位置)/10
</script>
</body>
</html>
4.5 动画函数添加回调函数
回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当上面函数执行外之后,再执行传进去的函数,此过程叫做回调。
<!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;
top: 0;
left: 0;
width: 200px;
height: 200px;
background-color: salmon;
}
span {
position: absolute;
top: 200px;
left: 0;
width: 100px;
height: 100px;
background: skyblue;
}
</style>
</head>
<body>
<button>点击走起</button>
<button>再点击再走起</button>
<span></span>
<script>
//缓动动画函数封装obj目标对象 targe目标位置
//思路:
// 1、让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
// 2、核心算法:(目标值-现在的位置)/10 作为每次移动的距离 步长
// 3、停止的条件是:让当前盒子位置等于目标位置就停止定时器
function animate(obj, target, callback) {
//先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长值写到定时器的里面
//由于(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();
};
};
//缓动动画 把每次加1步长值改为一个慢慢变小的值 步长公式:(目标值-现在的位置)/10
obj.style.left = obj.offsetLeft + step + 'px';
//匀速动画
//obj.style.left = obj.offsetLeft + 10 + 'px';
},
15)
}
var btn = document.querySelectorAll('button');
var span = document.querySelector('span');
//调用函数
btn[0].addEventListener('click', function() {
animate(span, 500)
});
btn[1].addEventListener('click', function() {
animate(span, 800, function() {
span.style.backgroundColor = 'red';
});
});
//匀速动画 就是 盒子是当前的位置 + 固定的值
//缓动动画 就是 盒子当前的位置 + 变化的值(目标值-现在的位置)/10
</script>
</body>
</html>
4.6 动画函数封装到单独JS文件里面
由于以后经常使用动画函数,可以单独封装到一个JS文件里面,使用的时候引用JS文件即可。
function animate(obj, target, callback) {
//先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长值写到定时器的里面
//由于(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();
};
};
//缓动动画 把每次加1步长值改为一个慢慢变小的值 步长公式:(目标值-现在的位置)/10
obj.style.left = obj.offsetLeft + step + 'px';
//匀速动画
//obj.style.left = obj.offsetLeft + 10 + 'px';
},
15)
}
5、常见网页特效案例
5.1节流阀
防止轮播图按钮连续点击造成播放过快。
节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
开始设置一个变量var flag=true; 节流阀
if(flag){flag=false; do something} 锁住函数关闭节流阀
利用回调函数动画执行完毕,flag=true 解锁函数 开启节流阀