02 - JavaScript APIs - 04.PC端网页特效

PC端网页特效

元素偏移量 offset 系列

offset 概述

  • 使用 offset 系列相关属性可动态地得到元素的位置(偏移)、大小等【注:返回的数值都不带单位】
    1.获得元素距离带有定位父元素的位置
    2.获得元素自身的大小(宽度高度)
  • element.offsetParent【返回作为该元素带有定位的父级元素,若父级都没有,则返回 body】
    【注:element.parentNode 不管父亲有没有定位,都返回最近一级的父亲】
  • element.offsetTop【返回元素相对带有定位父元素上方的偏移】
    element.offsetLeft【返回元素相对带有定位父元素左边框的偏移】
  • element.offsetWidth【返回自身,包括 padding、边框、内容区的宽度,返回数值不带单位】
    element.offsetHeight【返回自身,包括 padding、边框、内容区的高度,返回数值不带单位】

offset 与 style 区别

  • offset
    1.可得到任意样式表中的样式值
    2.获得的数值无单位
    3.offsetWidth 包含 padding + border + width
    4.offsetWidth 只读,不能赋值
  • style
    1.只能得到行内样式表中的样式值
    2.获得的数值有单位
    3.style.width 不包含 padding 及 border
    4.style.width 可读写,可赋值

