目录
一、offset
1-1、offset系列属性
1-2、offset与style区别
1-3、案例
1-3-1、计算鼠标在盒子内的坐标
1-3-2、拖动模态框
二、client
2-1、client系列属性
三、scroll
3-1、scroll系列属性
3-2、案例
3-2-1、滚动页面一定距离后固定侧边栏
一、offset
offset是偏移量,使用offset系列相关属性可以动态得到元素的位置(偏移)、大小等,可获得:
- 元素距离带有定位父元素的位置
- 元素自身的宽度、高度
注意:返回的数值不带单位
1-1、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 {
position: relative;
width: 200px;
height: 200px;
background-color: pink;
margin: 150px;
}
.son {
width: 100px;
height: 100px;
background-color: purple;
margin-left: 45px;
}
.w {
height: 200px;
width: 200px;
background-color: skyblue;
margin: 0 auto 200px;
padding: 10px;
border: 15px solid orange;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<div class="w"></div>
<script>
// offset 系列
var father = document.querySelector('.father');
var son = document.querySelector('.son');
// 1.可以得到元素的偏移 位置 返回的不带单位的数值
console.log(father.offsetTop);// 150
console.log(father.offsetLeft);// 150
// 它以带有定位的父亲为准
// 没有父亲或者父亲没有定位 则以 body 为准,为195
console.log(son.offsetLeft);// 45
var w = document.querySelector('.w');
// 2.可以得到元素的大小 宽度和高度 是包含padding + border + width
// 200 + 15*2 + 10*2
console.log(w.offsetWidth);// 250
console.log(w.offsetHeight); // 250
// 3. 返回带有定位的父亲 否则返回的是body
console.log(son.offsetParent); // 返回带有定位的父亲 否则返回的是body
console.log(son.parentNode); // 返回父亲 是最近一级的父亲 亲爸爸 不管父亲有没有定位
</script>
</body>
</html>
1-2、offset与style区别
- offset
- offset系列获得的数值是没有单位的
- offsetWidth包含padding+border+width
- offsetWidth等属性是只读属性,只能获取不能赋值
- style
- style.width获得的是带有单位的字符串
- style.width获得不包含padding和border的值
- style.width是可读可写属性,可以获取也可以赋值
所以:
- 想要获取元素大小位置,用offset更合适
- 想要给元素更改值,用style更合适
<!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>
.box {
width: 200px;
height: 200px;
background-color: pink;
padding: 10px;
}
</style>
</head>
<body>
<div class="box" style="width: 200px;"></div>
<script>
// offset与style的区别
var box = document.querySelector('.box');
console.log(box.offsetWidth); // 200 + 10*2 = 220
console.log(box.style.width); // 200px
box.style.width = '300px'; // 可利用style去设置值
</script>
</body>
</html>
1-3、案例
1-3-1、计算鼠标在盒子内的坐标
原理: 使用鼠标在页面中的坐标(pageX,pageY) - 盒子在页面中的偏移量(offsetLeft,offsetTop)
<!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>
.box {
width: 300px;
height: 300px;
background-color: pink;
margin: 200px;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
// 我们在盒子内点击, 想要得到鼠标距离盒子左右的距离。
// 首先得到鼠标在页面中的坐标( e.pageX, e.pageY)
// 其次得到盒子在页面中的距离(box.offsetLeft, box.offsetTop)
// 用鼠标距离页面的坐标减去盒子在页面中的距离, 得到 鼠标在盒子内的坐标
const box = document.querySelector('.box');
box.addEventListener('mousemove', function (e) {
// console.log(e.pageX);
// console.log(e.pageY);
// console.log(box.offsetLeft);
const x = e.pageX - this.offsetLeft;
const y = e.pageY - this.offsetTop;
this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
})
</script>
</body>
</html>
1-3-2、拖动模态框
原理:
-
当鼠标按下时(mousedown)拿到鼠标在模态框内的坐标下x,y(原理为1-3-1)
-
当鼠标拖动模态框开始移动时(mousemove),分别给模态框的left与top赋值:
- 模态框的left值为 鼠标距离页面左侧的距离 (pageX)- 鼠标在模态框的横坐标(x)
- 模态框的top值为 鼠标距离页面顶部的距离(pageY)- 鼠标在模态框的纵坐标(y)
-
当鼠标抬起时(mouseup),移除鼠标移动事件
<!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>
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color: #000;
}
.show-modal {
width: 100%;
text-align: center;
font-size: 24px;
cursor: pointer;
}
.login {
/*刚开始隐藏起来*/
display: none;
position: fixed;
width: 520px;
height: 290px;
border: 1px solid #ccc;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: #fff;
box-shadow: 0 0 20px #ddd;
z-index: 9999;
}
.login-title {
position: relative;
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 18px;
cursor: move;
}
.login-title span {
position: absolute;
width: 40px;
height: 40px;
right: -20px;
top: -30px;
border-radius: 50%;
font-size: 12px;
background: #fff;
border: 1px solid #ccc;
}
.login-content {
padding: 10px;
height: 180px;
}
.login-content-input {
display: flex;
}
.login-content-input label {
width: 100px;
text-align: right;
}
.login-content-input input {
width: 350px;
height: 35px;
line-height: 35px;
border: 1px solid #ccc;
margin-bottom: 20px;
}
.login-btn {
width: 100%;
height: 50px;
line-height: 50px;
display: block;
text-align: center;
font-size: 18px;
border-top: 1px solid #ccc;
}
.login-mask {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, .3);
}
</style>
</head>
<body>
<div class="show-modal">点击展示模态框</div>
<!--模态框-->
<div class="login">
<div class="login-title">
用户登录
<span><a class="close-btn" href="#">关闭</a></span>
</div>
<div class="login-content">
<div class="login-content-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名">
</div>
<div class="login-content-input">
<label>密码:</label>
<input type="password" placeholder="请输入密码">
</div>
</div>
<div><a href="#" class="login-btn">登录</a></div>
</div>
<!--模态框遮罩-->
<div class="login-mask"></div>
</body>
<script>
const showLogin = document.querySelector('.show-modal');
const login = document.querySelector('.login');
const mask = document.querySelector('.login-mask');
const closeBtn = document.querySelector('.close-btn');
const title = document.querySelector('.login-title');
// 点击展示模态框
showLogin.addEventListener('click', function () {
mask.style.display = 'block'; // 展示遮罩
login.style.display = 'block'; // 展示模态窗
})
// 点击关闭按钮关闭模态框
closeBtn.addEventListener('click', function () {
mask.style.display = 'none';
login.style.display = 'none';
})
// 拖拽模态框, 按住标题区域开始拖拽
title.addEventListener('mousedown', function (e) {
// 1 先获取一下鼠标在模态框内的坐标
// 鼠标在页面上的坐标 - 模态框距离页面顶部/上部的距离
const x = e.pageX - login.offsetLeft;
const y = e.pageY - login.offsetTop;
// 鼠标移动的监听事件加到document上,方式移动过快甩出模态框
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', move);
});
// 模态框现在的位置 = 鼠标在页面上的坐标 - 鼠标在模态框内的坐标
function move(e) {
// !!特别注意要加上px
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
}
});
</script>
</html>
二、client
使用client系列的相关属性可获取元素可视区的相关信息,可动态得到元素的边框大小、元素大小等。
2-1、client系列属性
client系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不包含边框 |
element.clientHeight | 返回自身包括padding、内容区的高度,不包含边框 |
注意:
-
client系列获取的内容也不包含单位
-
clientWidth、clientHeight与offsetWidth、offsetHeight不同的是:
- offsetWidth、offsetHeight获取的宽高为:padding + 内容区 + 边框
- clientWidth、clientHeight获取的宽高为: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>
div {
width: 200px;
height: 200px;
background-color: skyblue;
border: 10px solid orange;
padding: 10px;
}
</style>
</head>
<body>
<div></div>
<script>
// client 宽度 和我们offsetWidth 最大的区别就是 不包含边框
var div = document.querySelector('div');
console.log(div.clientWidth); // 200 + 10* 20 = 220
console.log(div.clientTop); // 10
</script>
</body>
</html>
三、scroll
使用scroll系列的线管属性可以动态得到元素的大小、滚动距离等。
3-1、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;
background-color: skyblue;
border: 10px solid orange;
padding: 10px;
overflow: auto;
}
</style>
</head>
<body>
<div>
我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
</div>
<script>
// scroll 系列
var div = document.querySelector('div');
console.log(div.scrollHeight); // 314 内容的实际高度
console.log(div.clientHeight); // 200 + 10* 2 = 220
// scroll滚动事件当我们滚动条发生变化会触发的事件
div.addEventListener('scroll', function () {
console.log(div.scrollTop);
})
</script>
</body>
</html>
3-2、案例
3-2-1、滚动页面一定距离后固定侧边栏
实现效果:侧边栏刚开始为相对定位,当页面滚动到一定距离后改为绝对定位并显示返回顶部按钮
原理:
- 首先确定页面需滚动的距离(滚动多少后侧边栏固定),以及侧边栏需要固定的位置
- 给页面添加监听页面滚动的事件,在事件中获取页面被卷去的距离(页面被卷去的距离通过:window.pageYOffset、window.pageXOffset获取)
- 如果卷去的距离大于等于设定的距离那么就固定侧边栏,将侧边栏固定到所需要固定的位置
<!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>
.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>
</head>
<body>
<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. 获取元素
const sliderbar = document.querySelector('.slider-bar');
const banner = document.querySelector('.banner');
// banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
const bannerTop = banner.offsetTop
// 当我们侧边栏固定定位之后应该变化的数值
const sliderbarTop = sliderbar.offsetTop - bannerTop;
// 获取main 主体元素
const main = document.querySelector('.main');
const goBack = document.querySelector('.goBack');
const mainTop = main.offsetTop;
// 2. 页面滚动事件 scroll
document.addEventListener('scroll', function () {
// console.log(11);
// window.pageYOffset 页面被卷去的头部
// 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
if (window.pageYOffset >= bannerTop) {
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop + 'px';
} else {
sliderbar.style.position = 'absolute';
sliderbar.style.top = '300px';
}
// 4. 当我们页面滚动到main盒子,就显示 goback模块
if (window.pageYOffset >= mainTop) {
goBack.style.display = 'block';
} else {
goBack.style.display = 'none';
}
})
</script>
</body>
</html>