0

0

如何使用原生JavaScript实现轮播图?代码详解

php是最好的语言

php是最好的语言

发布时间:2018-08-07 10:58:27

|

3245人浏览过

|

来源于php中文网

原创

实现原理

1.png

通过自定义的animate函数来改变元素的left值让图片呈现左右滚动的效果

HTML:




    
    
    


    

  • 如何使用原生JavaScript实现轮播图?代码详解
  • 如何使用原生JavaScript实现轮播图?代码详解
  • 如何使用原生JavaScript实现轮播图?代码详解
  • 如何使用原生JavaScript实现轮播图?代码详解
  • 如何使用原生JavaScript实现轮播图?代码详解

    CSS:

    body, p, p,
    h1, h2, h3, h4, h5, h6,
    dl, dt, dd, ul, ol, li,
    table, caption, th, td,
    form, fieldset, input, textarea, select,
    pre, address, blockquote,
    embed, object {
        margin: 0px;
        padding: 0px;
    }
    
    ul, ol {
        list-style:none;
    }
    
    img {
        vertical-align: top;
    }
    
    .scroll {
        width: 950px;
        height: 438px;
        margin: auto;
        overflow: hidden;
        position: relative;
    }
    
    .box {
        width: 950px;
        height: 438px;
        overflow: hidden;
        position: relative;
    }
    
    .box ul{
        width: 700%;
        position: absolute;
        left: 0;
        top: 0;
        padding:0px;
        margin:0px;
    }
    
    .box ul li{
        float: left;
    }
    
    .scroll ol {
        position: absolute;
        right: 365px;
        bottom: 5px;
    }
    
    .scroll ol li {
        float: left;
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background: #000;
        margin-left: 10px;
        cursor: pointer;
        opacity: 0.5;
    }
    
    .scroll ol li.current {
        background-color: #000099;
        opacity: 0.8;
    }
    
    #last {
        position: absolute;
        bottom: 179px;
        width: 80px;
        height: 80px;
        cursor: pointer;
    }
    
    #next {
        position: absolute;
        bottom: 179px;
        right: 0px;
        width: 80px;
        height: 80px;
        cursor: pointer;
    }

    1.png

    展示效果如上图 

    立即学习Java免费学习笔记(深入)”;

    接下来讲解js代码 ,先获取html中的元素

    var scroll = document.getElementById("scroll");
    var ul = document.getElementById("ul");
    var ulLis = ul.children;
    var liWidth = ul.children[0].offsetWidth;


    再此之前,我们要明白,小圆点并不是写死的,它是根据ul li中的图片张数来决定的 。

    var ol = document.getElementById("olnavi");
    for (var i = 0; i < ulLis.length - 2; i++) {
        var li = document.createElement("li");
        li.id = (i + 1);  //id用于后面为li添加事件
        ol.appendChild(li);
        
    }
    ol.children[0].className = "current" //将第一个小圆点设置为触发状态

    要实现无缝滚动 就需要多两张图片才行 ,即克隆第一张图片,放到最后一张的后面,克隆最后一张,放到第一张的前面。

    var num = ulLis.length - 1;
    ul.appendChild(ul.children[0].cloneNode(true));
    ul.insertBefore(ul.children[num].cloneNode(true), ul.firstChild);

    接下来为左右箭头添加事件,鼠标放到箭头上会变色

    var last = document.getElementById("last");
    last.style.background = "url(images/last-control.png)";
    
    last.addEventListener("mouseenter", function () {
        last.style.background = "url(images/newlast-control.png)";
    }, false);
    
    last.addEventListener("mouseleave", function () {
        last.style.background = "url(images/last-control.png)";
    }, false);
    
    var next = document.getElementById("next");
    next.style.background = "url(images/next-control.png)";
    
    next.addEventListener("mouseenter", function () {
        next.style.background = "url(images/newnext-control.png)";
    }, false);
    
    next.addEventListener("mouseleave", function () {
        next.style.background = "url(images/next-control.png)";
    }, false);

    我们接着用js做动画 动画部分包括: 
    1.鼠标点击第几个小圆点,就要展示第几张图片,并且小圆点的颜色也发生变化.
    2. 鼠标点击左右箭头,图片向左右移动一张
    3.图片自动轮播,(这需要一个定时器)
    4.鼠标放在图片上,图片停止自动播放(这需要清除定时器)
    5.鼠标离开图片,图片继续自动轮播 (重新开始定时器) 
    这里我们封装了一个animate()动画函数

    Cutout.Pro
    Cutout.Pro

    AI驱动的视觉设计平台

    下载
    function animate(obj, target) {  //obj为需要移动的元素,在本文中为ul,target为需要移动到的位置
        var speed = obj.offsetLeft < target ? 10 : -10;  //判断速度向左还是向右
        obj.timer = setInterval(function () {  //计时器每隔一定时间移动一次
            var result = target - obj.offsetLeft;  //剩余需要移动的距离
            obj.style.left = obj.offsetLeft + speed + "px";  //改变元素的left来实现移动          
            if (Math.abs(result) <= Math.abs(speed)) {  //当需要移动的距离小于速度时
                clearInterval(obj.timer);   //清除计时器
                obj.style.left = target + "px";  //直接移动到需要移动的位置
                flag = true;  //将flag置为true,使点击事件能再次触发
            }
        }, 1);
    }

    接下来把动画函数赋给左右箭头

    var flag = true;  //用于判断上一个事件是否执行完毕,如果没有执行完毕禁止再次触发事件
    var index = 1;  //是第几个小圆点
    var lastclick = function () {
        if (flag) {
            flag = false;  //进入事件将flag置为false
            console.log(flag);
            if (index === 1) {  //判断是否为第一张
                index = 6;
                ul.style.left = "-5700px";  //当移动到第一张时,再向右移前会替换到最后一张后面的第一张,然后再向右移动。
                animate(ul, ul.offsetLeft + liWidth); //动画函数一次向有移动一个图片长度的距离
            }
            else {
                animate(ul, ul.offsetLeft + liWidth);
            }
            index -= 1; //移动小圆点计数器
            btnShow(index);  //给新的小圆点高亮,取消上一个小圆点的高亮
        }
    }
    last.addEventListener("click", lastclick, false);  //将函数赋给点击事件
    
    var nextclick = function () {  //向左移与向右移类似
        if (flag) {
            flag = false;
            if (index === 5) {
                index = 0;
                ul.style.left = "0px";
                animate(ul, ul.offsetLeft - liWidth);
            }
            else {
                animate(ul, ul.offsetLeft - liWidth);
            }
            index += 1;
            btnShow(index);
        }
    }
    next.addEventListener("click",nextclick, false);
    
    function btnShow(cur_index) {
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = ' '; //取消全部li的类
        }
        ol.children[cur_index - 1].className = "current";  //给新的小圆点加上类
    }

    再加上一个计时器,每隔一段时间就会触发一次下一张的效果,来实现轮播

    var timer;
    function play() {
        timer = setInterval(nextclick, 3000)
    }
    
    scroll.addEventListener("load", play(), false);  //整个p全部加载完毕后开始
    
    scroll.addEventListener("mouseenter", function () { //鼠标移入图片是清除计时器
        clearInterval(timer);
    }, false);
    
    scroll.addEventListener("mouseleave", function () {  //鼠标移出图片时再次启动计时器
        play();
    }, false);

    最后给小圆点加上事件,点第几个轮播到第几张

    //小圆点的点击事件
    var olliclick = function () {
        if (flag) {
            flag = false;
            var cur_li = document.getElementsByClassName("current");
            var lastid = cur_li[0].id;  //当前的小圆点是第几个
            var distance = this.id - lastid;  //计算当前小圆点与点击的小圆点的距离(分正负)
            if (distance == 0) {
                flag = true;
            }
            else {
                animate_ol(ul, distance);
            }
        }
    }
    
    //给所有的小圆点添加上点击事件
    var ollitimer = 1
    var lis = ol.getElementsByTagName('li');
    for (ollitimer; ollitimer < lis.length+1; ollitimer++) {
        var olli = document.getElementById(ollitimer);
        olli.addEventListener("click", olliclick, false);
    }
    
    function animate_ol(obj, value) {  //小圆点动画函数
        if (value > 0) {  //判断移动方向
            var speed = -20*value; //使动画时间一致
        }
        if (value < 0) {
            var speed = -20*value;
        }
        var lastleft = obj.offsetLeft;
        obj.timer = setInterval(function () {
            var distance = Math.abs(value * liWidth) - Math.abs(obj.offsetLeft - lastleft);
            //剩余需要移动的距离
            if (distance < Math.abs(speed)) {
                clearInterval(obj.timer);
                if (value > 0) {
                    obj.style.left = obj.offsetLeft - distance + "px";
                    flag = true;
                }
                if (value < 0) {
                    obj.style.left = obj.offsetLeft + distance + "px";
                    flag = true;
                }
            }
            else {
                obj.style.left = obj.offsetLeft + speed + "px";
            }
        }, 1);
        index = index + value;
        btnShow(index);
    }

    再对一下常见的鬼畜bug进行一下总结:
    通过设置flag来防止多次点击造成的计时器冲突,在点击后将flag置为false,在动画函数结束时再置为true,这样只能在上一个点击事件动画结束后才会触发第二次。

    最后放上完整的js代码

    var scroll = document.getElementById("scroll");
    var ul = document.getElementById("ul");
    var ulLis = ul.children;
    var liWidth = ul.children[0].offsetWidth;
    
    var num = ulLis.length - 1;
    ul.appendChild(ul.children[0].cloneNode(true));
    ul.insertBefore(ul.children[num].cloneNode(true), ul.firstChild);
    
    var ol = document.getElementById("olnavi");
    for (var i = 0; i < ulLis.length - 2; i++) {
        var li = document.createElement("li");
        li.id = (i + 1);
        ol.appendChild(li);
        
    }
    ol.children[0].className = "current";
    
    var last = document.getElementById("last");
    last.style.background = "url(images/last-control.png)";
    
    last.addEventListener("mouseenter", function () {
        last.style.background = "url(images/newlast-control.png)";
    }, false);
    
    last.addEventListener("mouseleave", function () {
        last.style.background = "url(images/last-control.png)";
    }, false);
    
    var next = document.getElementById("next");
    next.style.background = "url(images/next-control.png)";
    
    next.addEventListener("mouseenter", function () {
        next.style.background = "url(images/newnext-control.png)";
    }, false);
    
    next.addEventListener("mouseleave", function () {
        next.style.background = "url(images/next-control.png)";
    }, false);
    
    var flag = true;
    var index = 1;
    var lastclick = function () {
        if (flag) {
            flag = false;
            console.log(flag);
            if (index === 1) {
                index = 6;
                ul.style.left = "-5700px";
                animate(ul, ul.offsetLeft + liWidth);
            }
            else {
                animate(ul, ul.offsetLeft + liWidth);
            }
            index -= 1;
            btnShow(index);
        }
    }
    last.addEventListener("click", lastclick, false);
    
    var nextclick = function () {
        if (flag) {
            flag = false;
            if (index === 5) {
                index = 0;
                ul.style.left = "0px";
                animate(ul, ul.offsetLeft - liWidth);
            }
            else {
                animate(ul, ul.offsetLeft - liWidth);
            }
            index += 1;
            btnShow(index);
        }
    }
    next.addEventListener("click",nextclick, false);
    
    function btnShow(cur_index) {
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = ' ';
        }
        ol.children[cur_index - 1].className = "current";
    }
    
    function animate(obj, target) {
        var speed = obj.offsetLeft < target ? 10 : -10;
        obj.timer = setInterval(function () {
            var result = target - obj.offsetLeft;
            obj.style.left = obj.offsetLeft + speed + "px";            
            if (Math.abs(result) <= Math.abs(speed)) {
                clearInterval(obj.timer);
                obj.style.left = target + "px";
                flag = true;
            }
        }, 1);
    }
    
    var timer;
    function play() {
        timer = setInterval(nextclick, 3000)
    }
    
    scroll.addEventListener("load", play(), false);
    
    scroll.addEventListener("mouseenter", function () {
        clearInterval(timer);
    }, false);
    
    scroll.addEventListener("mouseleave", function () {
        play();
    }, false);
    
    var olliclick = function () {
        if (flag) {
            flag = false;
            var cur_li = document.getElementsByClassName("current");
            var lastid = cur_li[0].id;
            var distance = this.id - lastid;
            if (distance == 0) {
                flag = true;
            }
            else {
                animate_ol(ul, distance);
            }
        }
    }
    var ollitimer = 1
    var lis = ol.getElementsByTagName('li');
    for (ollitimer; ollitimer < lis.length+1; ollitimer++) {
        var olli = document.getElementById(ollitimer);
        olli.addEventListener("click", olliclick, false);
    }
    
    function animate_ol(obj, value) {
        if (value > 0) {
            var speed = -20*value;
        }
        if (value < 0) {
            var speed = -20*value;
        }
        var lastleft = obj.offsetLeft;
        obj.timer = setInterval(function () {
            var distance = Math.abs(value * liWidth) - Math.abs(obj.offsetLeft - lastleft);
            if (distance < Math.abs(speed)) {
                clearInterval(obj.timer);
                if (value > 0) {
                    clearInterval(obj.timer);
                    obj.style.left = obj.offsetLeft - distance + "px";
                    flag = true;
                }
                if (value < 0) {
                    clearInterval(obj.timer);
                    obj.style.left = obj.offsetLeft + distance + "px";
                    flag = true;
                }
            }
            else {
                obj.style.left = obj.offsetLeft + speed + "px";
            }
        }, 1);
        index = index + value;
        btnShow(index);
    }

    相关推荐:

    原生js实现轮播图

    原生javascript实现图片轮播效果代码

    相关文章

    java速学教程(入门到精通)
    java速学教程(入门到精通)

    java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

    下载

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

    热门AI工具

    更多
    DeepSeek
    DeepSeek

    幻方量化公司旗下的开源大模型平台

    豆包大模型
    豆包大模型

    字节跳动自主研发的一系列大型语言模型

    通义千问
    通义千问

    阿里巴巴推出的全能AI助手

    腾讯元宝
    腾讯元宝

    腾讯混元平台推出的AI助手

    文心一言
    文心一言

    文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

    讯飞写作
    讯飞写作

    基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

    即梦AI
    即梦AI

    一站式AI创作平台,免费AI图片和视频生成。

    ChatGPT
    ChatGPT

    最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

    相关专题

    更多
    C++ 设计模式与软件架构
    C++ 设计模式与软件架构

    本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

    14

    2026.01.30

    c++ 字符串格式化
    c++ 字符串格式化

    本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

    9

    2026.01.30

    java 字符串格式化
    java 字符串格式化

    本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

    12

    2026.01.30

    python 字符串格式化
    python 字符串格式化

    本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

    4

    2026.01.30

    java入门学习合集
    java入门学习合集

    本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

    20

    2026.01.29

    java配置环境变量教程合集
    java配置环境变量教程合集

    本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

    18

    2026.01.29

    java成品学习网站推荐大全
    java成品学习网站推荐大全

    本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

    19

    2026.01.29

    Java字符串处理使用教程合集
    Java字符串处理使用教程合集

    本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

    3

    2026.01.29

    Java空对象相关教程合集
    Java空对象相关教程合集

    本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

    6

    2026.01.29

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    Bootstrap 5教程
    Bootstrap 5教程

    共46课时 | 3.1万人学习

    前端开发(基础+实战项目合集)
    前端开发(基础+实战项目合集)

    共60课时 | 3.9万人学习

    第二十四期_前端开发
    第二十四期_前端开发

    共161课时 | 4.4万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号