示例

  • 获取鼠标在盒子内的坐标
    // 获取鼠标在盒子内的坐标
    <head>
    	<style>
            .box {
                width: 300px;
                height: 300px;
                background-color: pink;
                margin: 200px;
            }
        </style>
    </head>
    
    <body>
        <div class="box"></div>
        <script>
            var box = document.querySelector('.box');
            box.addEventListener('mousemove', function(e) {
                var x = e.pageX - this.offsetLeft;
                var y = e.pageY - this.offsetTop;
                this.innerHTML = 'x坐标是' + x + ' y坐标是' + y;
            })
        </script>
    </body>
    
  • 模态框拖拽
    // 模态框拖拽
    <head lang="en">
        <style>
            .login-header {
                width: 100%;
                text-align: center;
                height: 30px;
                font-size: 24px;
                line-height: 30px;
            }
            ul, li, ol, dl, dt, dd, div, p, span, h1, h2, h3, h4, h5, h6, a {
                padding: 0px;
                margin: 0px;
            }
            .login {
                display: none;
                width: 512px;
                height: 280px;
                position: fixed;
                border: #ebebeb solid 1px;
                left: 50%;
                top: 50%;
                background: #ffffff;
                box-shadow: 0px 0px 20px #ddd;
                z-index: 9999;
                transform: translate(-50%, -50%);
            }
            .login-title {
                width: 100%;
                margin: 10px 0px 0px 0px;
                text-align: center;
                line-height: 40px;
                height: 40px;
                font-size: 18px;
                position: relative;
                cursor: move;
            }
            .login-input-content {
                margin-top: 20px;
            }
            .login-button {
                width: 50%;
                margin: 30px auto 0px auto;
                line-height: 40px;
                font-size: 14px;
                border: #ebebeb 1px solid;
                text-align: center;
            }
            .login-bg {
                display: none;
                width: 100%;
                height: 100%;
                position: fixed;
                top: 0px;
                left: 0px;
                background: rgba(0, 0, 0, .3);
            }
            a {
                text-decoration: none;
                color: #000000;
            }
            .login-button a {
                display: block;
            }
            .login-input input.list-input {
                float: left;
                line-height: 35px;
                height: 35px;
                width: 350px;
                border: #ebebeb 1px solid;
                text-indent: 5px;
            }
            .login-input {
                overflow: hidden;
                margin: 0px 0px 20px 0px;
            }
            .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: #ffffff;
                border: #ebebeb solid 1px;
                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 id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
            </div>
            <div class="login-input-content">
                <div class="login-input">
                    <label>用户名:</label>
                    <input type="text" placeholder="请输入用户名" name="info[username]" id="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>
            var login = document.querySelector('.login');
            var mask = document.querySelector('.login-bg');
            var link = document.querySelector('#link');
            var closeBtn = document.querySelector('#closeBtn');
            var title = document.querySelector('#title');
            
            link.addEventListener('click', function() {
            	mask.style.display = 'block';
            	login.style.display = 'block';
          	})
            closeBtn.addEventListener('click', function() {
             	mask.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>
    </body>
    
  • 仿京东放大镜
    // 仿京东放大镜
    // detail.js
    window.addEventListener('load', function() {  // HTML、CSS 等内容加载完成时触发
        var preview_img = document.querySelector('.preview_img');
        var mask = document.querySelector('.mask');
        var big = document.querySelector('.big');
        
        preview_img.addEventListener('mouseover', function() {
            mask.style.display = 'block';
            big.style.display = 'block';
        })
        preview_img.addEventListener('mouseout', function() {
            mask.style.display = 'none';
            big.style.display = 'none';
        })
    
        preview_img.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 = preview_img.offsetWidth - mask.offsetWidth;  // 计算 mask 真正可利用的宽高
       		if (maskX <= 0) {  // mask 不能超出小图片盒子范围
                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';
            
            var bigIMg = document.querySelector('.bigImg');
            var bigMax = bigIMg.offsetWidth - big.offsetWidth;
            var bigX = maskX * bigMax / maskMax;  // 大图移动距离 = mask 移动距离 * 大图最大移动距离 / mask 最大移动距离 【比例】
            var bigY = maskY * bigMax / maskMax;
            bigIMg.style.left = -bigX + 'px';
            bigIMg.style.top = -bigY + 'px';
        })
    })
    
    // detail.html
    <div class="preview_img">
    	<img src="upload/s3.png" alt="">
        <div class="mask"></div>
        <div class="big">
            <img src="upload/big.jpg" alt="" class="bigImg">
        </div>
    </div>
    
    // detail.css
    .preview_img {
        position: relative;
        height: 398px;
        border: 1px solid #ccc;
    }
    .mask {
        display: none;
        position: absolute;
        top: 0;
        left: 0;
        width: 300px;
        height: 300px;
        background: #FEDE4F;
        opacity: .5;
        border: 1px solid #ccc;
        cursor: move;
    }
    .big {
        display: none;
        position: absolute;
        left: 410px;
        top: 0;
        width: 500px;
        height: 500px;
        background-color: pink;
        z-index: 999;
        border: 1px solid #ccc;
        overflow: hidden;
    }
    .big img {
        position: absolute;
        top: 0;
        left: 0;
    }
    

元素可视区 client 系列

client 概述

  • 使用 client 系列相关属性来获取元素可视区的相关信息
  • 通过 client 系列相关属性可动态地得到该元素的边框大小、元素大小等
  • element.clientTop【返回元素上边框大小】
    element.clientLeft【返回元素左边框大小】
  • element.clientWidth【返回自身包括padding、内容区的宽度,不含边框,返回值不带单位】
    element.clientHeight【返回自身包括padding、内容区的宽度,不含边框,返回值不带单位】

立即执行函数

  • 立即执行函数:不需调用,立马能自己执行的函数
  • 作用:独立创建了一个作用域,里面所有的变量都是局部变量,不会有命名冲突的情况
  • (function() {}) ()【写法一】【常用】
    (function() {} ())【写法二】
    <body>
        <script>
            (function(a, b) {  // 写法一
                console.log(a + b);
                var num = 10;  // 局部变量
            })(1, 2);  // 第二个小括号可看做调用函数
            // Uncaught TypeError: (intermediate value)(...) is not a function 【此报错是因为立即执行函数之间未加分号】
            (function sum(a, b) {  // 写法二
                console.log(a + b);
                var num = 10;  // 局部变量
            }(2, 3));
        </script>
    </body>
    
    ;  // 注意分号
    (function() {
    }());
    

示例

  • 淘宝 flexible.js 源码分析
    1.刷新页面会触发 load 事件的三种情况:
    ①a 标签的超链接;②F5 或 刷新按钮(强制刷新);③前进后退按钮
    2.火狐的往返缓存,保存页面数据、DOM状态、JS状态【实际是将整个页面都保存在内存中】,故此时后退按钮不能刷新页面。【火狐已修复此 bug】
    3.pageshow 事件是重新加载页面触发的事件,无论页面是否来自缓存。在重新加载页面中,pageshow 会在 load 事件触发后触发
    4.根据事件对象中的 persisted 可判断是否为缓存中的页面触发的 pageshow 事件
    5.pageshow 事件给 window 添加
    // 淘宝 flexible.js 源码分析
    // flexible.js
    (function flexible(window, document) {
        var docEl = document.documentElement  // 获取的 html 根元素
        var dpr = window.devicePixelRatio || 1  // 物理像素比【PC端为1;移动端不为1,如iphone6,8中为2】
    
        function setBodyFontSize() {
            if (document.body) {
                document.body.style.fontSize = (12 * dpr) + 'px'
            } else {
                document.addEventListener('DOMContentLoaded', setBodyFontSize)  // DOM 加载完后 再设body 的字体大小
            }
        }
        setBodyFontSize();
    
        function setRemUnit() {
            var rem = docEl.clientWidth / 10  // 设置 html 元素的文字大小
            docEl.style.fontSize = rem + 'px'
        }
        setRemUnit()
    
        window.addEventListener('resize', setRemUnit)  // 页面尺寸大小发生变化时,重新设置 rem 大小
        window.addEventListener('pageshow', function(e) {  // pageshow 重新加载页面触发的事件
            if (e.persisted) {  // 如果页面是从缓存取过来的页面,需重新计算 rem 大小
                setRemUnit()
            }
        })
    
        if (dpr >= 2) {  // detect 0.5px supports  有些移动端浏览器不支持0.5像素的写法
            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))
    
    // index.html
    <head>
        <script src="flexible.js"></script>
    </head>
    
    <body>
        <script>
            // console.log(window.devicePixelRatio);
            window.addEventListener('pageshow', function() {
                alert(11);
            })
        </script>
        <a href="http://www.itcast.cn">链接</a>
    </body>
    

元素滚动 scroll 系列

scroll 概述

  • 使用 scroll 系列相关属性可动态地得到该元素的大小、滚动距离等
  • element.scrollTop【返回被卷去的上侧距离,返回值无单位】【页面被卷去的头部:滚动条向下滚动时,页面上面被隐藏掉的高度】
    element.scrollLeft【返回被卷去的左侧距离,返回值无单位】
  • element.scrollWidth【返回自身实际的宽度,不含边框,返回值无单位】
    element.scrollHeight【返回自身实际的高度,不含边框,返回值无单位】
  • 滚动条在滚动时会触发 onscroll 事件

页面被卷去的头部

  • 有兼容性问题
    1.声明了 DTD,用 document.documentElement.scrollTop
    2.未声明 DTD,用 document.body.scrollTop
    3.新方法,window.pageYOffsetwindow.pageXOffset【IE9+支持】
    注:DTD:<!DOCTYPE html> </html>
    function getScroll() {
    	return {
     		left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
    		top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
     	};
    } 
    // 使用:getScroll().left
    

示例

  • 仿淘宝固定右侧侧边栏
    1.window.pageYOffset【页面被卷去的头部】
    element.scrollTop【元素被卷去的头部】
    2.window.scroll(x, y)【滚动窗口至文档中的特定位置】【x、y不带单位】
    // 仿淘宝固定右侧侧边栏
    /* 
    	1. 原先侧边栏是绝对定位
       	2. 当页面滚动到一定位置,侧边栏改为固定定位
       	3. 页面继续滚动,会让 返回顶部显示出来
    */
    <head>
        <style>
            .slider-bar {
                position: absolute;
                left: 50%;
                top: 300px;
                margin-left: 600px;
                width: 45px;
                height: 130px;
                background-color: pink;
            }
            .w {
                width: 1200px;
                margin: 10px auto;
            }
            .header {
                height: 150px;
                background-color: purple;
            }
            .banner {
                height: 250px;
                background-color: skyblue;
            }
            .main {
                height: 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>
            var sliderbar = document.querySelector('.slider-bar');
            var banner = document.querySelector('.banner');
            var main = document.querySelector('.main');
            var goBack = document.querySelector('.goBack');
            var bannerTop = banner.offsetTop
            var sliderbarTop = sliderbar.offsetTop - bannerTop;  // 侧边栏固定定位后应变化的数值
            var mainTop = main.offsetTop;
    
            document.addEventListener('scroll', function() {
    	        if (window.pageYOffset >= bannerTop) {
    	            sliderbar.style.position = 'fixed';
    	            sliderbar.style.top = sliderbarTop + 'px';
    	        } else {
    	            sliderbar.style.position = 'absolute';
    	            sliderbar.style.top = '300px';
    	        }
    
                if (window.pageYOffset >= mainTop) {
                    goBack.style.display = 'block';
                } else {
                    goBack.style.display = 'none';
                }
    		})
    
            goBack.addEventListener('click', function() {
                // window.scroll(0, 0);  // x、y 不跟单位 直接写数字即可
                animate(window, 0);  // 因为是窗口滚动 所以对象是window
            });
            
            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);
                        callback && callback();  // 回调函数写到定时器结束里面
                    }
                    window.scroll(0, window.pageYOffset + step);
                }, 15);
            }
        </script>
    </body>
    

