原生JavaScript实现无缝轮播图

无缝轮播图是页面常用的特效之一,然而在实际的开发过程中,大部分的开发者都会使用插件来对轮播图进行开发,那么它的底层到底是怎么实现的呢,本文章将围绕这一问题展开探讨。

在讨论如何利用原生JS实现图片之间无缝切换轮播的动画效果之前,我们先来谈谈无缝轮播图片的css布局。

首先我们需要一个用来显示图片的DIV容器,然后把想要轮播的图片没有缝隙的排成一行放入DIV容器中,给DIV容器设置 overflow: hidden,这样在页面中就可以只看到一张图片,然后通过利用JS来移动ul的left值就能达到无缝轮播的动画效果。

然而这还不够,我们还需要在第一张图片前放最后一张图片,以及在最后一张图片后放第一张图片,这样做得目的是为了实现第一张图片和最后一张图片切换时能达到无缝的动画效果。核心代码和布局效果如下:

<div id="box">
    <ul>
        <li><img src="img/5.jpg"></li>
        <li><img src="img/1.jpg"></li>
        <li><img src="img/2.jpg"></li>
        <li><img src="img/3.jpg"></li>
        <li><img src="img/4.jpg"></li>
        <li><img src="img/5.jpg"></li>
        <li><img src="img/1.jpg"></li>
    </ul>
</div>

下图是给DIV容器设置overflow: hidden前的效果:

布局搞定之后,接下来就是如何利用原生JS实现无缝轮播。

首先我们需要两个核心的函数,一个用于实现图片无缝切换时的减速运动,另一个用于获取ul的left值(注意:无缝轮播每次移动的都是整个ul的left值)

