JavaScript实践——有趣的轮番 | 青训营笔记

122 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第3天

前言

轮播图是指在一个模块或者窗口,通过鼠标点击或手指滑动后,可以看到多张图片。此模块常用于各网站或APP的页面。今天听《字节内部课》的JavaScript讲解颇有启发,参考了一些模板,打算自己试试如何实现它。

大致思路

1.首先所有的图片都是放在一个div中让它叠加起来的,设置层级让当前图片出现在最上面

2.为每个底部圆点按钮添加点击事件

3.用时间间隔函数让轮播图每隔一段时间自动更新

4.鼠标移入事件和鼠标移除事件

5.添加左右点击事件

6.下方动态按钮事件

搭建HTML

首先搭建HTML框架,把需要的图片放进去。
其中name="viewport"使网页同时匹配PC端和移动端。 content="width=device-width,initial-scale=1.0">定义了可视宽度为屏幕的物理宽度,且无缩放。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <title>轮番</title>
        <link href="./轮番.css" rel="stylesheet" type="text/css">
        <script src="./轮番.js"></script>
    </head>

    <body>
        <div class="view">
            <!--定义左右两个翻页的按钮-->
            <a href="#" class="prev">&lt; </a>
            <a href="#" class="next">&gt; </a>
            <ul>
                <li>
                    <img src="./img/鼠.jpg" alt="鼠">
                </li>
                <li>
                    <img src="./img/牛.jpg" alt="牛">
                </li>
                <li>
                    <img src="./img/羊.jpg" alt="羊">
                </li>
            </ul>
            <!--定义下方随模块变化的标志-->
            <ol class="circle">
                <li></li>
                <li></li>
                <li></li>
            </ol>
        </div>
    </body>
</html>

搭建CSS

搭建好HTML框架后,接下来利用CSS设置样式、完成布局和美化。
大致分为以下几个步骤:

1.处理整体样式和图片

