1、元素偏移量
(1)位置大小
<body>
<style>
.father {
position: relative;
width: 100px;
height: 100px;
background-color: red;
margin: 100px;
}
.son {
width: 50px;
height: 50px;
background-color: blue;;
margin: 10px;
}
</style>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
//1.offset,动态获取元素的位置/大小:offsetTop/offsetLeft,返回值是数值,不带单位;需要注意的是:父元素要有定位,才能生效;如果父元素没有定位,则得出的元素位置是相对于body的偏移量
console.log(father.offsetTop);
console.log(father.offsetLeft);
//2.动态获取元素的大小,即宽度、高度,包含padding+border
console.log(father.offsetWidth);
console.log(father.offsetHeight);
//3.返回元素的父元素
console.log(son.offsetParent);// 返回带有定位的父元素
console.log(son.parentNode);//返回最近的父元素
</script>
</body>
(2)区别style
offset,可以从任意样式表中获取样式值;没有单位;大小包含width+padding+border;只读属性(只能读取数据不能赋值)。
style,只能得到行内样式的样式值;获取的宽高是平单位的字符串;不包含padding/border;可读可写,可以获取数值也可以赋值。
因此,想获取元素的位置、大小,就使用offset;想要给元素更改数值,就要用style。
(3)获取鼠标在盒子内的坐标
<body>
<style>
.father {
position: relative;
width: 200px;
height: 200px;
background-color: red;
margin: 100px;
}
</style>
<div class="father"></div>
<script>
var father = document.querySelector('.father');
father.addEventListener('mousemove',function(e) {
//1.计算出鼠标与窗口之间的距离
console.log(e.pageX);
console.log(e.pageY);
//2.计算出元素与窗口之间的距离
console.log(this.offsetLeft);
console.log(this.offsetTop);
//3.鼠标与窗口之间的距离-元素与窗口之间的距离=鼠标与盒子边距之间的距离
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
father.innerHTML = 'x坐标 ' + x + 'y坐标 ' + y;
})
</script>
</body>
案例1:登陆框(模态框)的实现
点击按钮,弹出登陆框;点击关闭,关闭登陆框;鼠标按下,移动登陆框;鼠标松开,停止移动。这个案例的核心思想是:盒子的相对位置=鼠标移动时盒子的相对位置。
<body>
<style>
/* html */
html {
position: relative;
height: 100%;
}
/* 按钮 */
button {
display: block;
margin: 20px auto;
}
/* 登陆框 */
.login {
position: relative;
display: none;
width: 400px;
height: 207px;
background-color: #fff;
margin: 0 auto;
text-align: center;
line-height: 3;
}
.login em {
position: absolute;
top: 0;
right: 0;
display: inline-block;
width: 40px;
height: 40px;
font-style: normal;
}
/* 背景色 */
.login-bg {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: -1;
width: 100%;
height: 100%;
background-color: #ccc;
overflow: hidden;
}
</style>
<!-- 按钮 -->
<button>点击按钮,快速登陆</button>
<!-- 登陆框 -->
<dl class="login">
<dt>登陆会员</dt>
<dd>用户名:<input type="text" placeholder="请输入用户名"></dd>
<dd>密 码:<input type="password" name="" id="psd" placeholder="请输入密码"></dd>
<p>点击登陆</p>
<em>关闭</em>
</dl>
<!-- 背景色 -->
<!-- 让一个div元素带背景色占满全屏的方法,一是要给html元素一个高度,并且设置该元素相对定位;二是设置子元素div为绝对定位,top:0;left:0;同时设置子元素的宽度、高度为100%。需要注意的是,如果不给html元素设置100%的高度,那么子元素是无法全屏的。 -->
<div class="login-bg"></div>
<script>
//1.获取元素,如果需要的效果没有出来,可以使用console.log()检查哪一步出了问题;
var btn = document.querySelector('button');
var login = document.querySelector('.login');
var loginbg = document.querySelector('.login-bg');
var em = document.querySelector('em');
var dt = document.querySelector('dt');
//2.点击按钮,显示表单、背景
btn.addEventListener('click',function() {
loginbg.style.display = 'block';
login.style.display = 'block';
})
//3.点击关闭,隐藏表单、背景
em.addEventListener('click',function() {
loginbg.style.display = 'none';
login.style.display = 'none';
})
//4.拖拽容器
dt.addEventListener('mousedown',function(e) {
//4-1鼠标按下,计算出鼠标到盒子边的距离,鼠标坐标=盒子的偏移量=鼠标到盒子边界的距离
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
document.addEventListener('mousemove',move);
function move(e) {
//4-2鼠标按下燕移动时,盒子到窗口的距离会不断变化,因此,此时,鼠标的坐标-鼠标到盒子边界的距离=盒子到窗口的偏移量
login.style.left = e.pageX - x - 400 + 'px';
login.style.top = e.pageY - y - 200 + 'px';
}
//4-3鼠标松开时,清除移动事件
document.addEventListener('mouseup',function() {
document.removeEventListener('mousemove',move);
})
})
</script>
</body>
案例2:京东放大镜效果的实现
<body>
<style>
.wrapper-pic {
position: relative;
width: 400px;
height: 400px;
border: 1px solid #ccc;
cursor: move;
}
.wrapper-pic .small {
text-align: center;
}
.wrapper-pic .mask {
display: none;
position: absolute;
/* top: 50%;
left: 50%;
transform: translate(-50%,-50%); */
width: 200px;
height: 200px;
background-color: yellow;
opacity: .5;
}
.wrapper-pic .big {
display: none;
position: absolute;
top: 0;
right: -510px;
width: 500px;
height: 500px;
border: 1px solid #ccc;
text-align: center;
}
.big img {
position: absolute;
top: 0;
left: 0;
}
</style>
<div class="wrapper-pic">
<div class="small"><img src="./s.jpg" alt="" width="320"></div>
<div class="mask"></div>
<div class="big"><img src="./big.jpg" alt="" width="400" class="bigImg"></div>
</div>
<script>
window.addEventListener('load',function() {
var wrapper = document.querySelector('.wrapper-pic');
var mask = document.querySelector('.mask');
var big = document.querySelector('.big');
//1.鼠标经过,显示遮罩、大图
wrapper.addEventListener('mouseover',function() {
mask.style.display = 'block';
big.style.display = 'block';
});
//2.鼠标离开,隐藏遮罩、大图
wrapper.addEventListener('mouseout',function() {
mask.style.display = 'none';
big.style.display ='none';
});
//3.鼠标移动时,大图跟着小图片移动放大
wrapper.addEventListener('mousemove',function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var maskx = x - mask.offsetWidth / 2;
var masky = y - mask.offsetHeight / 2;
var maskMax = wrapper.offsetWidth - mask.offsetWidth;
//3-1控制遮罩在盒子内移动
if (maskx <= 0) {
maskx = 0;
} else if (maskx >= maskMax) {
maskx = maskMax;
}
if (masky <= 0) {
masky = 0;
} else if (masky >= maskMax) {
masky = maskMax;
}
mask.style.left = maskx + 'px';
mask.style.top = masky + 'px';
//3-2大图随着小图移动,遮挡层移动的距离/遮挡层移动的最大距离=大图移动的距离/大图移动的最大距离,根据这个比例关系,可以得出:大图移动的距离=遮挡层移动的距离 * 大图移动的最大距离 / 遮挡层移动的最大距离
var big = document.querySelector('.big');
var bigImg = document.querySelector('.bigImg');
var bigxMax = big.offsetWidth -bigImg.offsetWidth;
var bigx = maskx * bigxMax / maskMax;
var bigy = masky * bigxMax / maskMax;
//图片必须设置绝对定位,才能让大图移动距离赋值给top/left生效
bigImg.style.left = bigx + 'px';
bigImg.style.top = bigy + 'px';
});
})
</script>
</body>
2、元素可视区
(1)client可视区
client只能返回元素的内容+内边距;offset不但可以返回元素的边距+内边距,还可以返回元素边框长度。
<script>
var div = document.querySelector('div');
//返回元素的宽度、高度
console.log(div.clientWidth);
console.log(div.clientHeight);
//返回元素的上边距、左边距
console.log(div.clientTop);
console.log(div.clientLeft);
</script>
(2)立即执行函数
最大的特点是,立即执行函数内的变量都是局部变量,不会冲突。
<script>
//1.方式1:不用调用,直接执行
(function (x,y) {
console.log(x + y);
var num = 888;
})(3,5);
//2.还可以像普通函数一样,传递参数
(function() {
console.log(999);
var num = 33;
} ())
</script>
(3)flexible.js会用即可,能看懂源码即可。
3、元素滚动
(1)基本语法
scroll与client相同之处是不能返回border值,但是都可以返回宽度、高度,内边距。
<script>
var div = document.querySelector('div');
//1. 自身内容的实际宽度、高度
console.log(div.scrollWidth);
console.log(div.scrollHeight);
//2.顶部、左边是宽度/高度-显示的部分,即隐藏的上面部分、左边部分
div.addEventListener('scroll',function() {
console.log(div.scrollTop);
console.log(div.scrollLeft);
})
</script>
(2)侧边栏目滚动案例
该案例不但实现了侧边栏目滚动的效果,还通过进一步修改优化左右轮播滚动的函数,实现了上下滚动的效果
<body>
<style>
div {
width: 800px;
margin: 0 auto;
}
header,main,section,article,footer {
width: 800px;
height: 300px;
background-color: red;
margin-bottom: 20px;
}
aside {
position: absolute;
right: 0%;
top: 70%;
width: 30px;
height: 180px;
background-color: blue;
}
aside span {
display: none;
}
p {
height: 600px;
background-color: skyblue;
}
</style>
<div>
<header>头部</header>
<main>主体</main>
<section>段落</section>
<article>文章</article>
<footer>网站底部</footer>
<p>版权所有</p>
</div>
<aside><em>在线客服</em>
<span>返回顶部</span>
</aside>
<script>
var aside = document.querySelector('aside');
var main = document.querySelector('main');
var mainTop = main.offsetTop;
var asideTop = aside.offsetTop - mainTop;
var span = document.querySelector('span');
var footer = document.querySelector('footer');
var footerTop = footer.offsetTop;
document.addEventListener('scroll',function() {
console.log(window.pageYOffset);
//1.如果页面被卷入的高度大于等于某个元素被卷入的高度,侧边栏由相对定位变为固定定位
if (window.pageYOffset >= mainTop) {
aside.style.position = 'fixed';
aside.style.top = asideTop + 'px';
} else {
//2.如果小于等于,则恢复相对定位、以及默认top值
aside.style.position = 'absolute';
aside.style.top = '70%';
}
//3.当页面被卷入的高度大于等于网页底部被卷入的高度时,显示“返回顶部”,否则隐藏“返回顶部”
if (window.pageYOffset >= footerTop) {
span.style.display = 'block';
} else {
span.style.display = 'none'
}
});
//4.点击“返回顶部”时,页面自动返回到顶部;修改X/Y的值,可以让页面滚动到任意位置; X/Y坐标没有单位px
span.addEventListener('click',function() {
// window.scroll(0,0);
// window.scroll(0,100);
animate(window,0);
});
//页面上下移动的动画,由页面左右移动改造而来
function animate(obj,target,callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (window.pageYOffset == target) {
clearInterval(obj.timer);
if (callback) {
callback();
}
} else {
window.scroll(0,window.pageYOffset + step);
}
},30);
}
</script>
</body>
(3)区分几个概念
①offset可以获取元素的宽高、内边距、边框;而client、scroll只能获取宽高、内边距,不能获取边框;
offset主要是用来获取元素的位置;client主要是获取元素的宽高;scroll主要获取元素的滚动距离。
而页面的滚动距离是通过window.pageXoffset、window.pageYOffset获得;
②mouseover mouseenter
<body>
<style>
.father {
width: 200px;
height: 200px;
background-color: red;
}
.son {
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
//1.mouseover,鼠标经过父元素及其子元素,都会触发事件
father.addEventListener('mouseover',function() {
console.log(11);
})
//2.mouseenter,鼠标经过该元素,只有该元素自身触发事件,另外mouseenter与mouseleave配合使用,也不全触发冒泡
father.addEventListener('mouseenter',function() {
console.log(22);
})
</script>
</body>
4、动画函数封装
(1)JS动画的核心思想
重复改变元素的偏移量,具体来说分为4步
重复改变元素的偏移量,具体来说分为4步
//1.获取盒子当前位置,让盒子在当前位置添加1个像素的距离
//2.设置例子绝对定位,把盒子偏移量赋值给left
//3.开启一个定时器,让定时器重复改变盒子偏移量,让盒子动起来
//4.添加一个约束条件,让定时器在指定的位置停止
<body>
<style>
.son {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<div class="son"></div>
<script>
var son = document.querySelector('.son');
var timer = setInterval(function() {
if (son.offsetLeft + 1 >= 400) {
clearInterval(timer);
} else {
son.style.left = son.offsetLeft + 1 + 'px';
}
},30)
</script>
</body>
(2)封闭动画函数
封装动画之后,先获取对象,再调用函数并传递参数,即可实现一个函数多次调用的效果。
<body>
<style>
.son {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<div class="son"></div>
<script>
function animate(obj,target) {
var timer = setInterval(function() {
if (obj.offsetLeft + 1 >= target) {
clearInterval(timer);
} else {
obj.style.left = obj.offsetLeft + 1 + 'px';
}
},30);
}
var son = document.querySelector('.son');
animate(son,500);
</script>
</body>
(3)给不同的元素记录不同的计数器
把元素看作一个对象,把定时器看作对象的属性,这样就可以实现不同的元素记录不同的计数器。与var相比,不用每次申请新的内存空间了。
另外,点击也可以实现点击按钮对象才会移动。
<body>
<style>
.son {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<button>点击开启动画</button>
<div class="son"></div>
<script>
function animate(obj,target) {
//1.把定时器作为对象一个属性,可节约内存,并且让每个对象都单独的拥有自己的定时器
//2.点击按钮,对象才会移动,但是,连续点击按钮时,对象会跑的更加,原因是每次点击之后,就用调用一个定时器;解决的方案是只有保留一个定时 器即可;具体办法是清除之前的定时器,保留当前定时器,这样就确保每次点击之后只有一个定时器运行。
clearInterval(obj.timer);
obj.timer = setInterval(function() {
if (obj.offsetLeft + 1 >= target) {
clearInterval(obj.timer);
} else {
obj.style.left = obj.offsetLeft + 1 + 'px';
}
},30);
}
var son = document.querySelector('.son');
var btn = document.querySelector('button');
btn.addEventListener('click',function() {
animate(son,500);
})
</script>
</body>
(4)缓动动画的实现
匀速动画:偏移量+固定值;
变速动画:偏移量+变化值;
缓动动画的思路:
A.让盒子每次偏移距离变小,速度就会慢慢小下来;
B.(目标值-偏移量)/10 作为每次移动距离的步长;
C.停止的条件,让当前盒子的位置等于目标位置时就停止下来;
D.步长值要向上取整;
<body>
<style>
.son {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<button>点击开启动画</button>
<div class="son"></div>
<script>
function animate(obj,target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//小长值要向上取整
var step = Math.ceil((target - obj.offsetLeft) / 10);
//停止条件发生了变化,当偏移量=目标值时
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
} else {
//(目标值-偏移量)/10 就可以让动画的速度慢下来
obj.style.left = obj.offsetLeft + step + 'px';
}
},30);
}
var son = document.querySelector('.son');
var btn = document.querySelector('button');
btn.addEventListener('click',function() {
animate(son,500);
})
</script>
</body>
(5)缓动动画多个目标值之间的移动
这个功能可以实现上一张图、下一张图之间的轮播
<body>
<style>
.son {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<button class="btn500">500</button>
<button class="btn800">800</button>
<div class="son"></div>
<script>
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);
} else {
obj.style.left = obj.offsetLeft + step + 'px';
}
},30);
}
var son = document.querySelector('.son');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click',function() {
animate(son,0);
})
btn800.addEventListener('click',function() {
animate(son,800);
})
</script>
</body>
(6)缓动动画添加回调函数
回调函数作为实参传递给另外一个函数作为形参使用,回调函数一般在上一个函数执行完毕才执行。
<body>
<style>
.son {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<button class="btn500">500</button>
<button class="btn800">800</button>
<div class="son"></div>
<script>
//2.接收函数的形参
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);
//3.回调函数要在上一个函数执行结束后执行
if (callback) {
callback();
}
} else {
obj.style.left = obj.offsetLeft + step + 'px';
}
},30);
}
var son = document.querySelector('.son');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
btn500.addEventListener('click',function() {
animate(son,0);
})
btn800.addEventListener('click',function() {
//1.回调函数作为实参传递给另外一个函数
animate(son,800,function() {
son.style.backgroundColor = 'red';
});
})
</script>
</body>
(7)动画函数的使用
上面封装好的函数,可以放入JS文件,然后再引入并调用。
<body>
<style>
.wrapper {
position: relative;
position: absolute;
right: 0;
color: #fff;
}
.arrow {
width: 40px;
height: 40px;
background-color: red;
text-align: center;
line-height: 40px;
}
.content {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 40px;
background-color: purple;
line-height: 40px;
z-index: -1;
}
</style>
<div class="wrapper">
<div class="arrow">←</div>
<div class="content">查看详情</div>
</div>
//1.引入封装函数
<script src="./js.js"></script>
<script>
var arrow = document.querySelector('.arrow');
var content = document.querySelector('.content');
arrow.addEventListener('mouseenter',function() {
//2.调用函数、调用回调函数
animate(content,-160,function() {
arrow.innerHTML = '→';
});
});
arrow.addEventListener('mouseleave',function() {
animate(content,0,function() {
arrow.innerHTML = '←';
});
})
</script>
</body>
案例1:轮播图片
基本结构,一个大盒子,里面装有箭头、小圆点、图片
节流阀,是为了防止轮播图片按钮连续点击造成的播放过快。目的是,当上一个函数动画内容执行完毕时,再去执行下一下函数动画,让事件无法连接被触发。其核心思路是,利于回调函数,锁住函数与解锁函数。具体做法是:
A.设置一个变量:var flag = true;
B.添加判断条件,if(flag) {flag=false; do something};关闭水龙头;
C.利用回调函数,flag= true; 再打开水龙头。
<body>
<style>
.banner {
position: relative;
width: 800px;
height: 500px;
margin: 50px auto;
overflow: hidden;
}
/* 设置ul足够宽的目的,是上横排的li都显示在一行上 */
.banner ul {
position: absolute;
top: 0;
left: 0;
width: 600%;
}
.banner ul li {
float: left;
}
.banner .prev,.next {
position: absolute;
display: none;
}
.banner .prev {
left: 0;
top: 150px;
line-height: 250px;
}
.banner .next {
right: 0;
top: 150px;
}
.banner ol {
position: absolute;
bottom: 20px;
left: 50%;
}
.banner ol li {
float: left;
width: 10px;
height: 10px;
background-color: #999;
margin-right: 5px;
border-radius: 50%;
}
.banner ol li.current {
background-color: #fff;
}
</style>
<div class="banner">
<!-- 轮播图使用UL/LI布局 -->
<ul class="pic">
<li><img src="./image/slidepic1.jpg" alt=""></li>
<li><img src="./image/slidepic2.jpg" alt=""></li>
<li><img src="./image/slidepic3.jpg" alt=""></li>
<li><img src="./image/slidepic4.jpg" alt=""></li>
<li><img src="./image/slidepic5.jpg" alt=""></li>
</ul>
<!-- 箭头直接输入或者使用阿里云图标 -->
<img src="./image/prev.png" alt="" class="prev">
<img src="./image/next.png" alt="" class="next">
<!-- 圆点数量根据图片数据动态生成 -->
<ol>
</ol>
</div>
<script>
//动画函数
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();
if (callback) {
callback();
}
} else {
obj.style.left = obj.offsetLeft + step + 'px';
}
},30);
}
//1.鼠标经过轮播图片时,显示隐藏的左、右按钮;离开时,隐藏两个按钮
var banner = document.querySelector('.banner');
var prev = document.querySelector('.prev');
var next = document.querySelector('.next');
var bannerWidth = banner.offsetWidth;//获取UL移动的宽度
banner.addEventListener('mouseenter',function() {
prev.style.display = 'block';
next.style.display = 'block';
clearInterval(timer);
});
banner.addEventListener('mouseleave',function() {
prev.style.display = 'none';
next.style.display = 'none';
timer = setInterval(function() {
next.click();
}, 2000);
timer = null;
})
//2.根据图片数据添加小圆点的数量,点击小圆点背景变色
var ul = document.querySelector('.pic');
var ol = document.querySelector('ol');
for (var i = 0; i < ul.children.length; i++) {
//2-1创建元素li并添加其父元素
var li = document.createElement('li');
//给li添加自定义属性:索引号
li.setAttribute('index',i);
ol.appendChild(li);
//2-2给ol的第一个子元素添加背景色为白的类
ol.children[0].className = 'current';
//点击li,圆点背景变白色
li.addEventListener('click',function() {
//2-3去掉其它li的背景色
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
//2-4显示当前点击的li的背景色
this.className = 'current';
//2-45点击小圆点移动图片(ul),此时必须给ul定位;ul移动的距离=索引号*图片宽度,为负,则向左移;
var index = this.getAttribute('index');//获取自定义属性index的值
//把索引号赋值给num的作用是,解决点击右箭头按照顺序显示下一张图片的BUG
num = index;
//把索引号赋值给circle的作用,解决点击右箭头后圆点按照顺序显示的bug
circle = index;
animate(ul,-index*bannerWidth);
})
}
//3。点击右箭头,图片无缝滚动;所谓无缝滚动,就是把ul的第一个子元素图片复制一份,放到最后,然后判断当点击到最后一张图片时,设置ul的left为0,循环显示第一张、第二张……;这个方法会产生一个问题,那就是自动生成的小圆点会多一个,解决的办法是用克隆的方法把第一张图片克隆一份,放到最后。
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);
var num = 0;
var circle = 0;
//flag-1设置节流阀,是为了防止连续点击按钮不断的触发事件导致的图片轮播过快
var flag = true;
next.addEventListener('click',function() {
//flag-2关闭阀门
if (flag) {
flag = false;
//借助一个变量num,实现点击右箭头图片向左移动
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul,-num*bannerWidth,function() {
//flag-3打开阀门
flag = true;
});
//借助一个变量circle,实现点击右箭头,小加点跟着走
circle++;
if (circle == ol.children.length) {
circle = 0;
}
//调用函数
circleChange();
}
})
//4.点击左箭头,图片移动
prev.addEventListener('click',function() {
if(flag) {
flag = false;
//借助一个变量num,实现点击右箭头图片向左移动
if (num == 0) {
ul.style.left = (ul.children.length - 1)*bannerWidth + 'px';
num = ul.children.length - 1;
}
num--;
animate(ul,-num*bannerWidth,function() {
flag = true;
});
//借助一个变量circle,实现点击右箭头,小加点跟着走
circle--;
if (circle < 0) {
circle = ol.children.length - 1;
}
//调用函数
circleChange();
}
});
function circleChange() {
//清除其它小圆点背景色
for (var i = 0; i < ol.children.length; i ++)
{
ol.children[i].className = '';
}
//留下当前小圆点背景色
ol.children[circle].className = 'current';
}
//5.手动调用点击事件
var timer = setInterval(function() {
next.click();
}, 2000);
</script>
</body>
案例2:筋斗云
鼠标经过显示背景色,鼠标离开背景色恢复原位;鼠标点击背景色停留在当前位置。
<body>
<style>
.nav {
position: absolute;
height: 40px;
border: 1px solid burlywood;
}
.nav li{
float: left;
width: 60px;
height: 40px;
/* background-color: #ccc; */
line-height: 40px;
text-align: center;
margin-right: 10px;
}
.nav span {
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 38px;
background-color: red;
z-index: -1;
}
</style>
<div class="nav">
<span></span>
<ul>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
</ul>
</div>
<script>
var span = document.querySelector('span');
var lis = document.querySelectorAll('li');
var currentPosition = 0;
for (var i = 0 ; i < lis.length; i++) {
//1.鼠标经过导航文字,导航文字就出现背景;鼠标离开,导航背景就回到原位
lis[i].addEventListener('mouseenter',function() {
animate(span,this.offsetLeft);
});
lis[i].addEventListener('mouseleave',function() {
animate(span,currentPosition);
});
//2.点击之前,背景颜色就停留在当前点击的位置
lis[i].addEventListener('click',function() {
currentPosition = this.offsetLeft;
})
};
// 移动的动画
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();
}
} else {
obj.style.left = obj.offsetLeft + step + 'px';
}
},30);
}
</script>
</body>