PC 端网页特效

目录

1. 元素偏移量 offset 系列

1.1 offset 概述

1.2 offset 与 style 区别

1.3案例:获取鼠标在盒子内的坐标

1.4案例:模态框拖拽

1.5案例:仿京东放大镜

2. 元素可视区 client 系列

3. 元素滚动 scroll 系列

3.1 元素 scroll 系列属性

3.2 页面被卷去的头部

4、总结

4.1三大系列总结

4.2mouseenter 和mouseover的区别

5. 动画函数封装

5.1 动画实现原理

5.2 动画函数简单封装

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

5.4 缓动效果原理

5.5 动画函数多个目标值之间移动(回调函数)

5.6动画函数封装到单独JS文件里面


#博学谷IT学习技术支持#

1. 元素偏移量 offset 系列

1.1 offset 概述

offset 翻译过来就是偏移量, 我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏

移)、大小等。

1.获得元素距离带有定位父元素的位置
2.获得元素自身的大小(宽度高度)
3.注意: 返回的数值都不带单位

代码演示:

<style>
        .box {
            position: absolute;
            padding: 10px;
            width: 300px;
            height: 300px;
            border: 5px solid #000;
            background-color: pink;
        }

        .box div {
            margin: 50px 50px;
            width: 100px;
            height: 100px;
            padding: 10px;
            background-color: aquamarine;
            border: 5px solid #000;
        }
    </style>
</head>

<body>
    <div class="box">
        <div></div>
    </div>

    <script>
        var box = document.querySelector('.box');
        //offsetParent返回该元素带有定位的父级元素
        console.log(box.children[0].offsetParent);
        //offsetTop返回元素相对定位元素上边框的偏移  
        console.log(box.children[0].offsetTop); //60
        //offsetLeft返回元素相对定位元素左边框的偏移
        console.log(box.children[0].offsetLeft);  //60
        //offsetWith返回自身包括内边距,边框,内容的宽度
        console.log(box.children[0].offsetWidth); //130
        //offsetHeight返回自身包括内边距,边框,内容的高度
        console.log(box.children[0].offsetHeight);  //130
    </script>
</body>

1.2 offset 与 style 区别

offset:
1.offset 可以得到任意样式表中的样式值
2.offset 系列获得        的数值是没有单位的
3.offsetWidth 包含padding+border+width
4.offsetWidth 等属性是只读属性,只能获取不能赋值
所以,我们想要获取元素大小位置,用offset更合适
style:
1.style 只能得到行内样式表中的样式值
2.style.width 获得的是带有单位的字符串
3.style.width 获得不包含padding和border 的值
4.style.width 是可读写属性,可以获取也可以赋值
所以,我们想要给元素更改值,则需要用style改变

1.3案例:获取鼠标在盒子内的坐标

代码演示:

<style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            margin: 50px auto;
            width: 300px;
            height: 300px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div class="box"></div>

    <script>
        // ① 我们在盒子内点击,想要得到鼠标距离盒子左右的距离。
        // ② 首先得到鼠标在页面中的坐标(e.pageX, e.pageY)
        // ③ 其次得到盒子在页面中的距离 ( box.offsetLeft, box.offsetTop)
        // ④ 用鼠标距离页面的坐标减去盒子在页面中的距离,得到 鼠标在盒子内的坐标
        // ⑤ 如果想要移动一下鼠标,就要获取最新的坐标,使用鼠标移动事件 mousemove

        var box = document.querySelector('.box');
        box.addEventListener('click', fn);
        function fn(e) {
            //得到鼠标在页面中的坐标(e.pageX, e.pageY)
            var X = e.pageX;
            var Y = e.pageY;
            //得到盒子在页面中的距离 ( box.offsetLeft, box.offsetTop)
            var x = box.offsetLeft;
            var y = box.offsetTop;
            //用鼠标距离页面的坐标减去盒子在页面中的距离,得到 鼠标在盒子内的坐标
            var x1 = X - x;
            var y1 = Y - y;
            console.log(X,x);
            console.log(Y,y);
            console.log(x1, y1);
        }
    </script>
