前端-js网页特效(终章)超详细的轮播图效果及原理 一篇彻底吃透!

目录

前言

 一、结构搭建

细节部分:

代码实现:

效果图:

二、功能模块分析

1、盒子模块

原理:

代码实现:

效果:

2、焦点模块(重点)

原理:

细节部分:

代码实现:

效果:

3、右侧按钮模块(重点)

原理:

细节部分:

代码实现:

 效果:

4、左侧按钮

原理:

细节部分:

代码实现:

效果:

5、自动播放模块

原理:

代码实现:

效果:

6、节流阀模块

原理:

细节部分:

代码实现:

 7、一些会碰到的疑问

1、为什么焦点数小于实际的图片数?

2、克隆不成功

3、图片不移动

三、完整代码

 效果图:

四、结束语


前言


       在此之前,小糖其实尝试了很多讲解方式,但还是不满意推翻重写(小糖写文章的风格初衷就是尽量简短精细易懂)琢磨了两天,甚至于在CSDN观摩其他人的轮播图讲解文章,还是感觉讲的太晦涩,最后决定用模块化的讲解方式,(也算另一种简短了吧?)
这样大家好接受一些,不会眼花缭乱。制作不易,这篇文章足够大家放收藏夹吃灰了吧哈哈哈哈哈哈......

 一、结构搭建

细节部分

1、要注意焦点数是与(展示的)图片数量同步的。
如下:原生HTML焦点列表中是没写焦点的    

<!--焦点模块-->
<ol class="circle"  ></ol>

 2、图片要用列表包裹,且一行显示(用浮动)时,会发现其他图片消失了
    (原因:只是让li左浮动,但是浮动的元素无法撑开ul,所以让ul变宽即可,如下)
 

ul {
            position: absolute;
            width: 800%;
            height: 100%;
        }


 3、注意按钮层级!不然会被图片覆盖啦!要用按钮的css中的z-index!

.arrow-l, .arrow-r {
            z-index: 999;
}

代码实现:


     

  * {
            padding: 0;margin: 0;
        }
        .focus {
            overflow: hidden;
            position: relative;
            margin: 100px auto;
            width: 520px;
            height: 280px;
            background-color: pink;
            border-radius: 10px;
        }
        ul {
            position: absolute;
            width: 800%;
            height: 100%;
        }
        ul li {
            list-style: none;
            float: left;
            
        }
        .arrow-l, .arrow-r {
            display: none;
            text-decoration: none;
            z-index: 999;
            position: absolute;
            top:50%;
            margin-top: -20px;
            width: 24px;
            height: 40px;
            color:#fff;
            line-height: 40px;
            font-size: 18px;
            background: rgba(121, 120, 120, 0.5);
            text-align: center;
            border-radius: 0 9px 9px 0;
        }
        .arrow-l:hover, .arrow-r:hover {
            color:orange;
            font-weight: bolder;
        }
        .arrow-r {
            right: 0;
            border-radius: 9px 0 0 9px;
        }
        ol {
            position: absolute;
            bottom: 10px;
            left: 10px;
            display: flex;
            justify-content: space-evenly;

        }
        ol li {
            list-style: none;
            margin-right: 2px;
            width: 10px;
            height: 10px;
            background-color: rgb(255, 255, 255);
            border-radius: 50%;
            cursor: pointer;
            border: 1.5px solid white;
        }
        .carrent {
            background-color: orange;
        }
 <div class="focus">
        <!--按钮模块-->
        <a href="javacript:;" class="arrow-l">&lt</a>
        <a href="javacript:;" class="arrow-r">></a>
        <!--轮播图模块-->
        <ul>
            <li>
                <a href="javacript:;"><img src="./img/O1CN01m6rRlH1rFJ4fFW57D_!!6000000005601-0-octopus.jpg" alt=""></a>
            </li>
            <li>
                <a href="javacript:;"><img src="./img/TB10vPXKpXXXXacXXXXvKyzTVXX-520-280.jpg" alt=""></a>
            </li>
            <li>
                <a href="javacript:;"><img src="./img/TB1gXd1JXXXXXapXpXXvKyzTVXX-520-280.jpg" alt=""></a>
            </li>
            <li>
                <a href="javacript:;"><img src="./img/TB10vPXKpXXXXacXXXXvKyzTVXX-520-280.jpg" alt=""></a>
            </li>
            
        </ul>
        <!--焦点模块-->
        <ol class="circle"  ></ol>

    </div>