function fnMove(ele, obj,callback) {
    //参数一:需要动态变化样式的元素
    //参数二:一个对象 其 键为需要变化的css属性名,值为css属性目标值 例{fontSize:500,height:140,opacity:50}
    //参数三:回调如果动画结束 调用该函数

    clearInterval(ele.timer);

    //创建计时器动态的修改 目标元素的css属性值
    // 用ele存储timer 目的不让计时器number被释放,导致无法阻止计时器
    ele.timer = setInterval(function () {

        var fnStop = true; //标记 判断是否所有动画都达到目标值

        for (var attr in obj) { //遍历对象 获取到所有需要修改的属性名和目标值
            var curr = 0;
            // 元素当前css属性值 如果属性是opacity 0 - 1
            // 因为我们的速度大于等于1 直接操作0-1小数不太好操作
            // 我们对他进行放大100倍操作
            if(attr == ‘opacity‘){
                curr = parseInt(getStyle(ele, attr)*100)
            }else {
                curr = parseInt(getStyle(ele, attr))
            }

            //定义一个速度 让目标元素 每30毫秒增加5像素 直到达到目标值停止计时器(动画结束)
            //减速运动 目标值(不变) - 减去当前值(越来越接近目标) 减出来的结果越来越小 除以6不要让当前值一瞬间达到目标值
            var speed = (obj[attr] - curr)/6;
            //放大动作  0.3 => 1   -0.3 => -1 避免让速度等于0
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

            if(speed != 0){
                fnStop = false;
            }

            // console.log(curr);
            //动态改变css属性值  如果是透明度 我们之前给他乘以100倍 这里需要还原回0-1的数
            if(attr == ‘opacity‘){
                ele.style[attr] = parseFloat((curr + speed)/100);
                //透明度兼容写法 老版本浏览器透明度为0-100
                ele.style.filter = ‘alpha(opacity:‘+(curr + speed)+‘)‘
            }else {
                ele.style[attr] = curr + speed + ‘px‘
            }

        }
        //所有动画完成,调用回调函数(可选)
        if (fnStop){
            clearInterval(ele.timer);
            if(callback){
                callback();
            }
        }
    }, 30)
function getStyle(ele, sAttr) {
    //参数一:需要获取的元素对象
    //参数二:需要获取的样式属性
    //兼容写法获取 元素css样式的值
    //高版本浏览器getComputedStyle(元素,伪类),不是伪类设为null,返回的是一个CSS样式声明对象
    if (window.getComputedStyle) {
        sAttr = window.getComputedStyle(ele, null)[sAttr];
    } else {
        //低版本浏览器
        sAttr = ele.currentStyle(sAttr);
    }
    return sAttr
}

有了这两个方法,实现无缝轮播将变得简单。

首先我们需要一个定时器,让图片每两秒进行一次轮播。其次,我们还需要一个用于移动图片的函数,把该函数放入定时器中,每两秒调用一次,实现轮播效果。

 //通过js获取图片/li的宽度,得到每次轮播移动多少像素
 var imgWidth = liList[0].offsetWidth;
 //定义当前轮播图的下标(用来记录下一次该展示第几张图片)
 var index = 1; // 图片从第一张开始 index==0 其实是最后一张图片
 //页面小圆点高亮的下标
 var num = 0;
 //开始进行轮播
 box.timer = setInterval(showRight, 2000);
function showRight() {
    index++;
    num++;
    if (num >= spans.length) { //spans为与展示图片数量相同的小点数组
    num = 0;
    }
    if (index >= liList.length) { //上一次已经展示了第一张(li最后一张)了,该展示第二张
     // 直接设置css属性left 是没有动画效果的 无缝的让最后一张跳回 第1张
    ul.style.left = -imgWidth + ‘px‘;
    //改变index值 动画效果的让第一张移动到第二张
    index = 2;
    }
    fnMove(ul, {left: -imgWidth * index})
    activeSpan(num);  //点亮与图片相对应的小圆点
}
//高亮小圆点方法
function activeSpan(num) {
    for (var i = 0; i < spans.length; i++) {
    spans[i].className = ‘‘;
    }
    spans[num].className = ‘bgcolor‘
}

效果图:

接下来给左右按钮绑定点击事件,右按钮每次点击就是调用一次showRight()函数,有了showRight()函数,showLeft()函数也很容易编写出来(注意:每次点击需要清除原来进行轮播的定时器):

left.onclick = function (e) {
     //阻止事件冒泡的兼容写法
      e = e || window.event;
      window.event ? e.cancelBubble = true : e.stopPropagation();
      clearInterval(box.timer);
      showLeft();
      }
 right.onclick = function (e) {
       e = e || window.event;
       window.event ? e.cancelBubble = true : e.stopPropagation();
       clearInterval(box.timer);
       showRight();
       }

效果图(实际有鼠标在对左右按钮进行点击):

最后利用for循环给每个小圆点绑定点击事件,这里涉及到JS一个特性:异步事件队列。

在这里简单解释一下:页面加载时是从上往下地对代码进行同步加载,当遇到需要事件触发的回调函数时,JS会把该回调函数丢入异步事件队列当中,然后继续往下加载代码。当页面中有事件被触发时,JS会从异步事件队列中调用与该事件绑定的所有回调函数。

所以,在利用for循环给每个小圆点绑定点击事件时,我们需要记录下每个小圆点的下标,在调用与点击小圆点事件绑定的回调函数中读取与小圆点对应的下标。

//给小圆点添加点击
function spansClick() {
    for (var i = 0; i < spans.length; i++) {
        //记录每个小圆点的下标
        spans[i].index=i;
        spans[i].onclick = function (e) {
            e = e || window.event;
            window.event ? e.cancelBubble = true : e.stopPropagation();
            //读取每个小圆点的下标
            num = this.index;
            index = num + 1; //index永远比num大1
            activeSpan(num);
            fnMove(ul, {left: -imgWidth * index})
        }
    }
}

效果图(实际有鼠标对小圆点进行点击)

时间: 2024-10-06 19:44:35

原生JavaScript实现无缝轮播图的相关文章

Web前端原生JavaScript浅谈轮播图

1.一直来说轮播图都是困扰刚进业内小白的一大难点,因为我们不仅需要自己作出一个比较完美的运动框架(虽然网上一抓一大把,但是哪有比自己做出来实现的有成就感,不是吗?^_^),还必须需要非常关键性的把握住轮播的原理,这样才能把一个轮播图完美的呈现出来. 2.废话不多说,请看下面代码 1 //首先我们必须都明确,一个好的运动框架那必须是能够同时承载两种或多种以上需求的,所以我们应该避免单运动框架通过行内样式的局限性,就需要我们知道怎么去获取非行间样式 2 function getStyle(obj,a

纯原生javascript仿网易轮播图

第一次有自己的关于代码的博客,感到诚惶诚恐.这可能是我第一次以程序猿,或者连初级程序猿都不是的身份下开通的个人“技术”(胡写乱写)博客园地.闲言碎语不要讲,咱今天就写一点关于js的代码吧.网易首页大家肯定都去过,在首页左侧部分有个轮播图,效果很好,构思精巧,非常诱人.注,此demo非本人原创,在这里进行个人解读,力求通俗易懂(主要是让我自己明白!). 那么如何实现相关技术,进而实现如图效果呢?下面的进度条是用JQuery写的,这里暂不考虑.下面从三个方面讨论网一轮播图. 一.HTML部分 1 <

原生javascript之实战 轮播图

成品效果如下图所示: 因为博客园限制图片上传大小被我删了一些帧数,所以图片看起来会有一点卡,现实运行是不会的 搭建HTML和CSS结构 HTML代码如下: 1 <div class="wrapper"> 2 <ul class="sliderPage"> 3 <li> 4 <img src="images/1.jpg"> 5 </li> 6 <li> 7 <img sr

左右无缝轮播图的实现

无缝轮播图: <title>无缝轮播图</title> <style> *{margin: 0;padding:0; } ul{list-style: none;} .banner{width: 600px;height: 300px;border: 2px solid #ccc;margin: 100px auto;position: relative;overflow: hidden;} .img{position: absolute;top: 0;left: 0}

一个用原生JS造的轮播图插件

a native-js slider 一个无缝轮播图的小轮子 ( ?° ?? ?°)?? 前言 自己弄这个轮子是来自之前vue做一个音乐播放器项目时,用到了一个第三方vue组件better-scroll,当时参考这个文档做轮播图的时候,发现slider-item真实渲染出来的多了两个节点,向作者提问了下,回答当传入 snap:{loop:true} 的时候,前后各 clone 一个节点,保证可以无缝循环轮播,那么多克隆这两个节点是怎么实现无无缝轮播图呢,查阅了相关原理,就做了下这个轮子. 在线演

JS 无缝轮播图1-节点操作

无缝轮播图 (使用节点操作) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> *{ padding:0; margin:0; } body{ background:#F5F5F5; } #content{ width:300px; height:200px;

原生JS实现简易轮播图

原生JS实现简易轮播图(渐变?) 最近做网页总是会用到轮播图,我就把之前写的轮播图单独拿出来吧,如果有...如果真的有人也需要也可以复制去用用啊..哈~.. window.onload = function() { var tab = 0; var loop_imgs = new Array("img/l1.jpg", "img/l2.jpg", "img/l3.jpg", "img/l4.jpg", "img/l5

photoSlider-html5原生js移动开发轮播图-相册滑动插件

简单的移动端图片滑动切换浏览插件 分别引用css文件和js文件 如: <link rel="stylesheet" type="text/css" href="css/photoSlider.min.css" /> <script src="js/photoSlider.min.js" type="text/javascript" charset="utf-8">

无缝轮播图的一种方式原理

之前面试被问到这个问题,之前都是随便找大神插件,知道怎么去做,但是一直没实现过. 无缝轮播的原理 在滚动层前后分别插入最后一个元素和最前面一个元素,然后在动画滚到最后或者最前的时候,初始化滚动层的位置样式,速度很快,无法察觉,就如同无缝一般. html片段 <div class="wrap"> <ul> <li><img src="1.jpg"/></li> <li><img src=&q