文章目录
- 一、元素偏移量offset
- 1.1 offset常用属性
- 1.2 offset与style的区别
- 1.3 案例
- 二、元素可视区client
- 2.1 常用client属性
- 2.2 client应用-flexible.js核心原理
- 三、元素滚动scroll
- 3.1 scroll系列常用属性
- 3.2 mouseover和mouseenter的区别
- 四、动画函数封装
- 4.1 动画实现原理
- 4.2 动画函数封装
- 4.3 缓动动画
一、元素偏移量offset
1.1 offset常用属性
offset 翻译过来就是偏移量,我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等.它可以
- 获得元素距离带有定位父元素的位置(offsetLeft,offsetTop)
- 获得元素自身的大小( 宽度高度)(offsetWidth,offsetHeight)
- 注意:返回的数值都不带单位
<!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">
<style>
.father{
width:300px;
height: 300px;
margin: 200px;
background: pink;
position: relative;
}
.child{
width: 200px;
height: 200px;
background: purple;
margin: 40px;
padding:10px;
border: 2px solid red;
}
</style>
</head>
<body>
<div class="father">
<div class="child"></div>
</div>
<script>
var father = document.querySelector(".father")
var child = document.querySelector(".child")
// 1.获取相对偏移量。注意:如果父元素没有定位,则默认返回相对body的偏移量
// 当父元素.father有position:relative属性时,返回40,0;当你元素没有定位时返回240,200
console.log(child.offsetLeft,child.offsetTop)
// 2.获取自身大小(包含padding,border,width)
console.log(child.offsetWidth, child.offsetHeight) // 224 224
// 3.获取具有定位的父元素(当父元素没有定位时默认为body)
console.log(child.offsetParent) // .father有position:relative时,返回.father。
</script>
</body>
</html>
1.2 offset与style的区别
1、offset
- offset 可以得到任意样式表中的width,height样式值(内嵌,行内,外链样式)
- offset 系列获得的数值是没有单位的(数值型)
- offsetWidth包含padding+border+width
- offsetWidth 等属性是只读属性,只能获取不能赋值
- 总结:想要获取元素大小位置,用offset更合适
2、style
- style 只能得到行内样式表中的样式值
- style.width获得的是带有单位的字符串
- style.width获得不包含padding和border的值
- style.width 是可读写属性,可以获取也可以赋值
- 想要给元素更改值,则需要用style改变
<!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">
<style>
.box {
width: 200px;
height: 200px;
background: purple;
margin: 40px;
padding: 10px;
border: 2px solid red;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector(".box")
let offsetWidth = box.offsetWidth
let styleWidth = box.style.width
// 1、因为style只能获取到行内样式的width值,所以此处输出224,空
// 2、因为offset包含padding,border,width值,所以此处返回为200+10+10+2+2 = 224
console.log(offsetWidth,styleWidth)
</script>
</body>
</html>
1.3 案例
1、拖拽元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.box {
width: 200px;
height: 200px;
background: pink;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector(".box");
// 鼠标按下,获取坐标
box.addEventListener("mousedown", function (e) {
box.addEventListener("mousemove", move);
});
function move(e) {
// 示例1、获取鼠标在box内的坐标
var pageX = e.pageX;
var pageY = e.pageY;
var offsetX = this.offsetLeft;
var offsetY = this.offsetTop;
var x = pageX - offsetX;
var y = pageY - offsetY;
this.innerHTML = "鼠标在盒内坐标(x,y):(" + x + "," + y + ")";
// 示例2、拖拽实现 —— 绝对定位+动态定位赋值,默认鼠标在盒子居中位置
var posLeft = pageX - box.offsetWidth / 2;
var posTop = pageY - box.offsetHeight / 2;
this.style.left = posLeft + "px";
this.style.top = posTop + "px";
}
box.addEventListener("mouseup", function (e) {
box.removeEventListener("mousemove", move);
});
</script>
</body>
</html>
二、元素可视区client
2.1 常用client属性
client: 翻译过来是客户端,我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
2.2 client应用-flexible.js核心原理
1、立即执行函数
- 立即执行函数最大的作用是独立创建了一个作用域,里面的所有变量都是局部变量,不会有命名冲突的情况
- 创建独立作用域,避免命名冲突
// 1、具名函数直接调用
function fn(){
console.log("执行了")
}
fn()
// 2、方式2.1 (Fun)()
(function(a,b){
console.log(a+b)
})(1,2)
// 3、方式2.2 (Fun()())
(function(a,b){
console.log(a+b)
}(3,4))
2、pageshow事件
- 与onload事件相比,pageshow事件在页面显示时触发,且无论页面是否来自缓存都会触发(onload在firefox中如果有缓存页面数据,不会触发)。
- pageshow会在load事件后触发
- 根据事件对象中的persisted来判断 是否是缓存中的页面触发的。
- pageshow事件,是给window对象添加的
// 立即执行函数 (function() {})() 或者 (function() {} ())
// 主要作用:创建一个独立的作用域,里面所有的变量都是局部变量,避免了命名冲突问题
// 立即执行函数不需要调用,立马能够自己执行
(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
3.1 scroll系列常用属性
- 页面被卷去的上侧距离 : window.pageYOffset
- 页面被卷去的左侧距离 :window.pageXOffset
- 滚动事件:window.onscroll 或window.addEventListener(“scroll”,fun)
1、offsetHeight,clientHeight,scrollHeight的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="box" style="width:200px;height:200px;background: pink;border:6px solid blue;padding:10px">
一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box一段超长文本超出box
</div>
<script>
var box = document.querySelector(".box")
let oh = box.offsetHeight // padding+border+height
let ch = box.clientHeight // padding+height
let sh = box.scrollHeight // padding+contentHeight
// 输出:232 220 304
console.log(oh,ch,sh)
</script>
</body>
</html>
2、scroll的兼容性问题
- 当页面声明了doctype时,被卷去的头部通过:document.documentElement.scrollTop获取
- 当页面没声明doctype时,使用document.body.scrollTop
- 在IE9以后,通过window.pageYOffset和window.pageXOffset获取
function getScroll(){
return {
left :window.pageXOffset ||document.documentElement.scrollLeft||document.body.scrollLeft,
top:window.pageYOffset || document.documentElement.scrollTop||document.body.scrollTop,
}
}
3、使用场景
- offset属性:常用于获取元素的位置
- client属性:获取元素大小
- scroll属性:用于获取滚动距离
3.2 mouseover和mouseenter的区别
- 当鼠标移动到元素上时就会触发mouseenter事件
- mouseover鼠标经过自身盒子会触发,经过子例子还会触发。mouseenter只会经过自身盒子触发(因为mouseenter不会冒泡)
- mouseenter对应mouseleave
- mouseover对应mouseout
四、动画函数封装
4.1 动画实现原理
核心原理:通过定时器setInterval()不断移动盒子位置
实现盒子移动动画:
- 获得例子当前位置
- 让例子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要绝对定位,才能使用用element.style.left控制移动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.box {
width: 100px;
height: 100px;
background: pink;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector(".box");
var timer = setInterval(() => {
if(box.offsetLeft>=500){
clearInterval(timer)
}
let left = box.offsetLeft + 1;
box.style.left = left + "px";
});
</script>
</body>
</html>
4.2 动画函数封装
- 设置函数目标对象
- 确定目标位置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.big {
width: 200px;
height: 200px;
background: pink;
position: absolute;
left: 0;
top: 0;
}
.small {
width: 100px;
height: 100px;
background: blue;
position: absolute;
left: 0;
top: 220px;
}
</style>
</head>
<body>
<div class="big">big</div>
<div class="small"><button>small开始动画</button></div>
<script>
// 1、封装动画函数
// elObj -> 要实现动画的元素对象, target:停止动画的距离
function animate(elObj, target) {
// 如果元素对象有定时器,需要先清理,防止重复创建定时器
if (elObj.timer) {
clearInterval(elObj.timer);
}
// 持续设置元素左边距
elObj.timer = setInterval(() => {
if (elObj.offsetLeft > target) {
clearInterval(elObj.timer);
}
elObj.style.left = elObj.offsetLeft + 1 + "px";
}, 5);
}
var big = document.querySelector(".big");
var small = document.querySelector(".small");
var btn = document.querySelector("button");
btn.addEventListener("click", function () {
animate(small, 300);
});
animate(big, 400);
</script>
</body>
</html>
4.3 缓动动画
原理:
- 缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
- 核心算法:(目标值-现在的位置)/ 10 做为每次移动的距离步长
- 停止的条件是:让当前盒子位置等于目标位置就停止定时器
注意:动画步长需要取整,步长大于0时向上取整,小于0时向下取整
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.big {
width: 200px;
height: 200px;
background: pink;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="big">big</div>
<script>
// 1、缓动动画原理:随时时间增加,移动距离减少
function animate(elObj, target) {
// 如果元素对象有定时器,需要先清理,防止重复创建定时器
if (elObj.timer) {
clearInterval(elObj.timer);
}
// 持续设置元素左边距
elObj.timer = setInterval(() => {
// 步长值,用于控制每次移动距离
var step = (target - elObj.offsetLeft)/10
if (elObj.offsetLeft == target) {
clearInterval(elObj.timer);
}
elObj.style.left = elObj.offsetLeft + step + "px";
}, 15);
}
var big = document.querySelector(".big");
animate(big, 1200);
</script>
</body>
</html>