</body>

1.4案例:模态框拖拽

弹出框,我们也称为模态框。
1. 点击弹出层, 会弹出模态框, 并且显示灰色半透明的遮挡层。
2. 点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡层。
3. 鼠标放到模态框最上面一行,可以按住鼠标拖拽模态框在页面中移动。
4. 鼠标松开,可以停止拖动模态框移动。
代码演示:
<style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        a {
            text-decoration: none;
            color: #000000;
        }

        .login-header {
            text-align: center;
        }

        .login {
            display: none;
            position: absolute;
            left: 50%;
            top: 50%;
            width: 500px;
            height: 280px;
            background-color: #fff;
            border: #ebebeb solid 1px;
            transform: translate(-50%, -50%);
            z-index: 1000;
        }

        .mask {
            display: none;
            width: 100%;
            height: 100%;
            position: fixed;
            top: 0px;
            left: 0px;
            background: rgba(0, 0, 0, .3);
        }

        .login-title {
            text-align: center;
            line-height: 50px;
            border-bottom: 1px solid rgba(0, 0, 0, .1);
        }

        input {
            width: 300px;
            height: 35px;
            border: 1px solid #000;
        }

        .login-content {
            padding-left: 40px;
            margin-top: 40px;
        }

        .input-txt {
            margin-bottom: 20px;
        }

        .input-pwd input {
            margin-left: 16px;
        }

        .loginBtn {
            margin-top: 30PX;
            text-align: center;
        }

        .loginBtn input {
            width: 200px;
        }

        .circle {
            position: absolute;
            right: -25px;
            top: -25px;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            text-align: center;
            line-height: 50px;
            background-color: #fff;
            cursor: pointer;
        }
    </style>
</head>

<body>
    <!-- 1. 点击弹出层, 会弹出模态框, 并且显示灰色半透明的遮挡层。

        2. 点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡层。

        3. 鼠标放到模态框最上面一行,可以按住鼠标拖拽模态框在页面中移动。

        4. 鼠标松开,可以停止拖动模态框移动。 -->

    <!-- 1.点击弹出层 -->
    <div class="login-header"><a href="javascript:;" class="link">点击,弹出登录框</a></div>
    <div class="login">
        <div class="login-title">登录会员</div>
        <div class="login-content">
            <form action="">
                <div class="input-txt">
                    <label for="">
                        用户名:<input type="text" name="uname" id="">
                    </label>
                </div>
                <div class="input-pwd">
                    <label for="">
                        密码:<input type="password" name="pwd" id="">
                    </label>
                </div>
                <div class="loginBtn"><input type="submit" value="登录会员"></div>
            </form>
        </div>
        <div class="circle">关闭</div>
    </div>
    <div class="mask"></div>

    <script>
        // ① 点击弹出层, 模态框和遮挡层就会显示出来 display:block;
        // ② 点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;
        // ③ 在页面中拖拽的原理: 鼠标按下并且移动, 之后松开鼠标
        // ④ 触发事件是鼠标按下 mousedown, 鼠标移动mousemove 鼠标松开 mouseup
        // ⑤ 拖拽过程: 鼠标移动过程中,获得最新的值赋值给模态框的left和top值, 这样模态框可以跟着鼠标走了
        // ⑥ 鼠标按下触发的事件源是 最上面一行,就是 id 为 title 
        // ⑦ 鼠标的坐标 减去 鼠标在盒子内的坐标, 才是模态框真正的位置。
        // ⑧ 鼠标按下,我们要得到鼠标在盒子的坐标。
        // ⑨ 鼠标移动,就让模态框的坐标 设置为 : 鼠标坐标 减去盒子坐标即可,注意移动事件写到按下事件里面。
        // ⑩ 鼠标松开,就停止拖拽,就是可以让鼠标移动事件解除

        //获取元素
        var link = document.querySelector('.link');
        var login = document.querySelector('.login');
        var mask = document.querySelector('.mask');
        var circle = document.querySelector('.circle');
        var login_title = document.querySelector('.login-title');
        //点击弹出层, 模态框和遮挡层就会显示出来 display:block;
        link.addEventListener('click', function () {
            login.style.display = 'block';
            mask.style.display = 'block';
        });
        //点击关闭按钮,模态框和遮挡层就会隐藏起来 display:none;
        circle.addEventListener('click', function () {
            login.style.display = 'none';
            mask.style.display = 'none';
        });
        // 触发事件是鼠标按下 mousedown
        login_title.addEventListener('mousedown', fn);
        function fn(e) {
            //首先计算鼠标在盒子内的坐标
            var x = e.pageX - login.offsetLeft;
            var y = e.pageY - login.offsetTop;
            //鼠标移动时,模态框也会移动鼠标移动mousemove
            document.addEventListener('mousemove', fn);
            function fn(e) {
                //鼠标移动,就让模态框的坐标 设置为 : 鼠标坐标 减去盒子坐标即可,然后赋值即可
                login.style.left = e.pageX - x + 'px';
                login.style.top = e.pageY - y + 'px';
            };
            //鼠标松开,就停止拖拽,就是可以让鼠标移动事件解除鼠标松开 mouseup
            document.addEventListener('mouseup', function () {
                document.removeEventListener('mousemove', fn);
            });
        };
    </script>