效果图:

二、功能模块分析

1、盒子模块


原理:

                   当鼠标进入盒子时显示按钮,离开时隐藏按钮
                 (小糖觉得也可以用css平替,不过后期应该不行叭~)

代码实现:

var focus1 = document.querySelector('.focus');
        var arrowl = document.querySelector('.arrow-l');
        var arrowr = document.querySelector('.arrow-r');
        focus1.addEventListener('mouseenter',function(){
            arrowl.style.display = 'inline-block';
            arrowr.style.display = 'inline-block';
        });
        focus1.addEventListener('mouseleave',function(){
            arrowl.style.display = 'none';
            arrowr.style.display = 'none';
        });


效果:

2、焦点模块(重点)

原理:

                   利用js-DOM 根据(展示的)图片数量创建焦点,且当焦点被点击时变色图片切换

细节部分:

             1、利用之前我们书写缓动效果时的函数,把它封装起来,现在可以用来修改啦
             2、在创建焦点时要记录它的索引号,后面可以根据索引号找图片
                   记录后也要声明再使用哦!!
             3、盒子宽度要声明为全局变量(focus1width)
             4、图片移动的距离就是:- 索引号 * 盒子宽度(focus1width) 

代码实现:

 var ul = focus1.querySelector('ul');
        var ol = focus1.querySelector('.circle');
        for(var i = 0;i < ul.children.length;i++){
            //创建新元素
            var li = document.createElement('li');
            //记录当前小圆圈的索引号 用自定义属性来做
            li.setAttribute('index',i);
            //将元素插入ol里面
            ol.appendChild(li);

        li.addEventListener('click',function(){   //排他思想一定写在循环里面 不然只能执行一次
            for(var i = 0;i < ol.children.length;i++){
                //排除所有
                ol.children[i].className = '';
            }
            //留下自己
            this.className = 'carrent';
            //ul移动的距离 小圆圈的索引号 乘以 图片的宽度 
            //当我们点击某个li 就拿到当前li的索引号 
            var index = this.getAttribute('index');
            //var focus1width = focus1.offsetWidth;   要改为全局变量
            animate(ul,-index * focus1width);
        });
        };

效果:
 

3、右侧按钮模块(重点)


原理:

                   点击按钮实现图片切换,用一个num变量控制图片切换;实现无缝滚动效果

细节部分:

             1、无缝滚动:将ul中的第一个li复制一份放到ul最后面(即用深克隆
                   当图片滚动到最后一张时,让ul快速跳到最左侧, left:0; 同时赋值num为0。
             2、还要在声明一个circle变量控制焦点播放
             3、可能出现circle与num不一致造成bug,解决办法:在焦点的事件侦听器中令两者与索引号一致。
             4、知道无缝滚动时,num是如何变化的(细看代码)

代码实现:

var num = 0;    //控制图片切换           
        var circle = 0;    //控制焦点播放     
        arrowr.addEventListener('click',function(){
                if(num == ul.children.length - 1) {
                ul.style.left = 0 + 'px';
                num = 0;
            }
            num++;     
            animate(ul,-num*focus1width);
            circle++;
            //但是图片有五张 源泉只有四个,所以要设置
            if(circle == ol.children.length) {
                circle = 0;
            };               //要放在排他思想之前 因为if是执行的前提
            
            //排他思想
            //先清除其余小圆圈的current类名
            for (var i = 0;i < ol.children.length;i++){
                ol.children[i].className = '';
            }
            //留下当前小圆圈的类名
            ol.children[circle].className = 'carrent';
        }
        });

 效果:

 

4、左侧按钮


原理:

                   同上

细节部分:

             注意修改无缝滚动的条件以及焦点播放的条件

代码实现:

