offset相关属性可以动态的
得到该元素的位置(偏移)、大小等
offset系列常用属性 | 作用 |
---|---|
element.offsetParent | 返回该元素带有定位的父级元素,如果父级没定位,则返回body |
element.offsetTop |
返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft |
返回元素相对带有定位父元素左边框的偏移 |
element.offsetWidth | 返回自身宽度(包括padding、边框) |
element.offsetHeight | 返回自身高度(包括padding、边框) |
注意:返回值不带单位
offset | style |
---|---|
可以得到任意样式表中的样式值 | 只能得到行内样式表中的样式值(行内样式表:写在元素自身的样式) |
获得的数值无单位 | 获得带有单位的字符串 |
包含padding+border+width | 不包含padding和border |
只能读不能赋值 | 能读也能赋值 |
因此:获取元素的位置,用offset更适合;给元素改值,使用style更合适
client系列相关属性可以动态
得到元素的边框大小、元素大小等
client系列常用属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth |
返回自身padding、内容区的宽度,不包含边框 |
element.clientHeight |
返回自身padding、内容区的高度,不包含边框 |
(function() {})()
// 或者
(function(){}())
主要作用: 创建一个独立的作用域。 避免了命名冲突问题
scroll 系列的相关属性可以动态
的得到该元素的大小、滚动距离等
scroll系列常用属性 | 作用 |
---|---|
element.scrollTop |
返回被卷去的上侧距离 |
element.scrollLeft |
返回被卷去的左侧距离 |
element.clientWidth | 返回自身的实际宽度、不包含边框 |
element.clientHeight | 返回自身的实际高度、不包含边框 |
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件
滚动窗口至文档中的特定位置:window.
注意,里面的x和y 不跟单位,直接写数字
① 需要用到页面滚动事件srcoll,因此事件源为document
② 页面被卷去的头部:window.pageYOffset
获得,如果是被卷去的左侧window.pageXOffset
③ 滚到窗口到文档的特定位置
:window.scroll(x, y)
,x和y可以不带单位
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>Documenttitle>
<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: 3000px;
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>
var banner = document.querySelector(".banner");
var sliderBar = document.querySelector(".slider-bar");
var bannerTop = banner.offsetTop;
var sliderBarTop = sliderBar.offsetTop;
var main = document.querySelector(".main");
var goBack = document.querySelector(".goBack");
var mainTop = main.offsetTop;
document.addEventListener("scroll", function (e) {
if (window.pageYOffset >= bannerTop) {
sliderBar.style.position = "fixed";
sliderBar.style.top = sliderBarTop - bannerTop + "px";
} else {
sliderBar.style.position = "absolute";
sliderBar.style.top = "300px";
}
if (window.pageYOffset >= mainTop) {
goBack.style.display = "block";
} else {
goBack.style.display = "none";
}
});
goBack.addEventListener("click", function () {
window.scroll(0, 0);
});
script>
body>
html>
① 声明了 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
实现div在500到800之间移动
<!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: 100px;
height: 100px;
background-color: antiquewhite;
}
</style>
</head>
<body>
<button class="btn800">点击到800处</button>
<button class="btn500">点击到500处</button>
<div></div>
</body>
<script>
var div = document.querySelector("div");
var btn500 = document.querySelector(".btn500");
var btn800 = document.querySelector(".btn800");
function animate(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
obj.style.marginLeft = obj.offsetLeft + step + "px";
}, 30);
}
btn500.addEventListener("click", function () {
// 调用函数
animate(div, 500);
});
btn800.addEventListener("click", function () {
// 调用函数
animate(div, 800);
});
</script>
</html>
回调函数原理
:函数作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完毕之后,再执行传进去的这个函数,这个过程叫做回调
回调函数写的位置:定时器结束的位置。
在上面案例的基础上,当div到达800时变背景色
<script>
var div = document.querySelector("div");
var btn500 = document.querySelector(".btn500");
var btn800 = document.querySelector(".btn800");
function animate(obj, target.callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
if(callback){
callback() // 调用回调函数
}
}
obj.style.marginLeft = obj.offsetLeft + step + "px";
}, 30);
}
btn500.addEventListener("click", function () {
// 调用函数
animate(div, 500);
});
btn800.addEventListener("click", function () {
// 调用函数
animate(div, 800.function(){
btn800.style.backgroundColor ="red"
});
});
</script>
目的
:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
核心实现思路
:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
// 开始设置一个变量
var flag = true;
if(flag) {
flag = false; // 关闭水龙头
do something
}
// 利用回调函数 动画执行完毕
flag = true // 打开水龙头
用途
:防止轮播图按钮连续点击造成播放过快
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>Documenttitle>
<style>
.focus {
position: relative;
width: 721px;
height: 455px;
overflow: hidden;
}
.focus ul {
position: absolute;
top: 0;
left: 0;
width: 600%;
}
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
.arrow-r,
.arrow-l {
position: absolute;
top: 50%;
margin-top: -20px;
width: 24px;
height: 40px;
background: rgba(0, 0, 0, 0.3);
text-align: center;
line-height: 40px;
color: #fff;
font-size: 18px;
z-index: 2;
}
.arrow-r {
right: 0;
}
li {
float: left;
}
.circle {
position: absolute;
bottom: 10px;
left: 50px;
}
.circle li {
float: left;
width: 8px;
height: 8px;
/*background-color: #fff;*/
border: 2px solid rgba(255, 255, 255, 0.5);
margin: 0 3px;
border-radius: 50%;
/*鼠标经过显示小手*/
cursor: pointer;
}
.current {
background-color: #fff;
}
style>
head>
<body>
<div class="focus fl">
<a href="javascript:;" class="arrow-l"> > a>
<a href="javascript:;" class="arrow-r"> < a>
<ul>
<li >
<a href="#"><img src="upload/focus.jpg" alt="" />a>
li>
<li>
<a href="#"><img src="upload/focus1.jpg" alt="" />a>
li>
<li>
<a href="#"><img src="upload/focus2.jpg" alt="" />a>
li>
<li>
<a href="#"><img src="upload/focus3.jpg" alt="" />a>
li>
ul>
<ol class="circle">ol>
div>
body>
<script>
var ul = document.querySelector("ul");
var lis = document.querySelectorAll("li");
// 封装一个动画
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
callback && callback();
}
obj.style.left = obj.offsetLeft + step + "px";
}, 15);
}
window.addEventListener("load", function () {
var arrow_l = document.querySelector(".arrow-l");
var arrow_r = document.querySelector(".arrow-r");
var focus = document.querySelector(".focus");
var focusWidth = focus.offsetWidth;
focus.addEventListener("mouseenter", function () {
arrow_l.style.display = "block";
arrow_r.style.display = "block";
clearInterval(timer);
timer = null; // 清除定时器变量
});
focus.addEventListener("mouseleave", function () {
arrow_l.style.display = "none";
arrow_r.style.display = "none";
timer = setInterval(function () {
//手动调用点击事件
arrow_r.click();
}, 2000);
});
var ul = focus.querySelector("ul");
var ol = focus.querySelector(".circle");
for (var i = 0; i < ul.children.length; i++) {
var li = document.createElement("li");
li.setAttribute("index", i);
ol.appendChild(li);
// 直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener("click", function () {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
this.className = "current";
var index = this.getAttribute("index");
num = index;
circle = index;
animate(ul, -index * focusWidth);
});
}
ol.children[0].className = "current";
// 克隆第一张图片(li)放到ul 最后面
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);
var num = 0;
var circle = 0; // circle 控制小圆圈的播放
// flag 节流阀
var flag = true;
// 点击左侧按钮
arrow_r.addEventListener("click", function () {
if (flag) {
flag = false; // 关闭节流阀
// 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth, function () {
flag = true; // 打开节流阀
});
circle++;
if (circle == ol.children.length) {
circle = 0;
}
// 调用函数
circleChange();
}
});
// 点击右侧按钮
arrow_l.addEventListener("click", function () {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * focusWidth + "px";
}
num--;
animate(ul, -num * focusWidth, function () {
flag = true;
});
circle--;
circle = circle < 0 ? ol.children.length - 1 : circle;
circleChange();
}
});
// 封装一个控制小圆点的函数
function circleChange() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = "";
}
ol.children[circle].className = "current";
}
var timer = setInterval(function () {
//手动调用点击事件
arrow_r.click();
}, 2000);
});
script>
html>
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>Documenttitle>
<style>
body {
padding: 0;
margin: 0;
}
ul {
width: 560px;
height: 36px;
padding: 0;
margin: 0;
background-color: rgb(235, 247, 247);
opacity: 0.5;
}
li {
list-style: none;
float: left;
width: 80px;
height: 36px;
line-height: 36px;
text-align: center;
}
.current {
z-index: -999;
position: absolute;
top: 0;
left: 0;
width: 80px;
height: 36px;
background-color: pink;
opacity: 00.9;
}
style>
head>
<body>
<div>
<ul>
<li>首页li>
<li>语文li>
<li>数学li>
<li>英语li>
<li>物理li>
<li>化学li>
<li>体育li>
ul>
<span class="current"> span>
div>
body>
<script>
var ul = document.querySelector("ul");
var lis = document.querySelectorAll("li");
var current = document.querySelector(".current");
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
callback && callback();
}
obj.style.left = obj.offsetLeft + step + "px";
}, 15);
}
// console.log(lis.length);
window.addEventListener("load", function () {
for (var i = 0; i < lis.length; i++) {
lis[i].addEventListener("mouseenter", function () {
animate(current, this.offsetLeft);
});
lis[i].addEventListener("mouseleave", function () {
animate(current, 0);
});
lis[i].addEventListener("click", function () {
current = this.offsetLeft;
});
}
});
script>
html>
区别:mouseenter不会冒泡
mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发;mouseenter 只会经过自身盒子触发
跟mouseenter搭配的鼠标离开mouseleave 同样不会冒泡