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>
View Code

 仿京东放大镜效果 案例

<!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>
View Code

 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))
flexible注释详解

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">&lt;</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>
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)
            }
animateJS
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)

})
ratationJS

 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>

 

posted @ 2020-08-18 20:11  哈喽诗涵  阅读(143)  评论(0)    收藏  举报