arrowl.addEventListener('click',function(){
                if(num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -(num*focus1width) + 'px';
            }
            num--;     
            animate(ul,-num*focus1width);

            //点击左侧按钮 小圆圈跟着变化 可以再声明一个变量控制小圆圈的播放
            circle--;

            //但是图片有五张 圆圈只有四个,所以要设置
            if(circle < 0) {
                circle = ol.children.length - 1;
            }; //要放在排他思想之前 因为if是执行的前提

            //排他思想
            //先清除其余小圆圈的current类名
            for (var i = 0 ; i < ol.children.length ; i++){
                ol.children[i].className = '';
            }
            //留下当前小圆圈的类名
            ol.children[circle].className = 'carrent';
            }
            
        });


效果:
 

5、自动播放模块

原理:

                  利用定时器实现图片切换,可利用右侧按钮的”手动调用事件“

代码实现:

 //自动播放 
        var timer = setInterval(function(){
            arrowr.click();   //手动调用事件
        },2000);

效果:
 

6、节流阀模块

原理:

                  相当于给每次图片切换加一个”开关“,当切换完成才可以打开,

                  而判断是否完成切换的重要侦听器就是利用回调函数callback。

细节部分:

                  callback是加在每个按钮侦听器里的,要声明一个布尔类型的变量充当开关

代码实现:
 

 (左右侧按钮同样道理,此处只展示右侧)

 7、一些会碰到的疑问

1、为什么焦点数小于实际的图片数?

      答:因为我们是优先获取焦点,再额外克隆第一张图片,按照事件流执行顺序,焦点数已是完成获取的了。

2、克隆不成功

      答:克隆要使用深克隆,值为true

3、图片不移动

      答:移动的是整个ul而不是单个li

三、完整代码

最后给盒子添加溢出隐藏就好啦~
完整js代码自取!

 //1.获取按钮
        var focus1 = document.querySelector('.focus');
        var arrowl = document.querySelector('.arrow-l');
        var arrowr = document.querySelector('.arrow-r');
        var focus1width = focus1.offsetWidth;      //要改成全局变量
        var flag = true;  //节流阀
        focus1.addEventListener('mouseenter',function(){
            arrowl.style.display = 'inline-block';
            arrowr.style.display = 'inline-block';
            clearInterval(timer) ;  //当鼠标进入,停止自动播放
            timer = null;
        });
        focus1.addEventListener('mouseleave',function(){
            arrowl.style.display = 'none';
            arrowr.style.display = 'none';
            timer = setInterval(function(){
            arrowr.click();   //手动调用事件
        },2000);
        });
        //3.动态生成小圆圈 几个图片 几个小圆圈
        var ul = focus1.querySelector('ul');
        var ol = focus1.querySelector('.circle');
        for(var i = 0;i < ul.children.length;i++){
            //创建新元素
            var li = document.createElement('li');
            //记录当前小圆圈的索引号 用自定义属性来做
            li.setAttribute('index',i);
            //将元素插入ol里面
            ol.appendChild(li);
            li.addEventListener('click',function(){   //排他思想一定写在循环里面 不然只能执行一次
            for(var i = 0;i < ol.children.length;i++){
                //排除所有
                ol.children[i].className = '';
            }
            //留下自己
            this.className = 'carrent';
            //5.点击小圆圈 ul移动
            //ul移动的距离 小圆圈的索引号 乘以 图片的宽度 
            //当我们点击某个li 就拿到当前li的索引号 
            var index = this.getAttribute('index');
            num = circle = index;      //num 和 circle 和索引号统一 才不会出现bug

            //var focus1width = focus1.offsetWidth;   要改为全局变量
            animate(ul,-index * focus1width);
        });
        };

        //6.克隆第一张图片
        var first = ul.children[0].cloneNode(true);
        ul.appendChild(first);


        //右侧按钮    无缝滚动原理:将ul中的第一个li复制一份放到ul最后面
        //            当图片滚动到最后一张时,让ul快速跳到最左侧 即 left:0; 同时赋值num为0
        var num = 0;    //控制图片切换           
        var circle = 0;    //控制焦点播放     
        arrowr.addEventListener('click',function(){
            if(flag) {
                flag = false;
                if(num == ul.children.length - 1) {
                ul.style.left = 0 + 'px';
                num = 0;
            }
            num++;     
            animate(ul,-num*focus1width,function(){
                flag = true;
            });

            //点击右侧按钮 小圆圈跟着变化 可以再声明一个变量控制小圆圈的播放
            circle++;

            //但是图片有五张 源泉只有四个,所以要设置
            if(circle == ol.children.length) {
                circle = 0;
            };               //要放在排他思想之前 因为if是执行的前提
            

            //排他思想
            //先清除其余小圆圈的current类名
            for (var i = 0;i < ol.children.length;i++){
                ol.children[i].className = '';
            }
            //留下当前小圆圈的类名
            ol.children[circle].className = 'carrent';
        }
        });
        //9.左侧按钮
        arrowl.addEventListener('click',function(){
            if(flag) {
                flag = false;
                if(num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -(num*focus1width) + 'px';
            }
            num--;     
            animate(ul,-num*focus1width,function(){
                flag = true;
            });

            //10.点击左侧按钮 小圆圈跟着变化 可以再声明一个变量控制小圆圈的播放
            circle--;

            //但是图片有五张 圆圈只有四个,所以要设置
            if(circle < 0) {
                circle = ol.children.length - 1;
            }; //要放在排他思想之前 因为if是执行的前提

            //排他思想
            //先清除其余小圆圈的current类名
            for (var i = 0 ; i < ol.children.length ; i++){
                ol.children[i].className = '';
            }
            //留下当前小圆圈的类名
            ol.children[circle].className = 'carrent';
            }
            
        });
        //11.自动播放 
        var timer = setInterval(function(){
            arrowr.click();   //手动调用事件
        },4000);

        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);   
            //解决在前进与后退两种情况下 step 应该  “向上取整”  还是  “向下取整”!!!!!!!
    
    
             //当不断点击按钮时,这个元素就会越来越快,因为启动了太多计时器
             //解决办法:在启动定时器时之前保证只有一个计时器 即先清除所有计时器
        if( obj.offsetLeft == target){  //用  “==”   取代  '>='  可以解决盒子返回时无法执行的问题
            clearInterval(obj.timer);
            if(callback) {
                callback();
            }
        }
        obj.style.left = obj.offsetLeft + step +'px';
    },20);
    };

 效果图:

