一、元素偏移量 offset 系列
offset 偏移量,相关属性可以动态获取元素的位置、大小等
ie9+ 以上才支持
注意:返回的数值都不带单位
1、属性
<div class="box">
<div class="box-in"></div>
</div>
<script type="text/javascript">
var box = document.querySelector('.box');
// 1.offsetLeft 属性
console.log(box.offsetLeft); //相对于父元素(带有定位的)左侧的距离,都没有定位就相对于body
console.log(box.children[0].offsetLeft);
// 2.offsetTop 属性
console.log(box.offsetTop); //相对于父元素(带有定位的)上侧的距离,都没有定位就相对于body
// 3.offsetWidth 属性
console.log(box.offsetWidth); //获取元素实际宽度(width + border + padding)
// 4.offsetHeight 属性
console.log(box.offsetHeight); //获取元素实际高度(height + border + padding)
// 5.offsetParent 属性
console.log(box.offsetParent); //获取父元素(带有定位的),都没有定位就获取到的是body
console.log(box.children[0].offsetParent);
</script>
2、offset 与 style 获取宽高的区别
① style 只能获取行内样式,offset 可以获取任意样式
② style 获取的值是 width,offset 获取的值是 width + height + padding
③ style 获取的是带单位的字符串,offset 获取的是不带单位的数值
④ style 属性可以获取也可以赋值,offset 只能获取不能赋值
总结:想获取元素大小、位置用 offset 更合适,想修改大小、位置用 style 更合适
二、元素可视区 client 系列
client 客户端,相关属性可以动态得到该元素的边框大小、元素大小
ie9+ 以上才支持
注意:返回的数值都不带单位
<div class="box"></div>
<script type="text/javascript">
var box = document.querySelector('.box');
// 1.clientLeft 属性
console.log(box.clientLeft); //获取元素左边框大小
// 2.clientTop 属性
console.log(box.clientTop); //获取元素上边框大小
// 3.clientWidth 属性
console.log(box.clientWidth); //获取宽度 width + padding(不含 border)
// 4.clientHeight 属性
console.log(box.clientHeight); //获取高度 height + padding(不含 border)
</script>
三、元素滚动 scroll 系列
scroll 滚动的,相关属性可以动态得到该元素的大小、滚动距离等
ie9+ 以上才支持
注意:返回的数值都不带单位
1、属性
<div id="">
我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容
我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容我是内容
</div>
<script type="text/javascript">
var div = document.querySelector('div');
//1.scrollLeft 属性
div.addEventListener('scroll', function() { //onscroll事件
console.log(div.scrollLeft); //左侧被卷去的距离
})
//2.scrollTop 属性
div.addEventListener('scroll', function() {
console.log(div.scrollTop); //上侧被卷去的距离
})
//3.scrollWidth 属性
console.log(div.scrollWidth); //获取宽度 width + padding(不含 border)
//4.scrollHeight 属性
console.log(div.scrollHeight); //获取高度 height + padding(不含 border)
</script>
2、scroll 与 client 获取宽高的区别
- scroll 的 width + padding 里的width包含溢出内容
- client 是里的width指定的 width
3、网页滚动
- 页面上侧被卷去的距离用 window.pageYOffset 和 window.pageXOffset 获取;
- 网页 oncroll 滚动事件的事件源是页面 document
4、三大系列总结
- 获取元素位置:offsetLeft、offsetTop
- 获取元素大小:clientWidth、clientHeight
- 获取滚动距离:scrollTop、scrollLeft
5、mouseover 和 mouseenter 区别
- mouseover 经过自身和子盒子都会触发,mouseenter 经过自身触发,经过子盒子不会触发;
- 之所以这样是因为 mouseenter 不会冒泡;
- 跟 mouseenter 搭配的鼠标离开事件 mouseleave 同样不会冒泡
四、动画函数封装
1、动画
核心原理:动画利用定时器setInterval()和定位不断移动盒子位置
例如:
<div></div>
<script type="text/javascript">
var div = document.querySelector('div');
var time = setInterval(function(){ //用定时器不断重复这个操作
div.style.left = div.offsetLeft + 1 + 'px'; //让盒子在当前位置加上1个移动距离 盒子需要添加定位
if (div.offsetLeft > 1000) { //结束定时器的条件
clearInterval(time);
}
}, 100);
</script>
2、动画函数的封装
将动画封装成动画函数
例如:
<div></div>
<script type="text/javascript">
function animate(obj, target) { //传入目标对象obj 目标位置target
var time = setInterval(function(){
obj.style.left = obj.offsetLeft + 1 + 'px';
if (obj.offsetLeft > target) {
clearInterval(time);
}
}, 10);
}
var div = document.querySelector('div');
animate(div, 600);
</script>
3、动画函数封装的优化
(1)存在的问题
① 每调用一次 animate() 函数,就会开辟一个新的内存空间(因为 var 会开辟空间)
② 每个目标对象的定时器名称都相同,都是 time
③ 如果控制动画的开启,比如一个 button,如果点击多次,那么动画会越来越快(因为一个动画函数是持续一段时间的,多次点击会有多个计时器叠加,效果也就叠加了)
(2)解决
<div></div>
<button type="button">开启动画</button>
<script type="text/javascript">
function animate(obj, target) {
clearInterval(obj.timer); //清除掉以前的定时器
obj.timer = setInterval(function(){ //采用给对象添加属性的方法给定时器命名
obj.style.left = obj.offsetLeft + 1 + 'px';
if (obj.offsetLeft > target) {
clearInterval(obj.timer);
}
}, 10);
}
var div = document.querySelector('div');
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
animate(div, 600);
})
</script>
4、缓动动画
(1) 概念
就是让元素运动速度有所变化,最常见的是让速度慢下来
(2)核心原理
让盒子每次移动的距离变小,速度就会慢下来
(3)算法
(目标位置 - 当前位置 ) / 10 作为每次移动的距离
(4)停止的条件
盒子当前位置等于目标位置时,停止计时器
(5)实现
<div></div>
<button type="button">开启动画</button>
<script type="text/javascript">
function animate(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var step = (target - obj.offsetLeft) / 10; //(目标位置 - 当前位置 ) / 10 作为每次移动的距离
obj.style.left = obj.offsetLeft + step + 'px';
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
}, 15);
}
var div = document.querySelector('div');
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
animate(div, 500);
})
</script>
(6)存在的问题
当步长出现小数,就不能到达精准的位置,解决方式如下:
- 如果正向走(步长为正),向上取整 Math.ceil()
- 如果反向走(步长为负),向下取整 Math.floor()
<div></div>
<button type="button" class="btn500">500px位置</button>
<button type="button" class="btn800">800px位置</button>
<script type="text/javascript">
function animate(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var step = (target - obj.offsetLeft) / 10;
var step = step > 0 ? Math.ceil(step) : Math.floor(step);
obj.style.left = obj.offsetLeft + step + 'px';
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
}, 15);
}
var div = document.querySelector('div');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function() {
animate(div, 500);
})
btn800.addEventListener('click', function() {
animate(div, 800);
})
</script>
(7)缓动动画添加回调函数
回调函数原理:将函数 B 作为参数传到函数 A 里,当 A 执行完之后再执行函数 B,这个过程叫做回调,函数 B 称作回调函数
回调函数写的位置:定时器结束的位置
<div></div>
<button type="button" class="btn500">500px位置</button>
<button type="button" class="btn800">800px位置</button>
<script type="text/javascript">
function animate(obj, target, callback) { //形参 传入回调函数
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var step = (target - obj.offsetLeft) / 10;
var step = step > 0 ? Math.ceil(step) : Math.floor(step);
obj.style.left = obj.offsetLeft + step + 'px';
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
if (callback) { //判断是否传入回调函数,回调函数写在定时器结束的位置
callback();//执行回调函数
}
}
}, 15);
}
var div = document.querySelector('div');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click', function() {
animate(div, 500);
})
btn800.addEventListener('click', function() {
animate(div, 800, function() { //实参 传入回调函数
div.style.backgroundColor = 'mediumpurple';
});
})
</script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通