案例——轮播图(原生JS实现)

效果图
在这里插入图片描述
首先我们来理一下思路

  • 搭建结构

    注意点:
    我们需要一个container轮播图容器,溢出隐藏
    我们需要一个wrapper容器用于存放所有的图片,wrapper相对于container定位,后期改变wrapper的left值实现轮播图的切换

  • 写样式…

  • 写js

  1. 获取所有需要操作的元素
  2. 获取数据(基于AJAX异步获取数据,当然没有服务器提供数据,只能自己写一点)
  3. 实现数据绑定HTML页面(基于Promise管理异步操作)
    注意绑定的时候图片要多绑定一个,便于后面实现无缝轮播
  4. (每隔interval秒,实现单张轮播图的自动运动和切换)
  5. 实现轮播图的自动运动和切换
    - 设置轮播图运动的基础参数(全局变量)stepIndex,autoTimer,interval
    - 开启定时器驱动自动轮播(实现每隔interval秒轮播图的自动运动和切换)
    - stepIndex++(图片要切换了,当前图片索引改变)
    - 当索引大于原来的长度,让其立即运动到第一张,再让其运动第二张(最后一张图片和第一张图片一摸一样,立即运动表示直接设置它的left属性,让它在运动最后一张图片的时候切换到第一张图片,人眼是看不出来的跳转的,这样可以实现无缝衔接)
    - 设置动画(让图片在1秒内完成切换)
    - 切换焦点
  6. 实现鼠标进入和离开自动轮播的停止和开启,和按钮的隐藏和显示
  7. 实现点击焦点时图片的切换
  8. 实现点击按钮时图片的切换

然后直接上代码!!!
html

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>轮播图</title>
    <link rel="stylesheet/less" href="css/banner.less">
    <script src="js/less.min.js"></script>
</head>

<body>
    <section class="container" id="container">
        <div class="wrapper">
            <!-- <div><img src="img/1.png" alt=""></div>
            <div><img src="img/2.png" alt=""></div>
            <div><img src="img/3.png" alt=""></div>
            <div><img src="img/4.png" alt=""></div> -->
        </div>
        <ul class="focus">
            <!-- <li class="active"></li>
            <li></li>
            <li></li>
            <li></li> -->
        </ul>
        <a href="javascropt:;" class="arrow arrowLeft"></a>
        <a href="javascropt:;" class="arrow arrowRight"></a>
    </section>
    <script src="js/utils.js"></script>
    <script src="js/animate.js"></script>
    <script src="js/banner.js"></script>
</body>

</html>

css

@import "baseCss";
.container{
    position: relative;
    margin: 20px auto;
    width: 1000px;
    height: 300px;
    overflow: hidden;
    .wrapper{
        position: absolute;
        left: 0;
        top: 0;
        width: 4000px;
        height: 100%;
        div{
            float: left;
            width: 1000px;
            height: 100%;
            img{
                width: 100%;
                height: 100%;
            }
        }
    }
    .focus{
        position: absolute;
        left: 50%;
        bottom: 10px;
        transform: translateX(-50%);
        height: 12px;
        border-radius: 6px;
        background: rgba(0, 0, 0, .5);
        li{
            float: left;
            margin: 3px;
            width: 6px;
            height: 6px;
            background: #fff;
            border-radius: 50%;
            &.active{
                background: lightseagreen;
            }
        }

    }
    .arrow{
        position: absolute;
        
        display: none;
        width: 41px;
        height: 69px;
        &.arrowLeft{
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            background: url(../img/icon-slides.png) no-repeat -84px 0;

            &:hover{
                background: url(../img/icon-slides.png) no-repeat 0 0;

            }
        }
        &.arrowRight{
            right: 0;
            top: 50%;
            transform: translateY(-50%);
            background: url(../img/icon-slides.png) no-repeat -126px 0;

            &:hover{
                background: url(../img/icon-slides.png) no-repeat -42px 0;

            }
        }
    }
}

js