offset、client、scroll 三大系列总结

  • offset:常用于获得元素位置 offsetLeftoffsetTop
  • client:常用于获取元素大小 clientWidthclientHeight
  • scroll:常用于获取滚动距离 scrollTopscrollLeft
    注:页面滚动的距离通过 window.pageXOffset 获得
    在这里插入图片描述

mouseenter 与 mouseover 的区别

  • mouseovermouseout:鼠标经过 / 离开自身盒子会触发,经过 / 离开 子盒子还会触发【会冒泡】
  • mouseentermouseleave:鼠标只会经过 / 离开自身盒子触发【不会冒泡】

动画函数封装

动画实现原理

  • 通过定时器 setInterval() 不断移动盒子位置
    【注意:此元素需添加定位,才能使用 element.style.left,即若不加 position,无法移动】

动画函数给不同元素记录不同定时器

  • 给不同对象添加不同定时器
    ①obj.timer 避免生命周期内,再在内存中开辟空间
    ②区分是哪个对象的 timer
  • 核心原理:JS 动态语言,方便给当前对象添加属性

缓动效果原理

  • 让元素运动速度有所变化,常见的是让速度慢慢停下来
  • 算法:var step = (目标值 - 现在的位置 ) / 10
    step = step > 0 ? Math.ceil(step) : Math.floor(step)
    【步长值需要取整,否则有像素精度问题】
    【若为正值,则往大取整;若为负值,则往小取整】
  • 回调函数原理:函数可作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调【回调函数写的位置:定时器结束的位置】
  • setInterval 一般设 time 为 15ms【经验】

