目录
一、元素偏移量offset系列
offset概述
offset翻译过来就是偏移量,使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等
(1)获得元素距离带有定位父元素的位置。
(2)获得元素自身的大小(宽度高度)。
(3)注意:返回的数值都不带单位。
offset系列属性 | 作用 |
element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素左边框的偏移 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度。返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度。返回数值不带单位 |
offset 与 style 的区别
offset | style |
(1) offset可以得到任意样式表中的样式值 | (1) style只能得到行内样式表中的样式值 |
(2) offset系列获得的数值是没有单位的 | (2) style.width 获得的是带有单位的字符串 |
(3) offsetWidth包含padding + border + width | (3) style.width 获得不包含padding 和 border的值 |
(4) offsetWidth等属性是只读属性,只能获取不能赋值 | (4) style.width 是可读写属性,可以获取也可以赋值 |
所以:获取用offset,修改用style。
<style>
* {
/* margin: 0; */
}
.box {
width: 150px;
height: 150px;
background-color: pink;
}
.con {
position: absolute;
padding: 15px;
}
</style>
<body>
<div class="con">
<div class="box">
</div>
</div>
<script>
var box = document.querySelector('.box');
// offsetLeft、Top、width、height要求父元素带有定位,没有定位父元素返回距离body的距离
console.log(box.offsetLeft); // 返回左方距离 15
console.log(box.offsetTop); // 返回上方距离 15
console.log(box.offsetWidth); // 返回实际宽度 150
console.log(box.offsetHeight); // 返回实际高度 150
console.log(box.offsetParent); // 返回定位父元素,没有定位父元素返回body div.con
</script>
</body>
案例:获取鼠标在盒子内的坐标
<style>
.box {
width: 150px;
height: 150px;
background-color: pink;
font-size: 14px;
text-align: center;
}
</style>
<body>
<div class="box">
</div>
<script>
/**
* 1、需要获取盒子
* 2、需要用到鼠标移动事件 onmousemove
* 3、鼠标在盒子的位置 = 鼠标距离页面的距离 - 盒子距离body的距离;
* 4、鼠标距离文档页面的距离需要用到事件对象e,属性:e.pageX、e.pageY
* 5、盒子距离body的距离,offsetTop、offsetLeft
*/
var box = document.querySelector('.box');
box.onmousemove = function (e) {
var x = e.pageX - this.offsetLeft; // X坐标
var y = e.pageY - this.offsetTop; // Y坐标
this.innerHTML = 'X坐标:' + x + ' Y坐标:' + y;
}
</script>
</body>
效果:
案例:模态框拖拽
<style>
.login-header {
width: 100%;
text-align: center;
height: 30px;
font-size: 24px;
line-height: 30px;
}
ul,
li,
ol,
dl,
dt,
dd,
div,
p,
span,
h1,
h2,
h3,
h4,
h5,
h6,
a {
padding: 0px;
margin: 0px;
}
.login {
display: none;
width: 512px;
height: 280px;
position: fixed;
border: #ebebeb solid 1px;
left: 50%;
top: 50%;
background: #ffffff;
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: 40px;
font-size: 18px;
position: relative;
cursor: move;
}
.login-input-content {
margin-top: 20px;
}
.login-button {
width: 50%;
margin: 30px auto 0px auto;
line-height: 40px;
font-size: 14px;
border: #ebebeb 1px solid;
text-align: center;
}
.login-bg {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, .3);
}
a {
text-decoration: none;
color: #000000;
}
.login-button a {
display: block;
}
.login-input input.list-input {
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: #ebebeb 1px solid;
text-indent: 5px;
}
.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;
height: 35px;
font-size: 14px;
}
.login-title span {
position: absolute;
font-size: 12px;
right: -20px;
top: -30px;
background: #ffffff;
border: #ebebeb solid 1px;
width: 40px;
height: 40px;
border-radius: 20px;
}
</style>
<body>
<div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
<div id="login" class="login">
<div id="title" class="login-title">登录会员
<span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
</div>
<!-- 遮盖层 -->
<div id="bg" class="login-bg"></div>
<script>
/**
* 案例分析:
* 1. 点击弹出层, 模态框和遮挡层就会显示出来 display:block;
2. 点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;
3. 在页面中拖拽的原理:鼠标按下并且移动, 之后松开鼠标
4. 触发事件是鼠标按下mousedown,鼠标移动mousemove 鼠标松开 mouseup
5. 拖拽过程: 鼠标移动过程中,获得最新的值赋值给模态框的left和top值,这样模态框可以跟着鼠标走了
6. 鼠标按下触发的事件源是最上面一行,就是 id 为 title
7. 鼠标的坐标减去 鼠标在盒子内的坐标, 才是模态框真正的位置。
8. 鼠标按下,我们要得到鼠标在盒子的坐标。
9. 鼠标移动,就让模态框的坐标 设置为 :鼠标坐标 减去盒子坐标即可,注意移动事件写到按下事件里面。
10. 鼠标松开,就停止拖拽,就是可以让鼠标移动事件解除
*/
// 1、点击弹出层, 模态框和遮挡层就会显示出来 display:block;
var link = document.querySelector('#link');
var bg = document.querySelector('#bg');
var login = document.querySelector('#login')
link.onclick = function () {
bg.style.display = 'block';
login.style.display = 'block';
}
// 2、点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;
var cloneBtn = document.querySelector('#closeBtn');
cloneBtn.onclick = function () {
bg.style.display = 'none';
login.style.display = 'none';
}
//
var title = document.querySelector('#title')
// (1) 点击
title.onmousedown = function (e) {
// 鼠标在盒子内的坐标
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
// (2) 开始拖动
document.addEventListener('mousemove', move);
function move(e) {
// login盒子的left、top值 = 鼠标距离页面文档的距离 - 鼠标在盒子的距离
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
}
// (3) 松开鼠标时,删除监听器
document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', move);
})
}
</script>
</body>
效果:
案例:仿京东放大镜
<style>
.move-box {
position: relative;
width: 300px;
height: 400px;
border: 1px solid #000;
}
.move-box img {
width: 100%;
}
.big {
display: none;
position: fixed;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 400px;
height: 500px;
overflow: hidden;
border: 1px solid #000;
}
.pink-box {
cursor: move;
display: none;
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
opacity: .5;
}
#bigImg {
position: fixed;
top: 0;
left: 0;
}
</style>
<body>
<div>
<div class="move-box">
<img src="./images/b3.png" alt="">
<div class="pink-box"></div>
</div>
<div class="big">
<img src="./images/big.jpg" alt="" id="bigImg">
</div>
</div>
<script>
// 1、当鼠标进入小盒子,显示pink盒子、大盒子
var small = document.querySelector('.move-box');
var pinkBox = document.querySelector('.pink-box');
var big = document.querySelector('.big');
small.addEventListener('mouseover', function () {
pinkBox.style.display = 'block';
big.style.display = 'block';
})
// 2、当鼠标离开时,隐藏pink盒子、大盒子
small.addEventListener('mouseout', function () {
pinkBox.style.display = 'none';
big.style.display = 'none';
});
small.addEventListener('mousemove', function (e) {
// (1) 鼠标在盒子内的坐标
var x = e.pageX - small.offsetLeft;
var y = e.pageY - small.offsetTop;
// pink盒子的移动距离
var pinkX = x - pinkBox.offsetWidth / 2;
var pinkY = y - pinkBox.offsetHeight / 2;
// 最大移动距离 小盒子 - pink盒子
var pinkMaxX = small.offsetWidth - pinkBox.offsetWidth;
var pinkMaxY = small.offsetHeight - pinkBox.offsetHeight;
// 如果小于0,就停在0的位置
if (pinkX <= 0) {
pinkX = 0;
} else if (pinkX >= pinkMaxX) {
pinkX = pinkMaxX;
}
// 如果小于0,就停在0的位置
if (pinkY <= 0) {
pinkY = 0;
} else if (pinkY >= pinkMaxY) {
pinkY = pinkMaxY;
}
pinkBox.style.left = pinkX + 'px';
pinkBox.style.top = pinkY + 'px';
var bigImg = document.querySelector('#bigImg');
var bigMax = bigImg.offsetWidth - big.offsetWidth;
// 大图片的移动距离 = 最大移动距离 * 大图片移动距离 / pink盒子最大移动距离
var bigX = pinkX * bigMax / pinkMaxX;
var bigY = pinkY * bigMax / pinkMaxY;
bigImg.style.left = -bigX + 'px';
bigImg.style.top = -bigY + 'px';
});
</script>
</body>
效果:
二、元素可视区client系列
client概述
cline翻译过来就是客户端,使用clint系列的相关属性来获取元素可视区的相关信息。通过cline系列的相关属性可以动态的得到该元素的边框大小、元素大小等等。
cline系列属性 | 作用 |
element.clineTop | 返回元素上边距的大小 |
element.clineLeft | 返回元素左边框的大小 |
element.clineWidth | 返回自身包括padding、内容区的宽度,不含边框。返回的数值不带单位 |
element.clineHeight | 返回自身包括padding、内容区的高度,不含边框。返回的数值不带单位 |
分析flexible.js
立即执行函数 (function(){})() 或者 (function(){}())
主要作用: 创建一个独立的作用域。 避免了命名冲突问题
下面三种情况都会刷新页面都会触发 load 事件。
1.a标签的超链接
2.F5或者刷新按钮(强制刷新)
3.前进后退按钮
但是 火狐中,有个特点,有个“往返缓存”,这个缓存中不仅保存着页面数据,还保存了DOM和JavaScript的状态;实际上是将整个页面都保存在了内存里。
所以此时后退按钮不能刷新页面。
此时可以使用 pageshow事件来触发。,这个事件在页面显示时触发,无论页面是否来自缓存。在重新加载页面中,pageshow会在load事件触发后触发;根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件。
注意:这个事件给window添加
;(function flexible(window, document) {
// 获取的html 的根元素
var docEl = document.documentElement
// dpr 物理像素比
var dpr = window.devicePixelRatio || 1
// adjust body font size 设置我们body 的字体大小
function setBodyFontSize() {
// 如果页面中有body 这个元素 就设置body的字体大小
if (document.body) {
document.body.style.fontSize = 12 * dpr + 'px'
} else {
// 如果页面中没有body 这个元素,则等着 我们页面主要的DOM元素加载完毕再去设置body
// 的字体大小
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize()
// set 1rem = viewWidth / 10 设置我们html 元素的文字大小
function setRemUnit() {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize 当我们页面尺寸大小发生变化的时候,要重新设置下rem 的大小
window.addEventListener('resize', setRemUnit)
// pageshow 是我们重新加载页面触发的事件
window.addEventListener('pageshow', function (e) {
// e.persisted 返回的是true 就是说如果这个页面是从缓存取过来的页面,也需要从新计算一下rem 的大小
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports 有些移动端的浏览器不支持0.5像素的写法
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
})(window, document)
三、元素滚动scroll系列
scroll概述
scroll翻译过来就是滚动的,使用scroll 系列相关属性可以动态的得到该元素的大小、滚动距离等等。
scroll系列属性 | 作用 |
element.scrollTop | 返回被卷去的上侧距离。返回数值不带单位 |
element.scrollLeft | 返回被卷去的左侧距离。返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框。返回数值不带单位 |
element.scrollHeight | 返回自身实际的高度,不含边框。返回数值不带单位 |
页面被卷去的头部
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll事件。
四、三大系列总结
三大系列大小对比 | 作用 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度。返回数值不带单位 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框。返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框。返回数值不带单位 |
它们的主要用法:
(1)offset系列经常用于获得元素位置 offsetTop、offsetLeft
(2)client系列经常用于获取元素大小 clientWidth、clientHeight
(3)scroll系列经常用于获取滚动距离 scrollTop、scrollLeft
(4)注意:页面滚动的距离通过 window.pageXOffset 获得