四、结束语

希望本篇文章可以帮到求知若渴的众多同学吖~
若能帮到 也欢迎点赞、收藏、关注我,后续也会持续发布新文章,祝大家学有所成!
欢迎各位前端大佬留言讨论指教!
 小糖谢谢各位啦~❤  ❤  ❤  ❤

  • 13
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
要快速理解并掌握PFC(Power Factor Correction,功率因数校正)电源原理分析的技巧,可以按照以下4个步骤进行: 第一步是了解基本概念。PFC电源的目标是改善电源系统的功率因数,减小谐波失真,提高能源利用率。了解基本的PFC电源概念,如谐波、功率因数、能源利用等,是理解其原理分析的基础。 第二步是学习PFC电源的工作原理。PFC电源的核心组成是PFC控制器和PFC电路。通过学习PFC电源的工作原理,了解其如何校正和改善功率因数,以及各个元件和电路的作用和相互关系。 第三步是深入研究PFC电源的拓扑结构和控制方式。了解不同的PFC电路拓扑结构(如Boost型PFC、Bridgeless PFC等)和控制方式,对于理解PFC电源原理分析非常重要。研究拓扑结构和控制方式的优劣势、特点和适用范围,能够帮助快速抓住重点和关键问题。 最后一步是实践和案例分析。通过实际的项目实践和相关案例分析,深入理解PFC电源的原理和实际应用。可以通过仿真软件进行PFC电源的设计和验证,或者参考相关的研究论文和技术报告,从实践中获取经验和知识。 通过以上4个步骤,可以快速吃透PFC电源原理分析的技巧。但需要注意,PFC电源的原理和分析涉及一定的专业知识和技巧,需要较强的电力电子背景和电路分析能力。建议在了解基础知识后,多与领域专家和同行交流,不断学习和实践,进一步提升自己的能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值