代码

// animate.js
function animate(obj, target, callback) {
	clearInterval(obj.timer);  // 防止定时器太多,导致元素速度过快
	obj.timer = setInterval(function() {
	    var step = (target - obj.offsetLeft) / 10;
	    step = step > 0 ? Math.ceil(step) : Math.floor(step);
	    if (obj.offsetLeft == target) {
	        clearInterval(obj.timer);
	        callback && callback();
	    }
	    obj.style.left = obj.offsetLeft + step + 'px';
	}, 15);  // 15 是经验所得,此值做的动画较流畅
}
	
// index.html
<head>
    <style>
        .sliderbar {
            position: fixed;
            right: 0;
            bottom: 100px;
            width: 40px;
            height: 40px;
            text-align: center;
            line-height: 40px;
            cursor: pointer;
            color: #fff;
        }
        .con {
            position: absolute;
            left: 0;
            top: 0;
            width: 200px;
            height: 40px;
            background-color: purple;
            z-index: -1;
        }
    </style>
    <script src="animate.js"></script>
</head>

<body>
    <div class="sliderbar">
        <span></span>
        <div class="con">问题反馈</div>
    </div>

    <script>
        var sliderbar = document.querySelector('.sliderbar');
        var con = document.querySelector('.con');
        sliderbar.addEventListener('mouseenter', function() {
            animate(con, -160, function() {
                sliderbar.children[0].innerHTML = '→';
            });
        })
        sliderbar.addEventListener('mouseleave', function() {
            animate(con, 0, function() {
            	sliderbar.children[0].innerHTML = '←';
            });
        })
    </script>
