js原生实现轮播图(二)

接上一篇,第一个问题:我们要考虑图片数量,当图片数量<=1时,不显示指示器:

    //第二步:添加指示器
    var indicator_li = null;
    if (banner_li.length > 1) {
        var ul_indicator = document.getElementById("ul_indicator");
        var indicatorHtml = "";
        for (let i = 0; i < banner_li.length - 2; i++) {//要按原来的图片数量
            indicatorHtml += "<li></li>"
        }
        ul_indicator.innerHTML = indicatorHtml;
        indicator_li = ul_indicator.getElementsByTagName("li");
    }

第二个问题:实现移动端手势滑动操作:监听触摸操作,我们需要用到addEventListener方法,并且需要监听至少三个手势:
按下:关闭定时器并记录手指落点坐标

ul_banner.addEventListener("touchstart", function () {

})

滑动:根据滑动动态坐标与手指落点坐标计算动态滑动距离

ul_banner.addEventListener("touchmove", function () {

})

抬起:做一些还原操作如再次开启定时器

ul_banner.addEventListener("touchend", function () {

})

另外要计算好,手指在屏幕滑动的距离,即

moveX=手指抬起点-手指落点

手指往右滑动,轮播图往左移动,moveX就为负数,反之为正数,因为我们上面的属性left用的是百分比(也可以用px具体值),所以我们要根据滑动距离/屏幕宽度计算滑动的百分比,再加上原来的ul偏移的百分比得到最终的left偏移量!

另外一个优化点是,手指滑动图片抬起后,图片的位置该如何显示?我这里是做了一个判断处理,如果滑动图片距离超过50%,则在抬起时自动滑动到上一个或下一个图片,如果未到50%,则还原。

了解滑动原理及计算方法后,其实下面就很好写了:

function bannerCarousel() {
    // 第一步:获取banner li img列表,将列表第一张图片复制添加到最后一位,最后一张图片复制添加到第一位;
    //以本例4张图片为例,将第4张图片复制一份放到第一位,将第1张图片放置到最后一位,最后得到6张图片,
    // 这样每次轮播到position=0或者5时,将其位置重置为4或1,以实现无限滚动轮播
    var ul_banner = document.getElementById("ul_banner");
    var banner_li = ul_banner.getElementsByTagName("li");
    var banner_li_first = banner_li[0];
    var banner_li_last = banner_li[banner_li.length - 1];
    ul_banner.appendChild(banner_li_first.cloneNode(true));//将第一张图片复制一份添加到最后一位
    ul_banner.insertBefore(banner_li_last.cloneNode(true), ul_banner.firstChild);//将最后一张图片复制一份添加到第一位
    ul_banner.style.width = banner_li.length * 100 + "%";//宽度为6张图片宽度
    for (let i = 0; i < banner_li.length; i++) {
        banner_li[i].style.width = 100 / banner_li.length + "%";
    }
    ul_banner.style.left = "-100%";//因首位添加图片后,需要将整体定位到第2张图片(实际为banner第一张)

    //第二步:添加指示器
    var indicator_li = null;
    if (banner_li.length > 1) {
        var ul_indicator = document.getElementById("ul_indicator");
        var indicatorHtml = "";
        for (let i = 0; i < banner_li.length - 2; i++) {//要按原来的图片数量
            indicatorHtml += "<li></li>"
        }
        ul_indicator.innerHTML = indicatorHtml;
        indicator_li = ul_indicator.getElementsByTagName("li");
    }

    //第三步:开启定时器
    var page_index = 1;//初始位置为1
    var timer = function () {
        page_index++;
        ul_banner.style.transition = "left 0.5s";
        ul_banner.style.left = -page_index * 100 + "%";
        changeIndicator();
        reLoadPosition();
    };
    var interval = setInterval(timer, 2000);

    //指示器改变
    var changeIndicator = function () {
        if (indicator_li != null) {
            for (var i = 0; i < indicator_li.length; i++) {
                indicator_li[i].style.backgroundColor = "#ccc";
            }
            if (page_index === 0 || page_index === banner_li.length - 2) {//最后一张
                indicator_li[banner_li.length - 3].style.backgroundColor = "#fff";
            } else if (page_index === banner_li.length - 1) {
                indicator_li[0].style.backgroundColor = "#fff";
            } else {
                indicator_li[page_index - 1].style.backgroundColor = "#fff";
            }
        }
    }

    //重置banner位置
    var reLoadPosition = function () {
        setTimeout(function () {//延时操作,等待0.5s动画执行完毕后再执行以下操作
            if (page_index === 0) {
                page_index = banner_li.length - 2;
                ul_banner.style.transition = "none";
                ul_banner.style.left = (-page_index * 100) + "%";
            } else if (page_index === banner_li.length - 1) {
                page_index = 1;
                ul_banner.style.transition = "none";
                ul_banner.style.left = (-page_index * 100) + "%";
            }
        }, 500);
    }


    //滑动监听
    var screenW = window.screen.width;
    var startX, w_current_percent, w_move_percent;
    ul_banner.addEventListener("touchstart", function () {
        clearInterval(interval);
        var touch = event.targetTouches[0];
        startX = touch.clientX;
        w_current_percent = -page_index * 100;//当前left的百分比
    });
    ul_banner.addEventListener("touchmove", function () {
        var touch = event.targetTouches[0];
        var moveX = touch.clientX - startX;
        w_move_percent = moveX / screenW * 100;//跟随手指移动的百分比
        ul_banner.style.transition = "none";//重要:一定不要忘记清除过渡效果
        ul_banner.style.left = (w_current_percent + w_move_percent) + "%";

    });
    ul_banner.addEventListener("touchend", function () {
        //如果左右滑动<宽度一般,则还原为原来的位置,否则,滑动到上一位或下一位
        if ((w_move_percent < 50 && w_move_percent > 0) || (w_move_percent < 0 && w_move_percent > -50)) {
            ul_banner.style.left = w_current_percent + "%";
        } else if (w_move_percent > 50) {//往右滑动一位
            page_index--;
            ul_banner.style.transition = "left 0.5s";
            ul_banner.style.left = (w_current_percent + 100) + "%";
            changeIndicator();
            reLoadPosition();
        } else if (w_move_percent < -50) {//往左滑动一位
            page_index++;
            ul_banner.style.transition = "left 0.5s";
            ul_banner.style.left = (w_current_percent - 100) + "%";
            changeIndicator();
            reLoadPosition();
        }
        interval = setInterval(timer, 2000);
    });
}

其中重要的一点,在move过程中,一定不要忘了清除过渡效果:

ul_banner.style.transition = "none";

难点或者复杂点其实就是,滑动距离的计算,手指抬起时图片位置显示计算,以及指示器显示计算,这几点弄明白后,实现起来就不在话下了!

源码download

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白玉梁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值