*{
    /*重置浏览器默认样式,统一标准*/
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

li{
    list-style: none;
}

img{
    border:0;
    vertical-align: middle; /*使图片垂直对齐*/
}

/*重点:利用相对定位和overflow将图片放在同一位置*/
.view{
    position: relative; /*子绝父相,懂得都懂*/
    margin:150px auto;
    width: 500px;
    height: 400px;
    overflow: hidden; /*只展现出一个图片,其他隐藏*/
}

.view ul{
    position: absolute; /*依据父元素view进行定位*/
    top:0;
    left: 0;
    width: 500%;
}

/*重点:利用float将图片排成一行*/
.view ul li{
    float: left;
    transform: translateZ(0); /*提升性能,加快动画和转换*/
}

.view ul li img{
    width: 500px;
    height: 400px;
}

2.处理翻页按钮

a{
    text-decoration: none;
    color:blanchedalmond;
}

.prev,.next{
    position: absolute;
    width: 20px;
    height: 40px;
    background-color: rgba(0,0,0,0.3);
    top: 50%;
    margin-top: -15;
    color: #fff;
    text-align: center;
    line-height: 40px;
    font-size: 14px;
    z-index: 2; /*z-index表示元素层级,层级高的在上面*/
}

.prev{
    left: 0;
}

.next{
    right: 0;
}

3.处理下方对应图片的标志

.view ol{
    position: absolute;
    width: 150px;
    height: 15px;
    bottom: 12px;
    left: 40%;
}

ol li{
    float: left; /*设置为浮动型,使得他们出现在一排*/
    width: 20px;
    height: 5px;
    margin: 3px;
    background-color: #666565;
    padding-right: 5px;
}

ol .current {
    background-color: #fff;
}

.nav .selected {
    background-color: #f50;
}

这样页面样式就做好啦: image.png

封装js代码

接下来需要写一个使画面动起来的函数action。
其中利用setInterval函数实现定时调用。它第一个参数是回调函数,每隔一定时间执行一次; 第二个参数是间隔时间,单位是毫秒

function action(obj,target,callback){
    //清除定时器
    clearInterval(obj.timer);
    /*setInterval第一个参数是回调函数,每隔一定时间执行一次;
    第二个参数是间隔时间,单位是毫秒*/
    obj.timer = setInterval(function(){
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if(obj.offsetleft==target){
            clearInterval(obj.timer);
            callback && callback();
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    },15);
}

之后先实现左右按钮的功能。
首先需要获取css选择器的元素,这里使用getElementById函数反而更复杂,所以可以通过querySelector获取左右按钮,从而改变样式。

window.addEventListener('load',function(){
    //获取左右按钮
    var prev = this.document.querySelector('.prev');
    var next = this.document.querySelector('.next');
    //获取轮番图
    var view = this.document.querySelector('.view');
    var viewWidth = view.offsetWidth;
    //鼠标经过轮番图显示左右按钮
    view.addEventListener('mouseenter',function(){
        prev.style.display = 'block';
        next.style.display = 'block';
        clearInterval(timer);
        timer = null;
    });

    //鼠标离开时不显示左右按钮
view.addEventListener('mouseleave',function(){
    prev.style.display = 'none';
    next.style.display = 'none';
    timer = setInterval(function(){
        next.click();
    },2000);
});

再实现下部动态按钮的功能。
这时遇到一个困难:如何一直保持它的“动态”?-- 用for循环不断遍历。

//获取动态按钮
var ul = view.querySelector('ul');
var ol = view.querySelector('.circle');

for (var i = 0; i < ul.children.length; i++) {
    // 创建一个li 节点
    var li = document.createElement('li');
        // 记录小圆圈的索引号
    li.setAttribute('index', i);
        // 把li插入ol里面 节点
    ol.appendChild(li);
        // 点击小圆圈 添加类 其余移除   
    li.addEventListener('click', function() {
        // 把所有的小li 清除类名
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        // 当前小li 设置类名
        this.className = 'current';
            // 点击小圆圈移动图片 ul移动
            // 点击某个小li就拿到那个小li的索引号
        var index = this.getAttribute('index');
            // 点击某个小li 就拿到当前li的索引号给circle num
        num = circle = index;

        console.log(viewWidth);
        console.log(index);
        action(ul, -index * viewWidth);
    });
}
// 把ol里面的类名设为current
ol.children[0].className = 'current';
// 克隆第一张图片li 放到ul后面
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);

重头戏来了,实现图片的滑动。
想实现不断循环,需要在图片走到最后时复原left为0即可。
这时可以用if (num == ul.children.length - 1) { ul.style.left = 0; num = 0; }解决。左侧按钮同理。

// 点击右侧按钮图片滑动一张
var num = 0;
var circle = 0;
//右侧按钮
next.addEventListener('click', function() {
        // 无缝滑动
        if (num == ul.children.length - 1) {
            ul.style.left = 0;
            num = 0;
        }
        num++;
        action(ul, -num * viewWidth);
        // 点击右侧按钮 小圆圈一起变换
        circle++;
        if (circle == ol.children.length) {
            circle = 0;
        }
        circleChange();
    });
// 左侧按钮
prev.addEventListener('click', function() {
        // 无缝滑动
        if (num == 0) {
            num = ul.children.length - 1;
            ul.style.left = -num * viewWidth + 'px';
        }
        num--;
        action(ul, -num * viewWidth);
            // 点击右侧按钮 小圆圈一起变换
        circle--;
        // 先清除其余小圆圈的类名
        // if (circle < 0) {
        //     circle = ol.children.length - 1
        // }
        circle = circle < 0 ? ol.children.length - 1 : circle;
            // 调用函数
        circleChange();
    })
// 封装函数
function circleChange() {
    for (var i = 0; i < ol.children.length; i++) {
        ol.children[i].className = '';
    }
    ol.children[circle].className = 'current';
}
// 自动播放轮播图
var timer = this.setInterval(function() {
    // 手动点击事件
    next.click();
}, 2000);
})

这样就大功告成啦!

结束语

本以为自己学会了JavaScript基础语法已经能做一些小项目了,出手敲代码之后才知道自己是多么无助。js代码远远比自己想的复杂,参考了博客blog.csdn.net/m0_56712012…
源码为我的思路提供了很大的帮助。也清楚认识到自己所学的远远不够。 前端学习还在继续!