</body>

常见网页特效案例

网页轮播图

// animate.js
function animate(obj, target, callback) {
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
            callback && callback();
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15);
}

// index.js
// index.js 依赖 animate.js。故 animate.js 要写到 index.js 前面
window.addEventListener('load', function() {
    var arrow_l = document.querySelector('.arrow-l');
    var arrow_r = document.querySelector('.arrow-r');
    var focus = document.querySelector('.focus');
    var focusWidth = focus.offsetWidth;

    focus.addEventListener('mouseenter', function() {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
        clearInterval(timer);
        timer = null;  // 清除定时器变量
    });
    focus.addEventListener('mouseleave', function() {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
        timer = setInterval(function() {
            arrow_r.click();  // 手动调用点击事件
        }, 2000);
    });

    var ul = focus.querySelector('ul');
    var ol = focus.querySelector('.circle');
    for (var i = 0; i < ul.children.length; i++) {
        var li = document.createElement('li');
        li.setAttribute('index', i);
        ol.appendChild(li);
        li.addEventListener('click', function() {
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            this.className = 'current';

            var index = this.getAttribute('index');
            num = index;
            circle = index;
            animate(ul, -index * focusWidth);
        })
    }
    ol.children[0].className = 'current';
    
    var first = ul.children[0].cloneNode(true);  // 深克隆第一张图片 li 放到 ul 最后面【无缝滚动】
    ul.appendChild(first);

    var num = 0;
    var circle = 0;
    /*
    	节流阀【防止轮播图按钮连续点击造成播放过快】
    	目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画
    	思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数
    	开始设置 var flag = true;
		if (flag) {flag = false; do something}  // 关闭水龙头
		利用回调函数,动作执行完毕 flag = true  // 打开水龙头
    */
    var flag = true;  // 节流阀
    arrow_r.addEventListener('click', function() {
        if (flag) {
            flag = false;  // 关闭节流阀
            if (num == ul.children.length - 1) {  // 不做动画,快速跳转
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * focusWidth, function() {
                flag = true;  // 打开节流阀
            });
            circle++;
            if (circle == ol.children.length) {
                circle = 0;
            }
            circleChange();
        }
    });
    arrow_l.addEventListener('click', function() {
        if (flag) {
            flag = false;
            if (num == 0) {  // 不做动画
            	num = ul.children.length - 1;
                ul.style.left = -num * focusWidth + 'px';
            }
            num--;
            animate(ul, -num * focusWidth, function() {
                flag = true;
            });
            circle--;
            circle = circle < 0 ? ol.children.length - 1 : circle;
            circleChange();
        }
    });

    function circleChange() {
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        ol.children[circle].className = 'current';
    }
    var timer = setInterval(function() {
        arrow_r.click();
    }, 2000);
})