演示结果:

1.5案例:仿京东放大镜

代码演示:
<style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .box1 {
            position: relative;
            margin-top: 100px;
            margin-left: 100px;
            width: 300px;
            height: 300px;
            border: 1px solid #000;
        }

        .box1 img {
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 200px;
        }

        .box2 {
            display: none;
            position: absolute;
            left: 0;
            top: 0;
            width: 200px;
            height: 200px;
            background-color: yellow;
            opacity: .3;
            cursor: move;
        }

        .box3 {
            display: none;
            position: absolute;
            right: -750px;
            width: 600px;
            height: 600px;
        }

        .box3 img {
            position: absolute;
            width: 500px;
            transform: translate(0, 0);
        }
    </style>
</head>

<body>
    <div class="box1">
        <img src="./imgs/s3.png" alt="">
        <div class="box2"></div>
        <div class="box3">
            <img src="./imgs/big.jpg" alt="">
        </div>
    </div>

    <script>
        // ① 整个案例可以分为三个功能模块
        // ② 鼠标经过小图片盒子, 黄色的遮挡层 和 大图片盒子显示,离开隐藏2个盒子功能
        // ③ 黄色的遮挡层跟随鼠标功能。
        // ④ 移动黄色遮挡层,大图片跟随移动功能。
        //获取元素
        var box1 = document.querySelector('.box1');
        var box2 = document.querySelector('.box2');
        var box3 = document.querySelector('.box3');

        //鼠标经过小图片盒子, 黄色的遮挡层 和 大图片盒子显示
        box1.addEventListener('mouseover', function () {
            box2.style.display = 'block';
            box3.style.display = 'block';
        });
        //离开隐藏2个盒子
        box1.addEventListener('mouseout', function () {
            box2.style.display = 'none';
            box3.style.display = 'none';
        });
        //给大盒子添加鼠标移动事件
        box1.addEventListener('mousemove', fn);
        function fn(e) {
            //获取鼠标在盒子的坐标
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            //给box2添加left、top的值
            //加上判断条件,当盒子box2左边距离 0 < left < box1.offsetWidth - box2.offsetWidth
            //当盒子box2top值:0 < top < box1.offsetTop - box2.offsetTop
            box2.style.left = x - box2.offsetWidth / 2 + 'px';
            box2.style.top = y - box2.offsetHeight / 2 + 'px';
            //判断left
            if (box2.offsetLeft < 0) {
                box2.style.left = 0;
            } else if (box2.offsetLeft > box1.offsetWidth - box2.offsetWidth) {
                box2.style.left = box1.offsetWidth - box2.offsetWidth + 'px';
            }
            //判断top
            if (box2.offsetTop < 0) {
                box2.style.top = 0;
            } else if (box2.offsetTop > box1.offsetHeight - box2.offsetHeight) {
                box2.style.top = box1.offsetHeight - box2.offsetHeight + 'px';
            }

            //右边盒子里图片的移动
            //遮挡层移动距离/遮挡层最大移动距离=大图片移动距离/大图片最大移动距离
            //大图片移动距离
            var bigX = (box2.offsetLeft / (box1.offsetWidth - box2.offsetWidth)) * (box3.offsetWidth - box3.children[0].offsetWidth);
            var bigY = (box2.offsetTop / (box1.offsetHeight - box2.offsetHeight)) * (box3.offsetHeight - box3.children[0].offsetHeight);
            // console.log(bigY);
            box3.children[0].style.left = -bigX + 'px';
            box3.children[0].style.top = -bigY + 'px';
        }
    </script>
