目录
1. 元素偏移量offset系列
使用offset系列相关属性可以动态的得到该元素的位置(偏移量)、大小等。
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
- 注意:返回的数值都不带单位
1)offset系列属性
<style>
* {
padding: 0;
margin: 0;
}
.father {
/* position: relative; */
width: 200px;
height: 200px;
background-color: pink;
margin: 100px;
}
.son {
width: 50px;
height: 50px;
margin: 0 50px;
background-color: purple;
}
.w {
width: 200px;
height: 200px;
margin: auto;
padding: 10px;
border: 2px solid red;
background-color: skyblue;
}
</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');
console.log(father.offsetTop);
console.log(father.offsetLeft);
//父元素带有相对定位的为准,如果父元素没有定位则以body为准
console.log(son.offsetTop);
console.log(son.offsetLeft);
var w = document.querySelector('.w');
//得到元素的大小但是宽度、高度包含padding + border + width/height
console.log(w.offsetWidth);
console.log(w.offsetHeight);
//返回带有定位的父亲,如果父元素没有定位则返回body
console.log(son.offsetParent);
//返回的是最近一级的父亲,不管父元素有无定位
console.log(son.parentNode);
</script>
</body>
结果为:
2)offset与style区别
<style>
.box {
width: 200px;
height: 200px;
padding: 10px;
background-color: pink;
}
</style>
</head>
<body>
<!-- style只能得到行内样式表中的样式值 -->
<div class="box" style="width: 200px;"></div>
<script>
var box = document.querySelector('.box');
//包含padding + border + width
console.log(box.offsetWidth);
//只包含width
console.log(box.style.width);
// 可以用style直接更改属性值
box.style.width = '300px';
</script>
</body>
结果为:
2. 元素可视区client系列
client就是客户端,使用client系列的相关属性来获取元素可视区的相关信息,可以动态的得到该元素的边框大小、元素大小等。
1)client系列属性
2)立即执行函数
<body>
<script>
function fn() {
console.log(1);
}
fn();
//1.立即执行函数:不需要调用,能够立马执行的函数
//2.写法: (function() {})(); 或 (function(){} ());
//3.可以传递参数
//4.独立创建了一个作用域,里面所有的变量都是局部变量,所以不会有命名冲突的情况
(function(a, b) {
var num = 1; //局部变量
console.log(2);
console.log(a + b);
})(1, 2);
(function(a, b) {
console.log(3);
console.log(a * b);
}(1, 2));
</script>
</body>
结果为:
3. 元素滚动scroll系列
scroll就是滚动的,使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等。
1)scroll系列属性
2)页面被卷去的头部兼容性解决方案
三大系列总结
- offset系列经常用于获得元素位置 offsetLeft offsetTop
- client系列经常用于获取元素大小 clientWidth clientHeight
- scroll系列经常用于获取滚动距离 scrollTop scrollLeft
- 页面滚动的距离通过 window.pageXoffset 获得
mouseenter和mouseover的区别
mouseenter鼠标事件
- 当鼠标移动到元素上时就会触发mouseenter时间
- mouseover鼠标经过自身盒子会触发,经过子盒子还会触发;mouseenter只会经过自身盒子触发
- 是因为mouseenter不会冒泡
- 跟mouseenter搭配,鼠标离开mouseleave,同样不会冒泡
<style>
.father {
width: 300px;
height: 300px;
background-color: pink;
}
.son {
width: 100px;
height: 100px;
background-color: purple;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
//mouseover会冒泡
//当鼠标经过father时输出一次 1
//当鼠标经过son时通过冒泡 会再返回father 因此再输出一次 1
father.addEventListener('mouseover',function() {
console.log(1);
})
</script>
</body>
结果为:
<style>
.father {
width: 300px;
height: 300px;
background-color: pink;
}
.son {
width: 100px;
height: 100px;
background-color: purple;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
//mouseenter不会冒泡
//当鼠标经过father时输出一次 1
//当鼠标经过son时由于不会冒泡 因此不输出1
father.addEventListener('mouseenter',function() {
console.log(1);
})
</script>
</body>
结果为:
4. 动画函数封装
1)动画实现原理
核心原理:通过定时器setInterval()不断移动盒子位置
实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 此元素还需要添加定位,才能使用element.style.left
<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 >= 600) {
//停止动画,本质:停止定时器
clearInterval(timer);
}
div.style.left = div.offsetLeft + 5 + 'px';
},30);
</script>
</body>
结果为:
2)动画函数简单封装
函数需要传递2个参数,动画对象和移动到的距离。
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}
span {
display: block;
position: absolute;
left: 0;
top: 150px;
width: 200px;
height: 200px;
background-color: purple;
}
</style>
</head>
<body>
<div></div>
<span></span>
<script>
//简单动画函数封装 动画对象obj 目标位置target
function animation(obj, target) {
var timer = setInterval(function() {
if(obj.offsetLeft >= target) {
//停止动画,本质:停止定时器
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
},30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
animation(div, 600);
animation(span, 500);
</script>
</body>
结果为:
3)动画函数给不同元素记录不同定时器
如果多个元素都使用这个动画函数,每次都要var声明定时器,可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
核心原理:利用JS是一门动态语言,可以很方便的给当前对象添加属性。
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}
span {
display: block;
position: absolute;
left: 0;
top: 150px;
width: 200px;
height: 200px;
background-color: purple;
}
</style>
</head>
<body>
<button>点击按钮之后span才走</button>
<div></div>
<span>span</span>
<script>
//var obj = {}
//obj.name = '';
//简单动画函数封装 动画对象obj 目标位置target
function animation(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');
animation(div, 600);
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
//当我们不断点击按钮,这个动画的移动速度会越来越快
//解决方案:让元素只有一个定时器
animation(span, 500);
})
</script>
</body>
结果为:
4)缓动动画效果原理
缓动动画就是让元素运动速度有所变化,最常见的事让速度慢慢停下来
匀速动画:盒子当前的位置 + 固定的值
缓动动画:盒子当前的位置 + 变化的值(目标值 - 现在的位置)/ 10
思路:
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
- 核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
- 停止的条件是:让当前盒子位置等于目标位置就停止计时器
- 注意步长需要取整
<style>
span {
display: block;
position: absolute;
left: 0;
top: 150px;
width: 200px;
height: 200px;
background-color: purple;
}
</style>
</head>
<body>
<button>点击按钮之后span才走</button>
<span>span</span>
<script>
// 1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
// 2.核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
// 3.停止的条件是:让当前盒子位置等于目标位置就停止计时器
function animation(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
var step = Math.ceil((target - obj.offsetLeft) / 10);
if(obj.offsetLeft == target) {
//停止动画,本质:停止定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
},15);
}
var btn = document.querySelector('button');
var span = document.querySelector('span');
btn.addEventListener('click', function() {
animation(span, 600);
})
</script>
</body>
结果为:
5) 缓动动画多个目标值之间移动
<style>
span {
display: block;
position: absolute;
left: 0;
top: 150px;
width: 200px;
height: 200px;
background-color: purple;
}
</style>
</head>
<body>
<button class="btn500">点击按钮之后走到500px</button>
<button class="btn800">点击按钮之后走到800px</button>
<span>span</span>
<script>
// 1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
// 2.核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
// 3.停止的条件是:让当前盒子位置等于目标位置就停止计时器
function animation(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//核心算法:(目标值 - 现在的位置)/ 10,作为每次移动的距离步长
var step = (target - obj.offsetLeft) / 10;
//步长需要取整 8.1 -> 9 -8.1 -> -8
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 btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
var span = document.querySelector('span');
btn500.addEventListener('click', function() {
animation(span, 500);
});
btn800.addEventListener('click', function() {
animation(span, 800);
});
</script>
</body>
结果为:
6)动画函数添加回调函数
回调函数原理:函数可以作为一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完毕之后,再执行传进去的这个函数,这个过程就叫做回调。
回调函数写在定时器结束里面
<style>
span {
display: block;
position: absolute;
left: 0;
top: 150px;
width: 200px;
height: 200px;
background-color: purple;
}
</style>
</head>
<body>
<button class="btn500">点击按钮之后走到500px</button>
<button class="btn800">点击按钮之后走到800px</button>
<span>span</span>
<script>
function animation(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 btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
var span = document.querySelector('span');
btn500.addEventListener('click', function() {
animation(span, 500,function() {
span.style.backgroundColor = 'skyblue';
});
});
btn800.addEventListener('click', function() {
animation(span, 800, function() {
span.style.backgroundColor = 'red';
});
});
</script>
</body>
结果为:
7)动画函数封装到单独JS文件里面
由于经常使用这个动画函数,可以单独封装到一个JS文件里面,使用的时候引用这个JS文件即可。
- 单独新建一个JS文件
5. 节流阀
防止轮播图按钮连续点击造成播放过快。
目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路:
- 利用回调函数,添加一个变量来控制,锁住函数和解锁函数
- 开始设置一个变量 var flag = true;
- if(flag){ falg = false; do something } //关闭水龙头
- 利用回调函数,动画执行完毕,flag = true,打开水龙头