PC端网页特效
1.元素偏移量offset系列
· 获得元素距离带有定位父元素的位置
· 获得元素自身的大小(宽度高度)
· 注意:返回的数值都不带单位
offset 系列常用属性

<script type="text/javascript">
var father = document.querySelector('.father');
var son = document.querySelector('.son');
//1.可以得到元素的偏移位置 返回的不带单位的数值
console.log(father.offsetTop);
//它以带有定位的父级为准,如果没有父级或者父级没有定位 则以body为准
console.log(son.offsetLeft);
//2.可以得到元素的大小 宽度和高度 是包含padding + border + width
console.log(father.offsetWidth);
//3.返回带有定位的父级,否则返回的是body
console.log(son.offsetParent);//返回带有定位的父级,否则返回的是body
console.log(son.parentNode);//返回最近一级的父级 不管父级有没有定位
</script>
1.2 offset 与style区别

拖动的模态框 案例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
.login-header{
text-align: center;
margin: 200px 0 0;
}
.login{display: none;
width: 512px;
height: 280px;
position: fixed;
border: 1px solid #ebebeb;
left: 50%;
top: 50%;
background: #fff;
box-shadow: 0px 0px 20px #ddd;
z-index: 9999;
transform: translate(-50%,-50%);
cursor: move;
}
.login-title{
width: 100%;
margin: 10px 0 0 0;
text-align: center;
line-height: 40px;
height: 40px;
}
.login-input-content{
margin-top: 20px;
}
.login-button{width: 50%;
margin: 30px auto 0;
line-height: 40px;
font-size: 14px;
border: 1px solid #EBEBEB;
text-align: center;
}
.login-bg{
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(0,0,0,.3);
}
a{
text-decoration: none;
color: #000;
}
.login-button a{
display: block;
}
.login-input input.list-input{
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: 1px solid #EBEBEB;
text-indent: 5px;
}
.login-input{
overflow: hidden;
margin: 0 0 20px;
}
.login-input label{
float: left;
width: 90px;
padding-right: 10px;
text-align: right;
line-height: 35px;
height: 35px;
font-size: 14px;
}
.login-title span{
position: absolute;
font-size: 12px;
right: -20px;
top: -30px;
background-color: #FFFFFF;
border: 1px solid #ebebeb;
width: 40px;
height: 40px;
border-radius: 20px;
}
</style>
</head>
<body>
<div class="login-header"><a id="link" href="javascript:;">点击,弹出登陆框</a></div>
<div id="login" class="login">
<div id="title" class="login-title">
登录会员<span><a href="" id="closeBtn" class="close-login">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" id="username" placeholder="请输入用户名" name='info[username]' class="list-input" />
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input"/>
</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 type="text/javascript">
//1.获取元素
var link = document.querySelector('#link');
var login = document.querySelector('#login');
var closeBtn = document.querySelector('#closeBtn');
var bg = document.querySelector('#bg');
var title = document.querySelector('#title');
link.addEventListener('click',function(){
login.style.display = 'block';
bg.style.display = 'block';
})
closeBtn.addEventListener('click',function(){
login.style.display = 'none';
bg.style.display = 'none';
})
// 当鼠标顶部标题栏按下,获得鼠标在盒子内的坐标
title.addEventListener('mousedown',function(e){
//获取鼠标在盒子内的坐标x,y
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>
</body>
</html>
仿京东放大镜效果 案例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .preview_img{ position: relative; width: 300px; height: 300px; } .proImg{ width: 100%; height: 100%; } .mask{ display: none; position: absolute; top: 0; left: 0; width: 200px; height: 200px; background: #f5e59f; opacity: .5; } .big{ display: none; position: absolute; top: 0; left: 310px; width: 500px; height: 500px; z-index: 999; overflow: hidden; border: 1px solid #eee; } .big img{ position: absolute; top: 0; left: 0; } </style> </head> <body> <div class="preview_img"> <img src="../img/proImg.jpg" class="proImg"/> <div class="mask"></div> <div class="big"><img src="../img/bigImg.jpg" alt="" class="bigImg"/></div> </div> <script type="text/javascript"> var preview = document.querySelector('.preview_img'); var mask = document.querySelector('.mask'); var big = document.querySelector('.big'); //当鼠标经过 就显示和隐藏 mask遮挡层 和big 大图片层 preview.addEventListener('mouseover',function(){ mask.style.display = 'block'; big.style.display = 'block'; }) preview.addEventListener('mouseout',function(){ mask.style.display = 'none'; big.style.display = 'none'; }) //鼠标移动的时候,让黄色盒子跟着鼠标走 preview.addEventListener('mousemove',function(e){ //先计算出鼠标在盒子内的坐标 var x = e.pageX - preview.offsetLeft; var y = e.pageY - preview.offsetTop; //减去盒子高度的一半 就是mask最终left和top值 var maskx = x - mask.offsetWidth / 2 ; var masky = y - mask.offsetHeight / 2 ; var maskMax = preview.offsetWidth - mask.offsetWidth; if(maskx <= 0){ maskx = 0; }else if(maskx >= maskMax){ maskx = maskMax; } if(masky <= 0){ masky = 0; }else if(masky >= preview.offsetHeight - mask.offsetHeight){ masky = preview.offsetHeight - mask.offsetHeight; } mask.style.left = maskx +'px'; mask.style.top = masky +'px'; //大图片的移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层的最大移动距离 var bigImg = document.querySelector('.bigImg'); //大图最大移动距离 var bigMax = bigImg.offsetWidth - big.offsetWidth; //大图的移动距离x y var bigImgx = maskx * bigMax / maskMax; var bigImgy = masky * bigMax / maskMax; bigImg.style.left = -bigImgx + 'px'; bigImg.style.top = -bigImgy + 'px'; }) </script> </body> </html>
2. 元素可视区client系列
client系列属性

clientWidth与offsetWidth最大的区别就是不包含边框
淘宝flexible.js源码分析
<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
1.立即执行函数(function(){})()
立即执行函数:不需要调用,立马能够自己执行的函数。
主要作用:创建一个独立的作用域。避免了命名冲突问题。
2.写法:
① (function(){})()或者
② (function(){}());
<script type="text/javascript">
//1.立即执行函数:不需要调用,立马能够自己执行的函数
//2.写法 也可以传递参数进来
//(function(){})() 或者 (function(){}());
(function(a,b){
console.log(a + b);
var num = 10;
})(1,2);//第二个小括号可以看做是调用函数
(function(a,b){
console.log(a + b);
var num = 10;//局部变量
}(2,3));
//3.立即执行函数最大的作用 独立创建了一个作用域 里面所有变量都是局部变量 不会有命名冲突情况
</script>
pageshow事件(重新加载页面触发)
跟load事件不同的是 pageshow这个事件在页面显示时触发,无论页面是否来自缓存。在重新加载页面中,
pageshow会在load事件触发后触发;根据事件对象中的presisted来判断是否是缓存中的页
面触发的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元素加载完毕后设置字体大小 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系列
scroll系列属性

页面被卷去的头部:可以通过window.pageYOffset 获得 如果是被卷去的左侧 window.pageXOffset
元素被卷去不透 是element.scrollTop,如果是页面被卷去头部 则是window.pageYOffset
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .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:1000px; 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 type="text/javascript"> var sliderbar = document.querySelector('.slider-bar'); var goback = document.querySelector('.goback'); var banner = document.querySelector('.banner'); var main = document.querySelector('.main'); //bannerTop 就是被卷去头部的大小 一定要写到滚动的外面 var bannerTop = banner.offsetTop; var sliderbarTop = sliderbar.offsetTop; var mainTop = main.offsetTop; //页面滚动事件scoll document.addEventListener('scroll',function(){ //window.pageYOffset 页面被卷去的头部 if(window.pageYOffset> bannerTop){ sliderbar.style.position = 'fixed'; sliderbar.style.top = sliderbarTop - bannerTop + 'px'; }else{ sliderbar.style.position = 'absolute'; sliderbar.style.top = sliderbarTop + 'px'; console.log(sliderbarTop); } //当页面滚动到main盒子 就显示goback模块 if(window.pageYOffset > mainTop){ goback.style.display = 'block'; }else{ goback.style.display = 'none'; } }) </script> </body> </html>
页面被卷去的头部 有兼容性问题,因此被卷去的头部通常有以下几种写法:
① 声明了DTD,使用document.documentElement.scrollTop
② 未声明DTD,使用document.body.scrollTop
③ 新方法window.pageYOffset 和 window.pageXOffset,IE9开始支持
三大系列对比

他们主要用法:
① offset系列经常用于获得元素位置 offsetLeft offsetTop
② client经常用于获取元素大小 clientWidth clientHeight
③ scroll经常用于获取滚动距离 scrollTop scrollLeft
mouseenter 和 mouseover的区别
· 当鼠标移动到元素上时就会触发mouseenter事件
· mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter 只经过自身盒子触发
· 因为mouseenter 不会冒泡
4.动画函数封装
4.1 动画实现原理
核心原理:通过定时器setInterval()不断移动盒子位置。
动画对象一定要加定位
<script type="text/javascript">
//动画原理
//① 获得盒子当前位置
//② 让盒子在当前位置加上1个移动距离
//③ 利用定时器不断重复这个操作
//④ 加一个结束定时器的条件
//⑤ 注意此元素需要添加定位,才能使用element.style.left
var div = document.querySelector('div');
var timer = setInterval(function(){
if(div.offsetLeft >= 400){
clearInterval(timer);
}
div.style.left = div.offsetLeft + 1 + 'px';
},30)
</script>
4.2 动画函数简单封装
注意函数需要传递2个参数,动画对象和移动到的距离。
<script type="text/javascript">
//var obg = {};
//obg.name = 'andy';
//简单动画函数封装obj目标对象 target 目标位置
function animate(obg,target){
//当我们不断的点击按钮,这个元素的速度会越来越快 因为开启了太多的定时器
//解决方案就是 让元素只有一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function(){
if(obg.offsetLeft >= target){
clearInterval(timer);
}
obg.style.left = obg.offsetLeft + 1 + 'px';
},30)
}
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
animate(span,400);
})
animate(div,300);
</script>
4.4缓动效果原理
缓动动画公式:(目标值 - 现在的位置) / 10 作为每次移动的距离步长
匀速动画 就是 盒子当前的位置 + 固定的值 10
缓动动画 就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置)/10
<button class="btn800">点击夏雨湖到800</button>
<button class="btn300">点击夏雨湖到300</button>
<div></div>
<span></span>
<script type="text/javascript">
//var obg = {};
//obg.name = 'andy';
var span = document.querySelector('span');
var div = document.querySelector('div');
//简单动画函数封装obj目标对象 target 目标位置
function animate(obj,target){
//当我们不断的点击按钮,这个元素的速度会越来越快 因为开启了太多的定时器
//解决方案就是 让元素只有一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function(){
//缓动动画公式:(目标值 - 现在的位置) / 10 作为每次移动的距离步长
//把步长值改为整数 不要出现小数问题
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == target){
clearInterval(obj.timer);
}
//把每次加1 这个步长值改为一个慢慢变小的值
obj.style.left = obj.offsetLeft + step + 'px';
},40)
}
var btn800 = document.querySelector('.btn800');
var btn300 = document.querySelector('.btn300');
btn800.addEventListener('click',function(){
animate(span,800);
});
btn300.addEventListener('click',function(){
animate(span,300);
})
//匀速动画 就是 盒子当前的位置 + 固定的值 10
//缓动动画 就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置)/10
</script>
4.6 动画函数添加回调函数
回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行穿进去的这个函数,这个过程叫回调
回调函数 写到定时器结束里面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
width: 200px;
height: 200px;
background-color: pink;
position: absolute;
}
span{width: 300px;
height: 300px;
background-color: purple;
position: absolute;
}
</style>
</head>
<body>
<button class="btn800">点击夏雨湖到800</button>
<button class="btn300">点击夏雨湖到300</button>
<div></div>
<span></span>
<script type="text/javascript">
//var obg = {};
//obg.name = 'andy';
var span = document.querySelector('span');
var div = document.querySelector('div');
//简单动画函数封装obj目标对象 target 目标位置
function animate(obj,target,callback){
//当我们不断的点击按钮,这个元素的速度会越来越快 因为开启了太多的定时器
//解决方案就是 让元素只有一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function(){
//缓动动画公式:(目标值 - 现在的位置) / 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();
}
}
//把每次加1 这个步长值改为一个慢慢变小的值
obj.style.left = obj.offsetLeft + step + 'px';
},40)
}
var btn800 = document.querySelector('.btn800');
var btn300 = document.querySelector('.btn300');
btn800.addEventListener('click',function(){
animate(span,800,function(){
span.style.backgroundColor = 'yellow';
});
});
btn300.addEventListener('click',function(){
animate(span,300,function(){
span.style.backgroundColor = 'yellow';
})
})
//匀速动画 就是 盒子当前的位置 + 固定的值 10
//缓动动画 就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置)/10
</script>
</body>
</html>
轮播图案例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="../js/animate.js" type="text/javascript"></script> <script src="../js/rotation.js" type="text/javascript" charset="utf-8"></script> <style type="text/css"> *{ padding: 0; margin: 0; } ul,ol{ list-style: none; } .focus{ position: relative; width: 720px; height: 455px; background-color: purple; overflow: hidden; } .focus li img{ width: 720px; height: 455px; } .focus ul{ position: absolute; top: 0; left: 0; width: 600%; } .focus ul li{ float: left; } .arrow-l,.arrow-r{ position: absolute; display: none; top: 50%; margin-top: -20px; width: 24px; height: 40px; background:rgba(0,0,0,.3); text-align: center; line-height: 40px; z-index: 999; } .arrow-r{ right: 0; } .circle{ position: absolute; bottom: 10px; left: 50px; } .circle li{float: left; width: 8px; height: 8px; border: 2px solid rgba(255,255,255,.5); margin: 0 3px; border-radius: 50%; cursor: pointer; } .current{ background-color: #fff; } </style> </head> <body> <div class ="focus"> <!--左侧按钮--> <a href="javascript:;" class="arrow-l"><</a> <!--右侧按钮--> <a href="javascript:;" class="arrow-r">></a> <!--核心滚动区域--> <ul> <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> <li><a href="#"><img src="../upload/focus4.jpg" alt="" /></a></li> </ul> <!--小圆圈--> <ol class="circle"> </ol> </div> </body> </html>
//var obg = {}; //obg.name = 'andy'; //简单动画函数封装obj目标对象 target 目标位置 function animate(obj,target,callback){ //当我们不断的点击按钮,这个元素的速度会越来越快 因为开启了太多的定时器 //解决方案就是 让元素只有一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function(){ //缓动动画公式:(目标值 - 现在的位置) / 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(); } } //把每次加1 这个步长值改为一个慢慢变小的值 obj.style.left = obj.offsetLeft + step + 'px'; },40) }
window.addEventListener('load',function(){
//1.获取元素
var arrow_l = document.querySelector('.arrow-l');
var arrow_r = document.querySelector('.arrow-r');
var focus = document.querySelector('.focus');
var focusWidth = focus.offsetWidth;
//2、鼠标经过focus 就显示隐藏左右按钮
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)
})
//3.动态生成小圆圈 有几张图 就生成几个小圆圈
var ul = focus.querySelector('ul');
var ol = focus.querySelector('.circle');
for(var i = 0; i< ul.children.length; i++){
//创建一个li
var li = document.createElement('li');
//记录当前小圆圈的索引号 通过自定义属性来做
li.setAttribute('index',i);
//把li插入到ol里面
ol.appendChild(li);
//4.小圆圈排他思想 直接生成小圆圈的同时 直接帮定点击事件
li.addEventListener('click',function(){
//把所有li清除current 类名
for(var i = 0;i < ol.children.length; i++){
ol.children[i].className = '';
}
//当前的li 设置current类名
this.className = 'current';
//5.点击小圆圈,移动图片 移动的是ul
//ul 的移动距离 = 小圆圈的索引号 * 图片的宽度 注意 是负值
//当点击了某个li 就拿到当前li的索引号
var index = this.getAttribute('index');
//当点击li 就把当前的索引号 给num
num = index;
animate(ul,-index*focusWidth);
//当点击li 就把当前的索引号 给circle
circle = index;
})
}
ol.children[0].className = 'current';
//6.克隆第一张图片(li)放到ul最后面
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);
//7.点击右侧按钮,图片滚动一张
var num = 0;
//circle 控制小圆圈的播放
var circle = 0;
//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; //打开节流阀
});
//8.点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
circle++;
//如果circle == 4 说明走到最后克隆的这张图片了 就复原
if(circle == ol.children.length){
circle = 0;
}
circleChange();
}
});
//左侧按钮做法
arrow_l.addEventListener('click',function(){
if(flag){
flag = false; //关闭节流阀
//如果走到最后 复制的一张图片,此时 ul要快速复原 left 改为0
if(num == 0){
ul.style.left = -num * focusWidth + 'px';
num = ul.children.length - 1;
}
num--;
animate(ul, -num * focusWidth,function(){
flag = true; //打开节流阀
});
//8.点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
circle--;
//如果circle <0 说明 第一张图片,则小圆圈要改为第4个小圆圈
// if(circle < 0){
// circle = ol.children.length - 1;
// }
circle = circle < 0 ? ol.children.length - 1 : circle;
circleChange();
}
});
function circleChange(){
//先清除其余小圆圈的current类名
for(var i = 0; i< ol.children.length;i++){
ol.children[i].className = '';
}
ol.children[circle].className ='current';
}
//10.自动播放图片
var timer = setInterval(function(){
//手动调用点击事件
arrow_r.click();
},2000)
})
5.常见网页特效案例
5.1 节流阀
防止轮播图按钮连续点击造成播放过快。
节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让世界无法连续触发。
核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
开始设置一个变量var flag = true;
if(flag){flag = flase; do something}关闭水龙头 代码在ratationJS
返回顶部案例
//3.当我们点击了返回顶部模块 就让窗口滚动到页面最上方 goback.addEventListener('click',function(){ //里面的x和y 不跟单位 直接写数字 //.scroll(0,0); //因为是窗口 所以对象是window animate(window,0); }); //简单动画函数封装obj目标对象 target 目标位置 function animate(obj,target,callback){ //当我们不断的点击按钮,这个元素的速度会越来越快 因为开启了太多的定时器 //解决方案就是 让元素只有一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function(){ //缓动动画公式:(目标值 - 现在的位置) / 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(); } //把每次加1 这个步长值改为一个慢慢变小的值 window.scroll(0,window.pageYOffset + step); },15) }
导航筋斗云效果 案例(调用的animate函数在上面的animateJS)
<div id="c_nav" class="c-nav">
<!--筋斗云图片-->
<span class="cloud"></span>
<ul>
<li class='current'><a href="#">首页新闻</a></li>
<li><a href="#">师资力量</a></li>
<li><a href="#">活动策划</a></li>
<li><a href="#">企业文化</a></li>
<li><a href="#">公司简介</a></li>
<li><a href="#">连续我们</a></li>
</ul>
</div>
<script src="../js/animate.js" type="text/javascript" charset="utf-8"></script>
<script>
var cloud = document.querySelector('.cloud');
var c_nav = document.querySelector('.c-nav');
var lis = c_nav.querySelector('li');
//给所有li绑定事件
//这个current作为筋斗云的起始位置
var current = 0;
for(var i = 0; i< lis.length;i++){
//鼠标经过把当前li的位置作为目标值
lis[i].addEventListener('mouseenter',function(){
animate(cloud,this.offsetLeft);
})
//鼠标离开就复原为0回到起始位置
lis[i].addEventListener('mouseleave',function(){
animate(cloud,current);
})
//当鼠标点击,就把当前位置作为目标值
lis[i].addEventListener('click',function(){
current = this.offsetLeft;
})
}
</script>

浙公网安备 33010602011771号