</body>

演示结果:

2. 元素可视区 client 系列

client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过
client 系列 的相关属性可以动态的得到该元素的边框大小、元素大小等。
案例: 淘宝 flexible.js 源码分析
1.立即执行函数
立即执行函数 (function() {})() 或者 (function(){}())
<body>
    <script>
        // 1.立即执行函数: 不需要调用,立马能够自己执行的函数
        function fn() {
            console.log(1);

        }
        fn();
        // 2. 写法 也可以传递参数进来
        // 1.(function() {})()    或者  2. (function(){}());
        (function(a, b) {
            console.log(a + b);
            var num = 10;
        })(1, 2); // 第二个小括号可以看做是调用函数
        (function sum(a, b) {
            console.log(a + b);
            var num = 10; // 局部变量
        }(2, 3));
        // 3. 立即执行函数最大的作用就是 独立创建了一个作用域, 里面所有的变量都是局部变量 不会有命名冲突的情况
    </script>
</body>
下面三种情况都会刷新页面都会触发 load 事件。
1. a标签的超链接
2. F5或者刷新按钮(强制刷新)
3. 前进后退按钮
但是 火狐中,有个特点,有个 “往返缓存” 这个缓存中不仅保存着页面数据,还保存了DOM和
JavaScript的 状态;实际上是将整个页面都保存在了内存里。
所以此时后退按钮不能刷新页面。
此时可以使用 pageshow事件来触发。 ,这个事件在页面显示时触发,无论页面是否来自缓存。在
重新加载页 面中,pageshow会在load事件触发后触发;根据事件对象中的persisted来判断是否是
缓存中的页面触发的 pageshow事件,注意这个事件给window添加。
<script>
        // console.log(window.devicePixelRatio);
        window.addEventListener('pageshow', function() {
            alert(11);
        })
    </script>

3. 元素滚动 scroll 系列

3.1 元素 scroll 系列属性

scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动
距离等。

代码演示:

<style>
        div {
            width:250px;
            height: 200px;
            background-color: pink;
            border: 10px solid red;
            padding: 10px;
            overflow: auto;
        }
    </style>
</head>

<body>
    <div>
        我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
        我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
    </div>
    <script>
        // scroll 系列
        var div = document.querySelector('div');
        console.log(div.scrollHeight);
        console.log(div.scrollWidth);
        console.log(div.clientHeight);
        console.log(div.clientWidth);
        // scroll滚动事件当我们滚动条发生变化会触发的事件
        div.addEventListener('scroll', function () {
            console.log(div.scrollTop);
        })
    </script>
</body>

3.2 页面被卷去的头部

