JavaScript:pc端网页特效--元素偏移量offset系列
1.offset概述
offset翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
- 获取元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
- 注意:返回的值都不带单位
offset系列常用属性:
offset系列属性 | 作用 |
---|---|
element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素左边框的偏移 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
(1)element.offsetTop和element.offsetLeft
对于一个div盒子
<div class="father"><div class="son"></div>
</div>
先给它设置一个css样式:
.father {width: 200px;height: 200px;background-color: pink;margin: 100px;
}
.son {width: 100px;height: 100px;background-color: goldenrod;margin-left: 45px;
}
然后再定义div,最后可以试着输出一下element.offsetTop和element.offsetLeft:
var father = document.querySelector('.father');
var son = document.querySelector('.son');
console.log(father.offsetTop);
console.log(father.offsetLeft);
console.log(son.offsetLeft);
最后输出的结果输出的是距离body的偏移,因为我们的父级没有定位或者盒子没有父亲,直接输出与body的相对偏移
(2)element.offsetWidth和element.offsetHeight
也可以用element.offsetWidth和element.offsetHeight得到元素的宽度和高度
console.log(son.offsetWidth);
console.log(son.offsetHeight);
注意:这个宽度和高度也包含padding和border
(3)element.offsetParent
console.log(son.offsetParent);
如果.farther没有定位,则返回body
如果.farther有定位,则返回.son的父元素.father
2.offset与style区别
offset | style |
---|---|
offset可以得到任何样式表中的样式值 | style只能得到行内样式表中的样式值 |
offset系列获得的数值是没有单位的 | style.width获得的是带有单位的字符串 |
offsetWidth包含padding+border+width | style.width活动不包含padding和border的值 |
offsetWidth等属性自身只读属性,只能获取不能赋值 | style.width是可读写属性,可以获取也可以赋值 |
如果想获取元素大小位置,用offset更合适 | 如果想给元素更改值,需要用style改变 |
案例:获取鼠标在盒子里的坐标
我们首先设置好盒子以及盒子的样式
<div class="box"></div>
.box {width: 200px;height: 200px;background-color: pink;margin: 100px;
}
然后我们来写直接获取鼠标在盒子里的坐标的JS
按理说我们不能直接得到鼠标在盒子里的坐标,但是我们可以得到鼠标相对页面的坐标,也能得到盒子边缘距离页面的坐标,然后再把它俩相减就可以得到啦,代码实现如下:
var box = document.querySelector('.box');
box.addEventListener('mousemove', function (e) {var x = e.pageX - box.offsetLeft;var y = e.pageY - box.offsetTop;this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
})
我们来做案例来更深入地体验一下它们之间的差异性吧~
案例:模态框拖拽
我们想做一个这样的登录界面
点击“登录会员”后就出现遮罩层,我们可以任意拖动这个遮罩层移动
我们先来搭建基本框架
<div class="login-header"><a href="javascript:;" id="link">点击登录会员</a></div>
<div class="login" id="login"><div class="login-title" id="title"><p>登录会员</p><span><a href="javascript:;" id="closeBtn" class="close-login">关闭</a></span></div><div class="login-input-content"><div class="login-input"><label for="username">用户名:</label><input type="text" placeholder="请输入用户名" id="username" name="info[username]" class="login-username"></div><div class="login-input"><label for="password">密码:</label><input type="password" placeholder="请输入密码" id="password" name="info[password]" class="login-password"></div></div><div class="login-button" id="loginBtn"><a href="javascript:void(0);" id="login-button-submit">登录</a></div>
</div><!-- 遮盖层 -->
<div class="login-bg" id="bg"></div>
然后再用css给它装饰一下
* {padding: 0;margin: 0;
}a {color: #000;text-decoration: none;display: inline-block;
}.login-header {position: fixed;top: 20px;left: 50%;font-size: 18px;transform: translateX(-50%);
}.login {display: none;width: 520px;height: 270px;position: fixed;border: #ebebeb solid 1px;left: 50%;top: 50%;background: #fff;box-shadow: 0px 0px 20px #ddd;z-index: 9999;transform: translate(-50%, -50%);
}.login-title {width: 100%;margin: 10px 0px 0px 0px;text-align: center;line-height: 40px;height: 109px;font-size: 18px;position: relative;border: none;
}.login-title span {position: absolute;right: -11px;top: -30px;font-size: 12px;background: #fff;border: #ebebeb solid 1px;width: 30px;height: 30px;border-radius: 50%;text-align: center;
}.login-title span a {position: absolute;left: 0px;line-height: 30px;height: 30px;width: 30px;
}.login-title p {position: relative;top: 13px;left: 0;
}.login-input-content {margin-top: -20px;margin-left: 40px;
}.login-input {overflow: hidden;margin: 0px 0px 20px 0px;
}.login-input label {float: left;width: 90px;padding-right: 10px;text-align: right;line-height: 35px;font-size: 14px;
}.login-input input {height: 30px;width: 281px;border: 1px solid #ebebeb;padding: 0 5px;
}.login-input input.list-input {float: left;line-height: 35px;height: 35px;width: 35px;border: #ebebeb 1px solid;
}.login-button {width: 75px;margin: 22px auto 0px auto;line-height: 40px;font-size: 14px;border: 1px solid #ebebeb;border-radius: 21px;text-align: center;
}.login-button a {display: block;
}.login-bg {display: none;width: 100%;height: 100%;position: fixed;top: 0;left: 0;background: rgba(0, 0, 0, .3);
}
接下来就是我们重点看怎么用JS来实现功能啦
我们先来将我们一会要用的名称定义好
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector('#closeBtn');
var title = document.querySelector('#title');
先加上点击“点击登录会员”显示遮罩层和点击“关闭”来隐藏遮罩层
link.addEventListener('click', function () {mask.style.display = 'block';login.style.display = 'block';
})
closeBtn.addEventListener('click', function () {mask.style.display = 'none';login.style.display = 'none';
})
接下来就是实现拖动遮罩层啦
先定义isDraggin,用来判断是否在移动遮罩层,定义offsetX,和offsetY来记录鼠标点击位置与登录框左上角的偏移量
var isDragging = false;
var offsetX, offsetY;
给title绑定一个监听器,鼠标按下后就来显示鼠标点击位置与登录框左上角的偏移量,在这里面要记得把isDraggin设置成true,表明正处于移动中
title.addEventListener('mousedown', function (e) {isDragging = true;offsetX = e.pageX - login.offsetLeft;offsetY = e.pageY - login.offsetTop;
});
然后要让登录框跟着鼠标移动,并且是在整个页面里移动,所以给document设置mousemove类型的监听器,实时更新登录框在页面的位置,从而达到拖动登录框的目的
document.addEventListener('mousemove', function (e) {if (isDragging) {login.style.left = (e.pageX - offsetX) + 'px';login.style.top = (e.pageY - offsetY) + 'px';}
});
最后不要忘记解除移动状态,不然登录框就bia在鼠标上,一直跟着鼠标走啦,设置mouseup类型的监听器,将isDraggin设置成false,这样登录框就不会再跟着鼠标走啦
document.addEventListener('mouseup', function () {isDragging = false;
});