console.log(w.offsetHeight);
// 3. 返回带有定位的父亲 否则返回的是body
console.log(son.offsetParent); // 返回带有定位的父亲 否则返回的是body
console.log(son.parentNode); // 返回父亲 是最近一级的父亲 亲爸爸 不管父亲有没有定位
1.2 offset 与 style 区别
完整代码演示如下:
1.3 案例1:获取鼠标在盒子内的坐标
案例分析:
-
我们在盒子内点击,想要得到鼠标距离盒子左右的距离;
-
首先得到鼠标在页面中的坐标(
e.pageX, e.pageY
); -
其次得到盒子在页面中的距离 (
box.offsetLeft, box.offsetTop
); -
用鼠标距离页面的坐标减去盒子在页面中的距离,得到 鼠标在盒子内的坐标;
-
如果想要移动一下鼠标,就要获取最新的坐标,使用鼠标移动事件
mousemove
;
完整代码演示如下:
1.4 案例2:模态框拖拽
要求:弹出框,我们也称为模态框。
-
点击弹出层, 会弹出模态框, 并且显示灰色半透明的遮挡层;
-
点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡层;
-
鼠标放到模态框最上面一行,可以按住鼠标拖拽模态框在页面中移动;
-
鼠标松开,可以停止拖动模态框移动;
案例分析:
-
点击弹出层, 模态框和遮挡层就会显示出来
display:block
; -
点击关闭按钮,模态框和遮挡层就会隐藏起来
display:none
; -
在页面中拖拽的原理: 鼠标按下并且移动, 之后松开鼠标;
-
触发事件是鼠标按下
mousedown
,鼠标移动mousemove
鼠标松开mouseup
; -
拖拽过程: 鼠标移动过程中,获得最新的值赋值给模态框的left和top值, 这样模态框可以跟着鼠标走了;
-
鼠标按下触发的事件源是 最上面一行,就是 id 为 title ;
-
鼠标的坐标 减去 鼠标在盒子内的坐标, 才是模态框真正的位置;
-
鼠标按下,我们要得到鼠标在盒子的坐标;
-
鼠标移动,就让模态框的坐标 设置为:鼠标坐标 减去盒子坐标即可,注意移动事件写到按下事件里面;
-
鼠标松开,就停止拖拽,就是可以让鼠标移动事件解除;
完整代码演示如下:
(2)元素可视区 client 系列
client
翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
| client系列属性 | 作用 |
| — | — |
| element.clientTop | 返回元素上边框的大小 |
| element.clientLeft | 返回元素左边框的大小 |
| element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
| element.clientHeight | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
2.1 案例:淘宝 flexible.js 源码分析
1️⃣ 立即执行函数 (function() {})()
或者 (function(){}())
,主要作用: 创建一个独立的作用域。 避免了命名冲突问题;
2️⃣ 下面三种情况都会刷新页面都会触发 load 事件。
-
a标签的超链接
-
F5或者刷新按钮(强制刷新)
-
前进后退按钮
但是 火狐中,有个特点,有个“往返缓存”,这个缓存中不仅保存着页面数据,还保存了DOM和JavaScript的状态;实际上是将整个页面都保存在了内存里。所以此时后退按钮不能刷新页面。
3️⃣ 此时可以使用 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))
(3)元素滚动 scroll 系列
3.1 元素 scroll 系列属性
scroll
翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
| scroll 系列属性 | 作用 |
| — | — |
| element.scrollTop | 返回被卷去的上侧距离,返回数值不带单位 |
| element.scrollLeft | 返回被卷去的左侧距离,返回数值不带单位 |
| element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
| element.scrollHeight | 返回自身实际的宽度,不含边框,返回数值不带单位 |
3.2 页面被卷去的头部
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll
事件。
3.2.1 案例:仿淘宝固定右侧侧边栏
要求:
-
原先侧边栏是绝对定位;
-
当页面滚动到一定位置,侧边栏改为固定定位;
-
页面继续滚动,会让 返回顶部显示出来;
案例分析:
-
需要用到页面滚动事件
scroll
因为是页面滚动,所以事件源是 document; -
滚动到某个位置,就是判断页面被卷去的上部值;
-
页面被卷去的头部:可以通过
window.pageYOffset
获得 如果是被卷去的左侧window.pageXOffset
; -
注意,元素被卷去的头部是
element.scrollTop
, 如果是页面被卷去的头部 则是window.pageYOffset
; -
其实这个值 可以通过盒子的
offsetTop
可以得到,如果大于等于这个值,就可以让盒子固定定位了;
完整代码演示如下:
返回顶部
3.3 页面被卷去的头部兼容性解决方案
需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:
-
声明了 DTD,使用 document.documentElement.scrollTop;
-
未声明 DTD,使用 document.body.scrollTop;
-
新方法
window.pageYOffset
和window.pageXOffset
,IE9 开始支持;
代码演示如下:
function getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
};
}
使用的时候 getScroll().left
3.4 三大系列总结
| 三大系列大小对比 | 作用 |
| — | — |
| element.offsetWidth | 返回自身包括padding、边框、内容区的宽度、返回数值不带单位 |
| element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
| element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
😆主要用法😆:
-
offset系列 经常用于获得元素位置
offsetLeft
offsetTop
; -
client 经常用于获取元素大小
clientWidth
clientHeight
; -
scroll 经常用于获取滚动距离
scrollTop
scrollLeft
; -
注意页面滚动的距离通过
window.pageXOffset
获得;
3.5 mouseenter和mouseover的区别
1️⃣ 当鼠标移动到元素上时就会触发 mouseenter
事件类似 mouseover;
2️⃣ 两者之间的差别是mouseover
鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter
只会经过自身盒子触发;
(4)动画函数封装
4.1 动画实现原理
核心原理:通过定时器 setInterval()
不断移动盒子位置。
实现步骤:
-
获得盒子当前位置;
-
让盒子在当前位置加上1个移动距离;
-
利用定时器不断重复这个操作;
-
加一个结束定时器的条件;
-
注意此元素需要添加定位,才能使用
element.style.left
;
完整代码演示如下:
4.2 动画函数简单封装
注意函数需要传递2个参数,动画对象和移动到的距离。
完整代码演示如下:
欢迎来到我的博客哦
4.3 动画函数给不同元素记录不同定时器
1️⃣ 如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
2️⃣ 核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。
完整代码演示如下:
点击我才能走呢
欢迎来到我的博客哦
4.4 缓动效果原理
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来;
😆思路😆:
-
让盒子每次移动的距离慢慢变小,速度就会慢慢落下来;
-
核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长;
-
停止的条件是: 让当前盒子位置等于目标位置就停止定时器;
-
注意步长值需要取整;
完整代码演示如下:
点击我才能走呢
欢迎来到我的博客哦
4.5 动画函数多个目标值之间移动
可以让动画函数从 800 移动到 500;
当我们点击按钮时候,判断步长是正值还是负值
-
如果是正值,则步长 往大了取整;
-
如果是负值,则步长 向小了取整;
完整代码演示如下:
点击我到500啦
点击我到800啦
欢迎来到我的博客哦
4.6 动画函数添加回调函数
1️⃣ 回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。
2️⃣ 回调函数写的位置:定时器结束的位置。
完整代码演示如下:
点击我到500啦
点击我到800啦
欢迎来到我的博客哦
点击我到500啦
点击我到800啦
欢迎来到我的博客哦