如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页
面上面被隐藏 掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。
页面被卷去的头部:可以通过window.pageYOffset 获得 如果是被卷去的左侧 window.pageXOffset
元素被卷去的头部是 element.scrollTop , 如果是页面被卷去的头部 则window.pageYOffset
案例:仿淘宝固定右侧侧边栏
代码演示:
<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>
        // 1.原先侧边栏是绝对定位
        // 2. 当页面滚动到一定位置,侧边栏改为固定定位
        // 3. 页面继续滚动,会让 返回顶部显示出来
        // ① 需要用到页面滚动事件 scroll 因为是页面滚动,所以事件源是 document
        // ② 滚动到某个位置,就是判断页面被卷去的上部值。
        // ③ 页面被卷去的头部:可以通过window.pageYOffset 获得 如果是被卷去的左侧 window.pageXOffset
        // ④ 注意,元素被卷去的头部是 element.scrollTop , 如果是页面被卷去的头部 则是 window.pageYOffset
        // ⑤ 其实这个值 可以通过盒子的 offsetTop 可以得到,如果大于等于这个值,就可以让盒子固定定位了
        //获取元素
        var sliderbar = document.querySelector('.slider-bar');
        var banner = document.querySelector('.banner');
        var main = document.querySelector('.main');
        //banner距离页面的高度
        var bannerTop = banner.offsetTop;
        // console.log(bannerTop);
        //main距离页面的高度
        var mainTop = main.offsetTop;
        //得到最开始侧边栏距离banner的高度
        var sliderbarTop = sliderbar.offsetTop - banner.offsetTop;
        //注册滚动事件
        document.addEventListener('scroll', fn);
        function fn() {
            //到banner区域,把侧边栏改成固定定位
            if (window.pageYOffset > bannerTop) {
                sliderbar.style.position = 'fixed';
                sliderbar.style.top = sliderbarTop + 'px';
            } else {
                sliderbar.style.position = 'absolute';
                sliderbar.style.top = 300 + 'px';
            }
            //到main区域,让侧边栏中的内容显示出来
            if (window.pageYOffset > mainTop) {
                sliderbar.children[0].style.display = 'block';
            } else {
                sliderbar.children[0].style.display = 'none';
            }
        };

    </script>

4、总结

4.1三大系列总结

他们主要用法:
1. offset系列 经常用于获得元素位置 offsetLeft offsetTop
2. client 经常用于获取元素大小 clientWidth clientHeight
3. scroll 经常用于获取滚动距离 scrollTop scrollLeft
4. 注意页面滚动的距离通过 window.pageXOffset 获得

4.2mouseenter 和mouseover的区别

mouseenter 鼠标事件
1. 当鼠标移动到元素上时就会触发 mouseenter 事件
2. 类似 mouseover,它们两者之间的差别是
3. mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。 mouseenter 只会经过自身盒子触
4. 之所以这样,就是因为mouseenter不会冒泡
5. 跟mouseenter搭配 鼠标离开 mouseleave 同样不会冒泡

5. 动画函数封装

5.1 动画实现原理

核心原理 通过定时器 setInterval() 不断移动盒子位置。
实现步骤:
1. 获得盒子当前位置
2. 让盒子在当前位置加上1个移动距离
3. 利用定时器不断重复这个操作
4. 加一个结束定时器的条件
5. 注意此元素需要添加定位,才能使用 element.style.left

5.2 动画函数简单封装

注意函数需要传递 2个参数,动画对象和移动到的距离。
代码演示:
    <style>
        .box {
            position: absolute;
            left: 0;
            top: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <script>
        // 简单动画函数封装obj目标对象 target 目标位置
        function animate(obj, target) {
            var timer = setInterval(function () {
                if (obj.offsetLeft >= target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(timer);
                }
                obj.style.left = obj.offsetLeft + 1 + 'px';

            }, 30);
        };
        var box = document.querySelector('.box');
        animate(box,300);
    </script>
</body>

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

如果多个元素都使用这个动画函数,每次都要 var 声明定时器。我们可以给不同的元素使用不同的
定时器(自 己专门用自己的定时器)。
核心原理:利用 JS 是一门动态语言,可以很方便的给当前对象添加属性。
代码演示:
   <script>
        // 简单动画函数封装obj目标对象 target 目标位置
        function animate(obj, target) {
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                if (obj.offsetLeft >= target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + 1 + 'px';

            }, 30);
        };
        var box = document.querySelector('.box');
        animate(box,300);
    </script>

