保姆式原生Js简单轮播图+缓速动画封装教程

轮播图的原理:
一系列的大小相等的图片平铺,利用CSS布局只显示一张图片,其余隐藏。通过计算偏移量利用定时器实现自动播放,或通过手动点击事件切换图片。
在这里插入图片描述
HTML布局
父容器box存放所有内容,子容器screen存放图片,current存放按钮序号.
left/right做移入出现箭头,点击左右滑动图片效果

<div class="all" id='box'>        
  <div class="screen">            
    <ul>                
      <li><img src="image/timg.jpg" width="500" height="200" /></li>                
      <li><img src="image/11.jpg" width="500" height="200" /></li>                
      <li><img src="image/timg2.jpg" width="500" height="200" /></li>                
      <li><img src="image/timg3.jpg" width="500" height="200" /></li>                
      <li><img src="image/timg4.jpg" width="500" height="200" /></li>            
    </ul>            
    <ol>                
      <li class="current">1</li>                
      <li>2</li>                
      <li>3</li>                
      <li>4</li>               
      <li>5</li>            
    </ol>
  </div>        
        <div id="arr"><span id="left">&lt;</span><span id="right">&gt;</span></div>    
  </div>

CSS布局
screen里设置overflow: hidden;可以只显示视口大小的图片,其余隐藏.
这里注释掉是为了方便观察效果,

 <style type="text/css">        
 * {
    
                
    padding: 0;            
    margin: 0;            
    list-style: none;            
    border: 0;        
}
        
 .all {
    
               
     width: 500px;            
     height: 200px;           
     padding: 7px;            
     border: 1px solid #ccc;            
     margin: 100px auto;            
     position: relative;        
}
.screen {
    
                
      width: 500px;            
      height: 200px;            
      /* overflow: hidden; */            
      position: relative;        
}
.screen li {
    
                
          width: 500px;            
          height: 200px;           
          overflow: hidden;            
          float: left;        
}
 .screen ul {
    
                
       position: absolute;            
       left: 0;            
       top: 0px;           
       width: 3500px;//五张图片加两张复制的宽度        
 }
       
.all ol {
    
                
        position: absolute;            
        right: 10px;            
        bottom: 10px;            
        line-height: 20px;            
        text-align: center;        
 }
.all ol li {
    
                
       float: left;            
       width: 20px;            
       height: 20px;            
       background: #fff;            
       border: 1px solid #ccc;            
       margin-left: 10px;            
       cursor: pointer;        
}
.all ol li.current {
    
                
         background: yellow;        
}
#arr {
    
                
   display: none;        
   }
#arr span {
    
                
   width: 40px;            
   height: 40px;            
   position: absolute;            
   left: 5px;            
   top: 50%;            
   margin-top: -20px;            
   background: #000;            
   cursor: pointer;            
   line-height: 40px;            
   text-align: center;            
   font-weight: bold;            
   font-family: '黑体';            
   font-size: 30px;           
   color: #fff;            
   opacity: 0.3;           
   border: 1px solid #fff;        
}
 #arr #right {
    
                
    right: 5px;            
    left: auto;        
}   
 </style>

js部分
1:鼠标进去的时候,显示左右两个箭头,鼠标移出,隐藏箭头

获取相关要操作的数据

let box = document.getElementById('box');
let arr = document.getElementById('arr');
let left = document.getElementById('left');
let right = document.getElementById('right');
let screen = box.querySelector('.screen');
let ul = screen.querySelector('ul');
let ol = screen.querySelector('ol');
let uLis = ul.children;
let oLis = querySelectorAll('li');

移入事件:box事件onmouseover:显示div#arr
移出事件:box事件onmouseout:隐藏div#arr

box.onmouseover = function () {
    
    
    arr.style.display = 'block';
};
box.onmouseout = function () {
    
    
    arr.style.display = '';
};

2:点击左右两边的箭头,向左,图片看上一张;向右,图片看下一张

优化,无缝滚动。
当从最后一张图切换回第一张图时,会有很大空白过渡,利用两张辅助图来填补这个空白。
这里补充下无缝滚动,直接看代码,复制最后一张图片放置第一张图片前,同时复制第一张图片放置最后一张图片的后面。

//拿到图片:第一个li和最后一个li(深克隆)
let first = uLis[0].cloneNode(true);
let last = uLis[uLis.length - 1].cloneNode(true);
//将第一张放到最后,最后一张放到最前
ul.insertBefore(last, uLis[0]);
ul.appendChild(first);

用户应该看到的是第一张图片:让整个ul向左移动500:screen.offsetWidth == 500

 box.style.left = -screen.offsetWidth + 'px';

在这里插入图片描述
3. 定义一个变量( 全局): 用来记录当前图片的位置:

let index = 1;//1 此时代表是真正的第1张(也就是现在的第2张)

在这里插入图片描述

封装一个缓速动画做效果,以后可以随时调用.
创建一个后缀为.js的文档.