let bannerRender = (function() {
    //1. 获取操作的的元素
    let container = document.querySelector('#container'),
        wrapper = container.querySelector('.wrapper'),
        focus = container.querySelector('.focus'),
        arrowLeft = container.querySelector('.arrowLeft'),
        arrowRight = container.querySelector('.arrowRight'),
        slideList = null,
        focusList = null;

    //轮播图运动的基础参数
    let stepIndex = 0, //记录当前展示快的索引
        autoTimer = null, //自动轮播的定时器
        interval = 3000; //间隔多长时间自动切换

    //2. 获取数据
    let queryData = function() {
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            xhr.open('get', 'json/banner.json', true); //异步获取数据
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    let data = JSON.parse(xhr.responseText);
                    resolve(data);
                }
            };
            xhr.send(null);
        });
    };
    //3. 实现数据绑定(获取数据成功之后执行数据绑定方法)
    let bindHTML = function(res) {

        let strSlide = ``,
            strFocus = ``;
        res.forEach((item, index) => {
            let {
                id,
                img = 'img/1.png',
                desc = 'xiaomi',
                link
            } = item;
            strSlide += `<div><img src="${img}" alt="${desc}"></div>`;
            //ES6模板字符串${}存放的是JS表达式,但是表达式要有返回值,因为我们要把返回值拼接到模板字符串中
            strFocus += `<li class="${index === 0?'active':''}"></li>`
        });
        //克隆一份到末尾
        strSlide += `<div><img src="${res[0].img}" alt="${res[0].desc}"></div>`;
        wrapper.innerHTML += strSlide;
        focus.innerHTML += strFocus;

        slideList = wrapper.querySelectorAll('.wrapper > div');
        focusList = focus.querySelectorAll('.focus > li');
        //根据slide的个数动态计算wrapper的宽度
        utils.setCss(wrapper, 'width', slideList.length * 1000);
    };
    //改变焦点
    let changeFocus = function() {
        let tempIndex = stepIndex; //创建临时索引
        tempIndex === slideList.length - 1 ? tempIndex = 0 : null;
        [].forEach.call(focusList, (item, index) => {
            item.className = index === tempIndex ? 'active' : '';
        });
    };
    //4. 实现轮播图的运动和切换
    //轮播图无缝衔接原理:
    //- 克隆第一张到末尾(在数据绑定的时候克隆)
    //- 正常累加运动,当运动到末尾(此时的末尾是克隆的哪一张),再过3秒切换的时候,后面就没有图片了,此时我们让其立即切换到真实第一张的位置
    // (立即切换,没有动画,left=0,刚才展示的最后一张和真实的第一张长的一样,给用户感觉没有切换),紧接着运动到第二张即可
    let autoMove = function() {

        stepIndex++;
        //如果索引大于原来的长度,让其瞬间运动到第一张,再让其运动到第二张
        if (stepIndex > (slideList.length - 1)) {
            utils.setCss(wrapper, 'left', 0);
            stepIndex = 1; //不是等于0,而是等于1,这样可以切换到第二张
        }
        //基于自己封装的animate实现动画
        animate(wrapper, {
            left: -stepIndex * 1000
        }, 1000);

        //每一次运动完成,需要让焦点跟着切换
        changeFocus();

    };

    //5. 实现鼠标进入和离开控制自动轮播的停止和开启
    let handleContainer = function() {
        container.onmouseenter = function() {
            clearInterval(autoTimer);
            arrowLeft.style.display = arrowRight.style.display = 'block';
        };
        container.onmouseleave = function() {
            autoTimer = setInterval(autoMove, interval);
            arrowLeft.style.display = arrowRight.style.display = 'none';
        };
    };
    //6. 实现点击焦点图片切换
    let handleFocus = function() {
        [].forEach.call(focusList, (item, index) => {
            item.onclick = function() {
                stepIndex = index;
                animate(wrapper, {
                    left: -stepIndex * 1000
                }, 1000);
                changeFocus();
            };
        });
    };
    //7. 实现点击按钮图片
    let handleArrow = function() {
        arrowRight.onclick = autoMove;
        arrowLeft.onclick = function() {
            stepIndex--;
            //如果索引小于零,则是第一张,不能再向右运动了,此时因当瞬间运动到最后一张(和第一张一模一样),再让其运动到倒数第二张
            if (stepIndex < 0) {
                utils.setCss(wrapper, 'left', -(slideList.length - 1) * 1000);
                stepIndex = slideList.length - 2;
            }
            animate(wrapper, {
                left: -stepIndex * 1000
            }, 1000);
            changeFocus();
        };
    }
    return {
        init: function() {
            let promise = queryData();
            promise.then(res => {
                bindHTML(res);
            }).then(() => {
                //开启定时器驱动的自动轮播
                autoTimer = setInterval(autoMove, interval);
            }).then(() => {
                //左右按钮或者焦点切换
                handleContainer();
                handleFocus();
            	handleArrow();
            });
        }
    };
})();
bannerRender.init();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值