5.4 缓动效果原理

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:
1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
2. 核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长
3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
4. 注意步长值需要取整
代码演示:
<script>
        // 思路:
        // 1. 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
        // 2. 核心算法: (目标值 - 现在的位置) / 10 做为每次移动的距离 步长
        // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
        // 4. 注意步长值需要取整
        function animate(obj, target) {
            obj.timer = setInterval(function () {
                if (obj.offsetLeft >= target) {
                    clearInterval(obj.timer);
                }
                obj.style.left = obj.offsetLeft + Math.ceil((target - obj.offsetLeft) / 10) + 'px';
            }, 50);
        };
        var box = document.querySelector('.box');
        animate(box, 800);

5.5 动画函数多个目标值之间移动(回调函数)

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

5.6动画函数封装到单独JS文件里面

1. 单独新建一个 JS 文件。
2. HTML 文件引入 JS 文件。
垂直位移动画封装:
function animateY(obj, target, callback) {
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
        var step = (target - obj.offsetTop) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetTop == target) {
            clearInterval(obj.timer);
            if (callback) {
                callback();
            }
        }
        obj.style.top = obj.offsetTop + step + 'px';
    }, 15);
};

案例:网页轮播图、

代码演示:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./动画封装.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        li {
            list-style: none;
        }

        a {
            text-decoration: none;
        }

        .box {
            position: relative;
            margin: 100px auto;
            width: 400px;
            height: 400px;
            background-color: pink;
            overflow: hidden;
        }

        .move {
            position: absolute;
            left: 0;
            top: 0;
            width: 3000px;
            height: 400px;
        }

        .box li {
            float: left;
        }

        .box li:nth-child(1) {
            background-color: aqua;
        }

        .box li:nth-child(2) {
            background-color: pink;
        }

        .box li:nth-child(3) {
            background-color: bisque;
        }

        .box li:nth-child(4) {
            background-color: skyblue;
        }

        .box li:nth-child(5) {
            background-color: aqua;
        }

        .box li a {
            display: block;
            width: 400px;
            height: 400px;
        }

        .circle {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translate(-50%);
        }

        .circle span {
            float: left;
            margin: 0 3px;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            border: 1px solid #ccc;
        }

        .current {
            background-color: #fff;
        }

        .left_arrow,
        .right_arrow {
            position: absolute;
            width: 30px;
            height: 40px;
            background-color: #000;
            opacity: .3;
            transform: translateY(-50%);
            color: #fff;
            line-height: 40px;
            text-align: center;
            font-size: 18px;
            cursor: default;
        }

        .left_arrow {
            top: 50%;
            left: 20px;
        }

        .right_arrow {
            top: 50%;
            right: 20px;
        }
    </style>
</head>