/** 
 * 缓速动画(向右移动)
 * @param {element} ele ,要移动的元素
 * @param {number} target,要移动的目标位置
*/
function animateSlow(ele, target) {
    
    
// 清理定时器:元素自己的定时器,自己保存
// ele.timeId 访问ele对象的timeId属性:没有得到的结果undefined
   clearInterval(ele.timeId);      // 有就清除,没有就什么都没做
// ele的移动:将当前元素自己的定时器存到自己的对象属性中
   ele.timeId = setInterval(function () {
    
    
  // 拿到ele的边距
     let left = ele.offsetLeft;
  // 计算步长
 // 如果是向右移动:最终是1px移动:Math.ceil(小数) 得到1
 // 如果是向左移动:最终是-1px移动:Math.ceil(-小数) 得到0
 // let step = Math.ceil((target - left) * 0.1);

// 让step根据目标结果(可正可负)
   let step = (target - left) * 0.1;
// 根据step的正负关系:求最小的1px
// step > 0 :target(目标)比left(当前位置)大,向右移动:+1
// step < 0 :target(目标)比left(当前位置)小,向左移动:-1
   step = step > 0 ? Math.ceil(step) : Math.floor(step);
// 计算下一个位置
   let next = left + step;
// console.log(left, step);
// 判定位置
   if (next == target) {
    
    
    // 下一步要到target:直接设定target
       ele.style.left = target + 'px';
    // 终止定时器:定时器存储在自己ele的属性中
       clearInterval(ele.timeId);
    // 结束当前函数
      return;
}
// 正常移动
   ele.style.left = next + 'px';
    }, 20);
};

引入动画js文档
4. 点击左键事件操作:移动ul,移动是screen屏幕对应的宽度(li)

// left.onclick = funciton(){};    // 匿名回调
left.onclick = leftClick;
function leftClick() {
    
    
 // 看前一张:下标-1即可
 index--;
 //  做动画:index变成了0,让ul移动:移动 -index * screen.offsetWidth
animateSlow(ul, -index * screen.offsetWidth);
}

一直点击运行后会发现出现空白,只能通过点击右键才能回往回走在这里插入图片描述

function leftClick() {
    
    
if (index == 0) {
    
    
    //index--就表示前面一张图片,如果index已经等于0:说明当前的图片本质是看的最后一张(效果是第一张):为了保证动画效果
    // 让index瞬间变成倒数第二张:最后加了个第一张
    index = uLis.length - 2;
    // 让ul瞬间移动到倒数第二张
    ul.style.left = -index * screen.offsetWidth + 'px';
}
 // 看前一张:下标-1即可
 index--;
 //  做动画:index变成了0,让ul移动:移动 -index * screen.offsetWidth
animateSlow(ul, -index * screen.offsetWidth);
}

在这里插入图片描述
右边同理,让ul向左移动

right.onclick = rightClick;
function rightClick() {
    
    
    // 如果index已经是最后一张:本质代表的是有效第一张:瞬移到一张:index应该重置为1
    if (index == uLis.length - 1) {
    
    
        index = 1; // 回到第一张(此时看的是最后一张)
        // 瞬移到第一张
        ul.style.left = -screen.offsetWidth + 'px';
    }
    index++;
    // 3. 动画效果
    animateSlow(ul, -index * screen.offsetWidth);

在这里插入图片描述
把css样式里面的隐藏注释解开,大致的样子就做出来了,可以左右点击试下效果
接下来做点击左右按钮根据图片转换数字序号

function leftClick() {
    
    
if (index == 0) {
    
    
// 要考虑index = 0,本身当前看到的是第5张,下一次要看第4张
oLis[index == 0 ? oLis.length - 1 : index - 1].classList.remove('current');//去除赋值给li下标的类名
       index = uLis.length - 2;
    ul.style.left = -index * screen.offsetWidth + 'px';
}
 index--;
animateSlow(ul, -index * screen.offsetWidth);
oLis[index == 0 ? oLis.length - 1 : index - 1].classList.add('current');//赋值给已经自减li下标的类名
}

右边

right.onclick = rightClick;
function rightClick() {
    
    
    oLis[index == uLis.length - 1 ? 0 : index - 1].classList.remove('current');
// 如果index已经是最后一张:本质代表的是有效第一张:瞬移到一张:index应该重置为1
    if (index == uLis.length - 1) {
    
    
        index = 1;
        ul.style.left = -screen.offsetWidth + 'px';
    }
    index++;
 
    animateSlow(ul, -index * screen.offsetWidth);
    oLis[index == uLis.length - 1 ? 0 : index - 1].classList.add('current');

点击页面数字可以直接跳到对应的图片上

// 1. oLis里面的li的下标与 index之间的关系: oLis的下标 + 1 = index
oLis.forEach(function (item, key) {
    
    
//item代表元素,key代表下标
    item.onclick = function () {
    
    
        let oldOlisKey = index - 1;
        if (index == 0) oldOlisKey = oLis.length - 1;
        if (index == 6) oldOlisKey = 0;
        //求出原来的页面的下标: 去除原来页码的样式
        oLis[oldOlisKey].classList.remove('current');
        //计算index当前的值: index = 当前页码下标 + 1
        index = key + 1;
        console.log(index)
        //利用index动画效果实现
        animateSlow(ul, -index * screen.offsetWidth);
        //将当前页面对应的样式: 高亮显示        
        item.classList.animateSlow('current');

轮播图就是会自己动,少不了定时器,定时器有setTimeout(回调函数,时间间隔),setInterval(回调函数,时间间隔)两种,前者执行一次,后者无限.
最后实现定时器触发自动向右轮播:let 变量=setInterval(回调函数,毫秒);
写在页面最开始获取元素后面加上即可.

let timeId = setInterval(rightClick, 3000);

加强版: 鼠标移入box的时候:清除自动轮播定时器.
添加到页面最开始box移入函数里面

 clearInterval(timeId);

鼠标移出box的时候:又继续轮播
添加到页面最开始box移出函数里面

timeId = setInterval(rightClick, 3000);

总结:要清楚理解到下标/图片播放模式,代码量不算多,基本做完左边右边复制粘贴修改一下就可以了.
顺带还封装了个动画,比较占代码,大家可以根据自身需求修改.有不明白的或建议可以留言.

猜你喜欢

转载自blog.csdn.net/weixin_47886687/article/details/108222628