PC端网页特效
1.元素偏移量 offset系列
1.1offset概述
偏移量,使用相关属性可以动态的得到元素的位置(偏移)、大小等
获得 元素 距离 带有定位的父元素的 位置
获得 元素 自身的大小(宽高)
注意:返回的数值都不带单位
常用属性和作用:
element.offsetParent
返回作为该元素带有定位的父级元素,如果父级都没有定位则返回body
element.offsetTop
返回元素相对带有定位父元素上方的偏移
element.offsetLeft
返回元素相对带有定位父元素左边框的偏移
.father{
width: 100px;
height: 100px;
background-color: pink;
}
.son{
width: 60px;
height: 60px;
background-color: purple;
margin-left: 30px;
}
<div class="father">
<div class="son"></div>
</div>
var father=document.querySelector('.father');
var son=document.querySelector('.son')
//可以得到元素的偏移 位置
console.log(father.offsetTop);
console.log(father.offsetLeft);
//以带有定位的父元素为准, 此时父元素没定位position(或者无父元素),则以body为准
console.log(son.offsetLeft);
element.offsetWidth
返回自身包括padding、边框、 内容区的宽度,返回数值不带单位
element.offsetHeight
返回自身包括padding.边框、内容区的高度,返回数值不带单位
//可以得到宽高 包含padding+border+width
var w=document.querySelector('.w');
console.log(w.offsetWidth);//100
console.log(w.offsetHeight);//100
1.2offset与style区别
offset
- offset 可以得到任意样式表中的样式值
- offset 系列获得的数值是没有单位的
- offsetWidth 包含padding+ border +width
- offsetWidth 等属性是只读属性.只能获取不能赋值
- 所以, 我们想要获取元素大小位置,用offset更合适
style
- style 只能得到行内样式表中的样式值
- style.width 获得的是带有单位的字符串
- style.width 获得不包含padding和border的值
- style.width是可读写属性 ,可以获取也可以赋值
- 所以, 我们想要给元素更改值,则需要用style改变
1.3使用
案例:获取鼠标在盒子内的坐标
分析:
1.在盒子内点击 想要得到鼠标距离盒子的距离
2.首先得到鼠标在页面中的坐标(e.pageX,e.pageY)
3.其次得到盒子在页面中的距离(box.offsetLeft,box.offsetTop)
4.相减得到
5.如果想要移动一下鼠标,就获取新的坐标,使用鼠标移动事件mousemove
.w{
width: 100px;
height: 100px;
background-color: #767171;
margin-left:30px;
margin-top: 30px;
/*padding: 10px;*/
}
</style>
</head>
<body>
<div class="w"></div>
<script>
var w=document.querySelector('.w');
w.addEventListener('click',function (e) {
var x=e.pageX-this.offsetLeft;
var y=e.pageY-this.offsetTop;
this.innerHTML='x:'+x+'y:'+y;
})
</script>
var w=document.querySelector('.w');
w.addEventListener('mousemove',function (e) {
var x=e.pageX-this.offsetLeft;
var y=e.pageY-this.offsetTop;
this.innerHTML='x:'+x+'y:'+y;
})
案例:拖动模态框(弹出框)
样式未完善
1.点击弹出层,会弹出模态框,并且显示灰色半透明的遮挡层
2.点击关闭按钮,可以关闭,并且同时关闭灰色半透明遮挡层
3.鼠标放到模态框最上边一行,可以按住鼠标拖拽模态框在页面移动
4.鼠标松开,可以停止拖动模态框移动
5.鼠标按下:mousedown 移动:mousemove 松开:mouseup
6.拖拽过程:鼠标移动过程中,获得最新的赋值给模态框的left和top值,这样模态框就跟着鼠标走了
7.鼠标按下触发的事件源是最上边一行,就是title
8.鼠标的坐标减去鼠标在盒子内的坐标,是模态框真正的位置
9.鼠标按下,得到鼠标在盒子的坐标,鼠标移动,模态框坐标:鼠标坐标减去盒子坐标
注意移动事件写到按下事件里边
<style>
.login-header{
text-align: center;
}
#link{
text-decoration: none;
color: #222222;
}
.login{
display: none;
width:300px;
height: 150px;
line-height: 25px;
border: 1px solid #e1e1e1;
background-color: white;
text-align: center;
z-index: 999;
/*margin-top:50px ;*/
/*margin-left: 250px;*/
position: fixed;
left: 50%;
top:50%;
transform: translate(-50%,-50%);/*固定定位时垂直水平居中*/
}
.login-title{
/*position: absolute;*/
text-align: center;
}
.close-login{
color: #222222;
/*text-align: right;*/
width: 100%;
text-decoration: none;
}
.login-title span{
position: absolute;
right: 15px;
}
.login-bg{
display: none;
width: 100%;
height: 100%;
position: fixed;
top:0;
left: 0;
background: rgba(0,0,0, .3);
}
</style>
</head>
<body>
<div class="login-header">
<a href='javascript:;' id='link'>点击,弹出登录框</a>
</div>
<div class="login">
<div class="login-title" id="title">
登录会员
<span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
</div>
<div class="login-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="username" id="username" class="username">
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" name="password" id="password" class="password">
</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>
var login=document.querySelector('.login');
var bg=document.querySelector('.login-bg');
var link=document.querySelector('#link');
var closeBtn=document.querySelector('#closeBtn');
var title=document.querySelector('#title');
link.addEventListener('click',function () {
bg.style.display='block';
login.style.display='block';
})
closeBtn.addEventListener('click',function () {
bg.style.display='none';
login.style.display='none';
})
title.addEventListener('mousedown',function (e) {
var x=e.pageX-login.offsetLeft;//鼠标坐标
var y=e.pageY-login.offsetTop;
document.addEventListener('mousemove',move)
function move(e) {
login.style.left = e.pageX-x+'px';
login.style.top=e.pageY-y+'px';
}
document.addEventListener('mouseup',function () {
document.removeEventListener('mousemove',move)
})
})
</script>
案例:仿京东图片放大镜
分析:
1.分三个功能模块
2.鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开则隐藏
3.黄色遮挡层跟随鼠标
4.大图盒子显示黄色处的大图
5.遮挡层移动,大图片跟随移动
遮挡层移动距离/遮挡层最大移动距离=大图片移动距离/大图片最大移动距离
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手机详情页!</title>
<style>
*{
margin: 0;
padding: 0;
}
.wai{
width: 300px;
height: 300px;
border: 1px solid red;
position: absolute;
top:30px;
left: 30px;
padding: 0 0 0 0;
/*font-size: 0;*/
color: #ff645b;
}
#t{
position: absolute;
/*vertical-align: middle;*/
top:0;
left: 0;
width: 100%;
height: 100%;
}
.bg{
display: none;
position: absolute;
top:0;
left: 0;
width:100px ;
height: 100px;
background-color: #ff645b;
opacity:.5 ;
}
.right{
display: none;
width: 300px;
height: 300px;
position: absolute;
/*top:30px;*/
left: 336px;
background-color: #222222;
z-index: 999;
overflow: hidden;
}
.dt{
position: absolute;
top:0;
left: 0;
}
</style>
</head>
<body>
<div class="wai">
<!-- llasdads-->
<img src="../resource/01.jpg" id="t">
<div class="bg"></div>
<div class="right">
<img src="../resource/01.jpg" id="dt" class="dt">
</div>
</div>
</body>
<script>
var wai=document.querySelector('.wai');
var bg=document.querySelector('.bg');
var right=document.querySelector('.right');
wai.addEventListener('mouseover',function () {
bg.style.display='block';
right.style.display='block';
})
wai.addEventListener('mouseout',function () {
bg.style.display='none';
right.style.display='none';
})
wai.addEventListener('mousemove',function (e) {
//先计算出鼠标在盒子内的坐标
var x=e.pageX-this.offsetLeft;//父级无定位
var y=e.pageY-this.offsetTop;
// console.log(x,y);
var bgX=x-bg.offsetWidth/2;
var bgY=y-bg.offsetHeight/2;
//如果遮盖层x小于了0,就让他停在0的位置
/*if (bgX<=0){
bgX=0;
} else if(bgX>=wai.offsetWidth-bg.offsetWidth){
bgX=wai.offsetWidth-bg.offsetWidth;
}
if (bgY<=0){
bgY=0;
} else if(bgY>=wai.offsetHeight-bg.offsetHeight){
bgY=wai.offsetHeight-bg.offsetHeight;
}
bg.style.left=bgX+'px';
bg.style.top=bgY+'px';*/
//遮挡层的最大移动距离
var bgMax=wai.offsetWidth-bg.offsetWidth;
if (bgX<=0){
bgX=0;
} else if(bgX>=bgMax){
bgX=bgMax;
}
if (bgY<=0){
bgY=0;
} else if(bgY>=bgMax){
bgY=bgMax;
}
bg.style.left=bgX+'px';
bg.style.top=bgY+'px';
//大图
var dt=document.querySelector('.dt');
//大图片最大移动距离
var dtMax=dt.offsetWidth-right.offsetWidth;
//大图片的移动距离
var dtX=bgX*dtMax/bgMax;
var dtY=bgY*dtMax/bgMax;
dt.style.left=-dtX+'px';
dt.style.top=-dtY+'px';
})
</script>
</html>
2.元素可视区 client系列
2.1概述
client即客户端 使用client系列的相关属性来获取元素可视区的相关信息,通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等
client系列属性和作用
element.clientTop:返回元素上边框的大小
element.lientLeft:返回元素左边框的大小
element.cientWidth:返回自身包括padding.内容区的宽度,不含边框,返回数值不带单位
element.lientHeight:返回自身包括padding、 内容区的高度,不含边框,返回数值不带单位
2.2使用
案例:淘宝flexible.js源码分析
立即执行函数(function(){})()
主要作用:创建一个独立的作用域,避免了命名冲突
//立即执行函数:不需要调用,立马能够自己执行
//普通
function fn() {
console.log(1);
}
fn();
//立即执行函数 写法
//(function () {})() 后边的()表示调用 或者(function () {}() );
(function sum0(a,b) {
console.log(2);
console.log(a+b);//3
var num=10;
})(1,2);//()看做调用函数 两个立即执行函数之间必须加; 不然会报错
(function sum(a,b) {
console.log(a+b);//5
var num=10;
}(2,3));//这种的必须加;
//3.立即执行函数最大的作用就是 独立创建了一个作用域
3.元素滚动scroll系列属性
3.1概述
滚动的 使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等
scroll系列属性和作用
element.scrollTop:返回被卷去的上例距离,返回数值不带单位
element.scrolleft:返回被卷去的左侧距离,返回数值不带单位
element.scrollWidth:返回自身实际的宽度,不含边框,返回数值不带单位
element.scrolHeight:返回自身实际的高度,不含边框,返回数值不带单位
3.2使用
案例:仿淘宝固定侧边栏
分析:
1.原先侧边栏是绝对定位
2.当页面滚动到一定位置,侧边栏改为固定位置
页面继续滚动,会让返回顶部显示出来
3.因为是页面滚动,所以事件源是ducument
4.滚动到某个位置,就是判断页面被卷上去的上部值
5.页面被卷去的头部:可以通过window.pageYOffset 获得 如果是被卷去的左侧 换成X
6.注意:元素被卷去的头部是element.scrollTop,如果是页面被卷去的头部则是window.pageYOffset
<style>
.a1{
width: 1000px;
height: 400px;
background-color: #ff645b;
margin: 10px auto;
}
.a2{
width: 1000px;
height: 700px;
background-color: #333333;
/*position: relative;*/
/*top:10px;*/
margin: 10px auto;
}
.a3{
width: 1000px;
height: 900px;
background-color: #84c0ba;
/*position: relative;*/
margin: 10px auto;
}
.c {
width: 50px;
height: 120px;
background-color: #b4ff0d;
position: absolute;
top: 460px;
left:50%;
margin-left: 500px;
}
span{
display: none;
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div class="a1" id="a1">
111
</div>
<div class="a2">222</div>
<div class="a3">333</div>
<div class="c"><span class="gb"><a href="#a1">返回顶部</a></span></div>
</body>
<script>
var c=document.querySelector('.c');
var a2=document.querySelector('.a2');
// console.log(a2.offsetTop);
//侧边栏固定定位后 距离顶部距离应该不变了
var ctop=c.offsetTop-a2.offsetTop;
var a3=document.querySelector('.a3');
var gb=document.querySelector('.gb');
var a3top=a3.offsetTop;
document.addEventListener('scroll',function () {
// console.log(window.pageYOffset);//页面被卷去的头部
if (window.pageYOffset>=a2.offsetTop){
c.style.position='fixed';
c.style.top=ctop+'px';
}else {
c.style.position='absolute';
c.style.top=460+'px';
}
//页面滚动到a3时候 显示返回顶部
if (window.pageYOffset>=a3top){
gb.style.display='block';
}else {
gb.style.display='none';
}
})
4.三大系列总结
三大系列大小对比 作用
element.offsetWidth
返回自身包括padding、边框、 内容区的宽度,返回数值不带单位
element.clientWidth
返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位
element,scrollWidth
返回自身实际的宽度,不含边框,返回数值不带单位
主要用法:
-
offset系列 经常用于获得元素位置offsetleft offsetTop
-
client 经常用于获取元素大小clientWidth clientHeight
-
scroll经常用于获取滚动距离 scrollTop scrolleft
4.注意页面滚动的距离通过 window . pagexoffset获得
5.mouseenter和mouseover的区别***
var fa=document.querySelector('.fa');
var son=document.querySelector('.son');
fa.addEventListener('mouseover',function () {
console.log(11);
})
fa.addEventListener('mouseenter',function () {
console.log(22);
})
都是当鼠标移动到元素上时就会触发
但是mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发,
mouseenter 只有鼠标经过自身盒子才会触发
原因是:mouseenter不会冒泡
跟mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡
6.动画函数封装
6.1动画实现原理
核心原理:通过定时器setInterval()不断移动盒子位置
步骤:
1.获得盒子当前位置
2.让盒子在当前位置加上1个移动距离
3.利用定时器不断重复这个操作
4.结束定时器的条件
5.注意此元素需要 添加定位,才能使用element.style.left
div{
position: absolute;
width: 200px;
height: 200px;
background-color: pink;
left:0 ;
}
var div=document.querySelector('div');
var timer=setInterval(function () {
if (div.offsetLeft>=400){
clearInterval(timer);//盒子停止移动也就是停止定时器
}
div.style.left=div.offsetLeft+5+'px';
},30)
6.2动画函数简单封装
注意函数需要传递2个参数,动画对象和移动到的距离
div{
position: absolute;
width: 200px;
height: 200px;
background-color: pink;
left:0 ;
}
span{
position: absolute;
left: 0;
top: 220px;
display: block;
width: 50px;
height: 50px;
background-color: #84c0ba;
}
//简单动画函数封装 obj目标对象 target目标位置
function animate(obj,target) {
var timer=setInterval(function () {
if (obj.offsetLeft>=target){
clearInterval(timer);//盒子停止移动也就是停止定时器
}
obj.style.left=obj.offsetLeft+5+'px';
},30)
}
var div=document.querySelector('div');
var span=document.querySelector('span');
animate(span,300);//调用
animate(div,400);
6.3动画函数给不同元素记录不同定时器
如果多个元素都使用这个动画函数,每次都要var声明定时器,我们可以给不同元素使用不同的定时器(自己专门用自己的定时器)
核心原理:利用js是一门动态语言,可以很方便的给当前对象添加属性
上边的代码 调用一次函数就需要开辟一次内存空间
上边代码优化:
//给不同元素指定不同定时器
//简单动画函数封装 obj目标对象 target目标位置
function animate(obj,target) {
obj.timer=setInterval(function () {
if (obj.offsetLeft>=target){
clearInterval(obj.timer);//盒子停止移动也就是停止定时器
}
obj.style.left=obj.offsetLeft+5+'px';
},30)
}
var div=document.querySelector('div');
var span=document.querySelector('span');
animate(span,300);
animate(div,400);
6.4缓动动画
缓动效果 原理:让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:
1.让盒子每次移动的距离慢慢变小,速度就会慢慢降下来
2.核心算法:(目标值-现在的位置)/10 作为每次移动的距离步长
3.停止的条件:让当前盒子位置等于目标位置就停止定时器
//给不同元素指定不同定时器
//简单动画函数封装 obj目标对象 target目标位置
function animate(obj,target) {
//速度加快解决方法
clearInterval(obj.timer);
obj.timer=setInterval(function () {
//步长值写到定时器的里面
//var step=(target-obj.offsetLeft)/10
//把步长值改为整数,防止出现小数问题
var step=Math.ceil(target-obj.offsetLeft)/10;//往大了取
if (obj.offsetLeft==target){
clearInterval(obj.timer);//盒子停止移动也就是停止定时器
}
//
obj.style.left=obj.offsetLeft+step+'px';
},40)
}
var div=document.querySelector('div');
var span=document.querySelector('span');
var btn=document.querySelector('button');
btn.addEventListener('click',function () {
//当不断点击按钮,这个元素速度会越来越快,因为开启了太多定时器
//解决方法是 让元素只有一个定时器执行 每次都清楚定时器 如上
animate(span,800);
animate(div,500)
})
//匀速动画 就是盒子是当前的位置+固定的值
//缓动动画就是 盒子当前的位置+变化的值
回退情况
再点击时 要判断正负
//给不同元素指定不同定时器
//简单动画函数封装 obj目标对象 target目标位置
function animate(obj,target) {
//速度加快解决方法
clearInterval(obj.timer);
obj.timer=setInterval(function () {
//步长值写到定时器的里面
//把步长值改为整数,防止出现小数问题
// var step=Math.ceil(target-obj.offsetLeft)/10;//往大了取
//当后退时 负值往小了取
var step=(target-obj.offsetLeft)/10;
step=step>0?Math.ceil(step):Math.floor(step);
if (obj.offsetLeft==target){
clearInterval(obj.timer);//盒子停止移动也就是停止定时器
}
//
obj.style.left=obj.offsetLeft+step+'px';
},40)
}
var div=document.querySelector('div');
var span=document.querySelector('span');
var btn1=document.querySelector('#btn1');
btn1.addEventListener('click',function () {
//当不断点击按钮,这个元素速度会越来越快,因为开启了太多定时器
//解决方法是 让元素只有一个定时器执行 每次都清楚定时器 如上
animate(span,800);
animate(div,500);
})
//匀速动画 就是盒子是当前的位置+固定的值
//缓动动画就是 盒子当前的位置+变化的值
var btn2=document.querySelector('#btn2');
btn2.addEventListener('click',function () {
animate(div,800);
})
6.5动画函数添加回调函数
回调函数原理:函数可以作为一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,在执行穿进去的这个函数,这个函数就叫回调
回调函数写的位置:定时器结束的位置
//给不同元素指定不同定时器
//简单动画函数封装 obj目标对象 target目标位置
function animate(obj,target,callback) {
// console.log(callback);
// callback();调用
//速度加快解决方法
clearInterval(obj.timer);
obj.timer=setInterval(function () {
//步长值写到定时器的里面
//把步长值改为整数,防止出现小数问题
// var step=Math.ceil(target-obj.offsetLeft)/10;//往大了取
//当后退时 负值往小了取
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.left=obj.offsetLeft+step+'px';
},40)
}
var div=document.querySelector('div');
var span=document.querySelector('span');
var btn1=document.querySelector('#btn1');
btn1.addEventListener('click',function () {
//当不断点击按钮,这个元素速度会越来越快,因为开启了太多定时器
//解决方法是 让元素只有一个定时器执行 每次都清楚定时器 如上
animate(span,800);
animate(div,500);
})
//匀速动画 就是盒子是当前的位置+固定的值
//缓动动画就是 盒子当前的位置+变化的值
var btn2=document.querySelector('#btn2');
btn2.addEventListener('click',function () {
animate(div,800,function () {
// alert('hello');
div.style.backgroundColor='red';
});
})
案例:使用
<style>
.con{
position: absolute;
width: 150px;
height: 50px;
background-color: pink;
left: 0px;
top:0px;
z-index: -1;
}
.slider{
position: absolute;
right: 0px;
width: 50px;
height: 50px;
background-color: #84c0ba;
}
</style>
</head>
<body>
<div class="slider">
<span>←</span>
<div class="con">问题反馈</div>
</div>
</body>
<script>
var slider=document.querySelector('.slider');
var con=document.querySelector('.con');
slider.addEventListener('mouseenter',function () {
animate(con,-100,function () {
//等动画执行完毕后 改为右箭头
slider.children[0].innerHTML='→';
});
})
slider.addEventListener('mouseleave',function () {
animate(con,0,function () {
slider.children[0].innerHTML='←';
});
})
//给不同元素指定不同定时器
//简单动画函数封装 obj目标对象 target目标位置
function animate(obj,target,callback) {
// console.log(callback);
// callback();调用
//速度加快解决方法
clearInterval(obj.timer);
obj.timer=setInterval(function () {
//步长值写到定时器的里面
//把步长值改为整数,防止出现小数问题
// var step=Math.ceil(target-obj.offsetLeft)/10;//往大了取
//当后退时 负值往小了取
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.left=obj.offsetLeft+step+'px';
},40)
}
</script>
7.常见网页特效案例
7.1网页轮播图
也称为焦点图
功能需求:
1.鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮
2.点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理
3.图片播放的同时,下面小圆圈模块跟随一起变化
4.点击小圆圈,可以播放相应图片(ul移动 索引号*图片宽度)
5.鼠标不经过轮播图,轮播图模块,自动停止播放
节流阀:
防止轮播图按钮连续点击造成播放过快。
节流阀目的:当上-一个函数动画内容执行完毕,再去执行下一个函数动画 ,让事件无法连续触发。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
开始设置一个变量var flag = true;
if(fla g) (flag= false; do something)关闭水龙头
利用回调函数动画执行完毕,flag=true 打开水龙头
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
li{
list-style: none;
}
.k{
position: relative;
width: 500px;
height: 400px;
margin: 100px auto;
padding: 0;
background-color: #84c0ba;
/*text-align: center;*/
overflow: hidden;
}
.arrow-l{
display: none;
text-align: center;
text-decoration: none;
position: absolute;
left: 0px;
top: 200px;
width: 30px;
height: 30px;
background-color: #767171;
opacity: .5;
z-index: 999;
}
.arrow-r{
display: none;
text-align: center;
text-decoration: none;
position: absolute;
right: 0px;
top: 200px;
width: 30px;
height: 30px;
background-color: #767171;
opacity: .5;
z-index: 999;
}
.k ul{
position: absolute;
top:0;
left: 0;
width: 600%;
height: 100%;
padding: 0;
margin: 0;
}
.k ul li{
float: left;
height: 100%;
/*width: 100%;*/
}
.k ul li img{
height: 100%;
width: 500px;
}
.circle{
position: absolute;
bottom: 10px;
left: 200px;
}
.circle li{
float: left;
width: 8px;
height: 8px;
border: 1px solid #767171;
margin: 0 3px;
/*圆角*/
border-radius: 50%;
/* 鼠标经过显示小手*/
cursor: pointer;
}
.current{
background-color: #fff;
}
</style>
</head>
<body>
<div class="k">
<!-- 左侧按钮-->
<a href="javaccript:;" class="arrow-l"><</a>
<!-- 右侧按钮-->
<a href="javaccript:;" class="arrow-r">></a>
<ul>
<li>
<a href="#"><img src="../resource/01.jpg"></a>
</li>
<li>
<a href="#"><img src="../resource/001.png"></a>
</li>
<li>
<a href="#"><img src="../resource/01.jpg"></a>
</li>
<li>
<a href="#"><img src="../resource/001.png"></a>
</li>
</ul>
<!-- //小圆圈-->
<ol class="circle">
<!--<li></li>
<li class="current"></li>
<li></li>
-->
</ol>
</div>
</body>
<script>
//函数在前边 因为后边的依赖于动画函数
//给不同元素指定不同定时器
//简单动画函数封装 obj目标对象 target目标位置
function animate(obj,target,callback) {
// console.log(callback);
// callback();调用
//速度加快解决方法
clearInterval(obj.timer);
obj.timer=setInterval(function () {
//步长值写到定时器的里面
//把步长值改为整数,防止出现小数问题
// var step=Math.ceil(target-obj.offsetLeft)/10;//往大了取
//当后退时 负值往小了取
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();
}*/
callback &&callback();//短路运算
}
//
obj.style.left=obj.offsetLeft+step+'px';
},40)
}
var k=document.querySelector('.k');
var kwidth=k.offsetWidth;
var arrowl=document.querySelector('.arrow-l');
var arrowr=document.querySelector('.arrow-r');
//1;鼠标经过k就显示按钮
k.addEventListener('mouseenter',function () {
arrowl.style.display='block';
arrowr.style.display='block';
//停止定时器
clearInterval(timer);
timer=null;//清楚定时器变量
})
k.addEventListener('mouseleave',function () {
arrowl.style.display='none';
arrowr.style.display='none';
timer=setInterval(function () {
//手动调用点击事件
arrowr.click();
},2000)
})
//2.根据图片数动态生成圆圈个数
var ul=k.querySelector('ul');
var ol=k.querySelector('.circle');
for (var i=0;i<ul.children.length;i++){
//创建小li
var li=document.createElement('li');
//记录当前小圆圈的索引号 通过自定义属性来做
li.setAttribute('index',i);
//插入到ol
ol.appendChild(li);
//3.小圆圈排他思想 在生成同时 绑定点击事件
li.addEventListener('click',function () {
//干掉所有人
for (var i=0;i<ol.children.length;i++){
ol.children[i].className='';
}
//留下我自己
this.className='current';
//4.图片移动 移动的是ul
//ul的移动距离 索引号*图片宽度 注意是负值
//当点击某个li 拿到索引号
var index=this.getAttribute('index');
//当我们点击了某个小li 就把这个li的索引号给num 给circle
num=index;
circle=index;
animate(ul,-index*kwidth);
})
}
//5.把ol里面的第一个li设为白色
ol.children[0].className='current';
//6.克隆第一张图片li 放到ul最后面
var first=ul.children[0].cloneNode(true);
ul.appendChild(first);
//7.点击右侧按钮 图片滚动一张
//图片无缝滚动:把ul的第一个复制一份 放到ul的最后面,当滚动到克隆的图片时,让ul快速跳到最左侧:left为0
//同时num=0 从头开始
var num=0;
//circle控制小圆圈播放
var circle=0;
//节流阀
var flag=true;
arrowr.addEventListener('click',function () {
if (flag) {
flag = false;
//如果走到最后一张 快速复原
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * kwidth,function () {
flag=true;
});
//8.点击右侧按钮 小圆圈跟随变化
circle++;
if (circle == ul.children.length - 1) {
circle = 0;
}
circleChange();
}
});
arrowl.addEventListener('click',function () {
if (flag) {
flag = false;
//如果走到最后一张 快速复原
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * kwidth + 'px';
}
num--;
animate(ul, -num * kwidth,function () {
flag=true;
});
//8.点击右侧按钮 小圆圈跟随变化
circle--;
/* if (circle<0){
circle=ol.children.length-1;
}*/
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 () {
//手动调用点击事件
arrowr.click();
},2000)
</script>
</html>
7.2带有动画的返回底部
<script>
function animate(obj,target,callback) {
// console.log(callback);
// callback();调用
//速度加快解决方法
clearInterval(obj.timer);
obj.timer=setInterval(function () {
//步长值写到定时器的里面
//把步长值改为整数,防止出现小数问题
// var step=Math.ceil(target-obj.offsetLeft)/10;//往大了取
//当后退时 负值往小了取
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();
}*/
//简单写法
callback &&callback();//短路运算
}
//
// obj.style.left=window.pageYOffset+step+'px';
window.scroll(0,window.pageYOffset+step );
},40)
}
var c=document.querySelector('.c');
var a2=document.querySelector('.a2');
// console.log(a2.offsetTop);
//侧边栏固定定位后 距离顶部距离应该不变了
var ctop=c.offsetTop-a2.offsetTop;
var a3=document.querySelector('.a3');
var gb=document.querySelector('.gb');
var a3top=a3.offsetTop;
document.addEventListener('scroll',function () {
// console.log(window.pageYOffset);//页面被卷去的头部
if (window.pageYOffset>=a2.offsetTop){
c.style.position='fixed';
c.style.top=ctop+'px';
}else {
c.style.position='absolute';
c.style.top=460+'px';
}
//页面滚动到a3时候 显示返回顶部
if (window.pageYOffset>=a3top){
gb.style.display='block';
}else {
gb.style.display='none';
}
})
gb.addEventListener('click',function () {
//x,y直接写数字
// window.scroll(0,0);//回到顶部
animate(window,0);
})
</script>