<body>
    <div class="box">
        <ul class="move">
            <li><a href="#"></a></li>
            <li><a href="#"></a></li>
            <li><a href="#"></a></li>
            <li><a href="#"></a></li>
        </ul>
        <div class="circle"></div>
        <div class="left_arrow">
            < </div>
                <div class="right_arrow"> > </div>
        </div>

        <script>
            window.addEventListener('load', function () {
                var move = document.querySelector('.move');
                //自动轮播图
                var liwidth = move.children[0].offsetWidth;
                //获取张li对象
                var lis = move.children;
                //克隆第一张图片
                var lifirst = lis[0].cloneNode(true);
                move.appendChild(lifirst);
                var flag = 0;
                setInterval(fn, 4000);
                //执行定时器的函数
                function fn() {
                    flag++;
                    //判断ul走了多少
                    if (flag === lis.length) {
                        move.style.left = 0;
                        flag = 1;
                    }
                    // animate(obj, target, callback)
                    //调用动画
                    animate(move, -flag * liwidth);
                    //干掉其它圆点
                    for (var i = 0; i < lis.length - 1; i++) {
                        circle.children[i].className = '';
                    }
                    // 保留我自己
                    if (flag === lis.length - 1) {
                        circle.children[0].className = 'current';
                    } else if (flag < lis.length - 1) {
                        circle.children[flag].className = 'current';
                    }
                    //给每个小圆圈注册点击事件
                    for (var i = 0; i < lis.length - 1; i++) {
                        circle.children[i].setAttribute('data-index', i);
                        circle.children[i].addEventListener('click', function () {
                            //把当前图片的自定义属性值给flag
                            flag = this.getAttribute('data-index');
                            animate(move, -flag * liwidth);
                            for (var i = 0; i < lis.length - 1; i++) {
                                circle.children[i].className = '';
                            }
                            circle.children[flag].className = 'current';
                        });
                    }
                };
                //添加小圆圈
                //根据图片的多少,创建多少个小圆圈
                var circle = document.querySelector('.circle');
                for (var i = 0; i < lis.length - 1; i++) {
                    var span = document.createElement('span');
                    circle.appendChild(span);
                }
                circle.children[flag].className = 'current';
                //获取左右箭头元素  
                var leftarrow = document.querySelector('.left_arrow');
                var rightarrow = document.querySelector('.right_arrow');
                //节流阀
                var flag1 = true;
                //给箭头注册点击事件
                leftarrow.addEventListener('click', function () {
                    if (flag1 == true) {
                        flag1 = false;
                        flag--;
                        if (flag == -1) {
                            move.style.left = -(lis.length - 2) * liwidth + 'px';
                            flag = lis.length - 2;
                        } else if (flag == lis.length - 2) {
                            move.style.left = -(lis.length - 2) * liwidth + 'px';
                            flag = lis.length - 2;
                        }
                        //给小圆圈添加对应的样式
                        for (var i = 0; i < lis.length - 1; i++) {
                            circle.children[i].className = '';
                        }
                        circle.children[flag].className = 'current';
                    }
                    animate(move, -flag * liwidth, function () {
                        flag1 = true;
                    });
                });
                rightarrow.addEventListener('click', function () {
                    if (flag1 == true) {
                        flag1 = false;
                        flag++;
                        if (flag == lis.length - 1) {
                            move.style.left = 0;
                            flag = 0;
                        }
                        if (flag == lis.length) {
                            move.style.left = 0;
                            flag = 1;
                        }
                        //给小圆圈添加对应的样式
                        for (var i = 0; i < lis.length - 1; i++) {
                            circle.children[i].className = '';
                        }
                        circle.children[flag].className = 'current';
                    }
                    animate(move, -flag * liwidth, function () {
                        flag1 = true;
                    });
                });
            });

        </script>
</body>

</html>
案例:筋头云案例
代码演示;
 <style>
        * {
            margin: 0;
            padding: 0;
        }

        .tab {
            position: relative;
            margin: 100px auto;
            width: 500px;
            height: 40px;
        }

        .tab li {
            list-style: none;
            float: left;
            padding: 0 10px;
            line-height: 40px;
            cursor: pointer;
        }

        .cloud {
            position: absolute;
            left: 0;
            top: 0;
            height: 40px;
            width: 84px;
            background-image: url(./imgs/cloud.gif);
            background-size: contain;
            background-repeat: no-repeat;
            z-index: -999;
        }

        .current {
            color: blue;
        }
    </style>
</head>

<body>
    <div class="tab">
        <div class="cloud"></div>
        <ul>
            <li class="current">天下足球</li>
            <li>天下足球</li>
            <li>天下足球</li>
            <li>天下足球</li>
            <li>天下足球</li>
        </ul>
    </div>

    <script>
        var cloud = document.querySelector('.cloud');
        var lis = document.querySelectorAll('li');
        var flag = 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, flag);
            })
            //添加鼠标点击事件
            lis[i].addEventListener('click', function () {
                flag = this.offsetLeft;
                for (var i = 0; i < lis.length; i++) {
                    lis[i].className = '';
                }
                this.className = 'current';
            })
        }
    </script>
</body>

演示结果:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值