// index.html
<div class="focus fl">
	<a href="javascript:;" class="arrow-l"> &lt; </a>
	<a href="javascript:;" class="arrow-r"></a>
   	<ul>
       	<li>
           	<a href="#"><img src="upload/focus.jpg" alt=""></a>
       	</li>
       	<li>
           	<a href="#"><img src="upload/focus1.jpg" alt=""></a>
       	</li>
       	<li>
           	<a href="#"><img src="upload/focus2.jpg" alt=""></a>
       	</li>
       	<li>
           	<a href="#"><img src="upload/focus3.jpg" alt=""></a>
       	</li>
   	</ul>
   	<ol class="circle">
   	</ol>
</div>

// index.css
.main {
    width: 980px;
    height: 455px;
    margin-left: 219px;
    margin-top: 10px;
}
.focus {
    position: relative;
    width: 721px;
    height: 455px;
    background-color: purple;
    overflow: hidden;
}
.focus ul {
    position: absolute;
    top: 0;
    left: 0;
    width: 600%;
}
.focus ul li {
    float: left;
}
.arrow-l,
.arrow-r {
    display: none;
    position: absolute;
    top: 50%;
    margin-top: -20px;
    width: 24px;
    height: 40px;
    background: rgba(0, 0, 0, .3);
    text-align: center;
    line-height: 40px;
    color: #fff;
    font-family: 'icomoon';
    font-size: 18px;
    z-index: 2;
}
.arrow-r {
    right: 0;
}
.circle {
    position: absolute;
    bottom: 10px;
    left: 50px;
}
.circle li {
    float: left;
    width: 8px;
    height: 8px;
    /*background-color: #fff;*/
    border: 2px solid rgba(255, 255, 255, 0.5);
    margin: 0 3px;
    border-radius: 50%;
    cursor: pointer;
}
.current {
    background-color: #fff;
}

筋斗云

// animate.js
function animate(obj, target, callback) {
	clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
            callback && callback();
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15);
}

// demo.html
<head lang="en">
    <style>
		* {
            margin: 0;
            padding: 0
        }
        ul {
            list-style: none;
        }
        body {
            background-color: black;
        }
        .c-nav {
            width: 900px;
            height: 42px;
            background: #fff url(images/rss.png) no-repeat right center;
            margin: 100px auto;
            border-radius: 5px;
            position: relative;
        }
        .c-nav ul {
            position: absolute;
        }
        .c-nav li {
            float: left;
            width: 83px;
            text-align: center;
            line-height: 42px;
        }
        .c-nav li a {
            color: #333;
            text-decoration: none;
            display: inline-block;
            height: 42px;
        }
        .c-nav li a:hover {
            color: white;
        }
        .c-nav li.current a {
            color: #0dff1d;
        }
        .cloud {
            position: absolute;
            left: 0;
            top: 0;
            width: 83px;
            height: 42px;
            background: url(images/cloud.gif) no-repeat;
        }
    </style>
    <script src="animate.js"></script>
    <script>
        window.addEventListener('load', function() {
      		var cloud = document.querySelector('.cloud');
            var c_nav = document.querySelector('.c-nav');
            var lis = c_nav.querySelectorAll('li');
            var current = 0;
            for (var i = 0; i < lis.length; i++) {
                lis[i].addEventListener('mouseenter', function() {
                    animate(cloud, this.offsetLeft);
                });
                lis[i].addEventListener('mouseleave', function() {
                    animate(cloud, current);
                });
                lis[i].addEventListener('click', function() {
                    current = this.offsetLeft;
                });
            }
        })
    </script>
</head>

<body>
    <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>
            <li><a href="#">我是佩奇</a></li>
            <li><a href="#">啥是佩奇</a></li>
        </ul>
    </div>
</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值