告别组件之教你使用原生js和css写移动端轮播图

在工作中由于项目需要要写一个轮播图,本想使用组件直接调用实现快速开发,但是一想到自己经常使用组件但是让自己手写的话确实一点都不会。

一个不会手写组件的前端程序员不是一个好程序员!于是打算自己手写一个。

老规矩,首先看一下最终效果,这个最终可以实现定时自动播放,触摸滑动,手动修改下面横条效果等功能。

项目中使用到的HTML代码如下

<div class="banner">
    <ul class="clearfix">
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner2.png"></a></li>
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner1.png"></a></li>
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner2.png"></a></li>
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner1.png"></a></li>
    </ul>
    <ul>
        <li class="now"></li>
        <li></li>
    </ul>
</div>

原理简介

在这里我们以两张轮播图为例,由图上可以注意到,我们一共放了四张轮播图,为什么呢?因为我们在向右滑动的过程中为了保证某张轮播图的右边始终有一个轮播图可以看到,于是我们把轮播图的最后一张放在最前面,轮播图的第一张放在最后面。当轮播图滑到最后面的时候,此时消除动画效果,把轮播图的transformX调到第二张轮播图的所在位置,如上图所示。

自动播放

首先我们来实现以下自动播放,项目中我没有使用jQuery,而是直接使用的原生js,我们先来获取一下dom元素。

要注意:在移动端并没有使用px作为定位距离单位,而是使用的相对距离,在这里我是基于750px的设计稿进行计算,按照我的计算规则:

1rem = 100px

也就是说,设计稿上的100px相当于我的html界面的1rem,具体的rem应用方法请移步我的??另一篇博客??

var imageCount = 2; //页面中用来轮播的图片有2张不同的
//轮播图大盒子
var banner = document.querySelector(".banner");
//图片的宽度,相当于width:100%
var width = 7.5;
//图片盒子
var imageBox = banner.querySelector("ul:first-child");
//点盒子
var pointBox = banner.querySelector("ul:last-child");
//所有的点
var points = pointBox.querySelectorAll("li");

在之后我们还会用到监听组件过渡动画结束之后触发的函数,因为我们要兼容webkit内核的浏览器,所以要写两个,这个我们不妨对此函数做一下封装,在一个函数里面进行两种浏览器的操作。

/*定义的一个命名空间*/
window.my = {};
/*封装一个事件 过渡结束事件*/
my.transitionEnd = function(dom,callback){
    //1.给谁加事件
    //2.事件触发后处理什么业务
    if(!dom || typeof dom != 'object'){
        //没dom的时候或者不是一个对象的时候 程序停止
        return false;
    }
    // 非webkit内核
    dom.addEventListener('transitionEnd', function(){
        callback && callback();
    });
    // webkit内核
    dom.addEventListener('webkitTransitionEnd', function(){
        callback && callback();
    });
}

接下来我们实现一下添加过渡效果,消除过渡效果,给轮播图定位,设置定时器,轮播图过渡效果结束之后触发的函数。

//加过渡
var addTransition = function() {
  imageBox.style.transition = "all 0.3s";
  imageBox.style.webkitTransition = "all 0.3s"; /*做兼容*/
};
//清除过渡
var removeTransition = function() {
  imageBox.style.transition = "none";
  imageBox.style.webkitTransition = "none";
};
//定位
var setTranslateX = function(translateX) {
  imageBox.style.transform = "translateX(" + translateX + "rem)";
  imageBox.style.webkitTransform = "translateX(" + translateX + "rem)";
};

//功能实现
//自动轮播  定时器  无缝衔接  动画结束瞬间定位
var index = 1;
var timer = setInterval(function() {
  index++; //自动轮播到下一张
  //改变定位  动画的形式去改变  transition transform translate
  addTransition(); //加过渡动画
  setTranslateX(-index * width); //定位
}, 3000);

//等过渡结束之后来做无缝衔接
my.transitionEnd(imageBox, function() {
  /*
  * 这边就出现了我们上面示意图中的transformX由最后一张图片的位置移动到第二张图片的位置
  * 1. 取消过渡动画
  * 2. 定位
  */
  if (index > imageCount) {
    index = 1;
  } else if (index <= 0) {
    index = imageCount;
  }
  removeTransition(); //清除过渡
  setTranslateX(-index * width); //定位
  setPoint(); //设置底部显示当前图片对应的圆角
});

// 这个函数的效果就是改变轮播图小横条的样式,把在当前位置的小横条填充成白色,具体样式可以自定义
var setPoint = function() {
  //清除上一次的now
  for (var i = 0; i < points.length; i++) {
    points[i].className = " ";
  }
  //给图片对应的点加上样式
  points[index - 1].className = "now";
};

到这里我们就可以实现轮播图定时滚动了。

触摸滚动

手指滑动的时候调用touch事件让轮播图滑动,记录坐标轴的改变 改变轮播图的定位(位移css3),当滑动的距离不超过一定的距离的时候 需要吸附回去 过渡的形式去做, 当滑动超过了一定的距离 需要 跳到 下一张或者上一张 (滑动的方向) 一定的距离(屏幕的三分之一)

//touch事件
var startX = 0; //记录起始  刚刚触摸的点的位置 x的坐标
var moveX = 0; //滑动的时候x的位置
var distanceX = 0; //滑动的距离
var isMove = false; //是否滑动过

imageBox.addEventListener("touchstart", function(e) {
  clearInterval(timer); //清除定时器
  startX = e.touches[0].clientX; //记录起始X
});

imageBox.addEventListener("touchmove", function(e) {
  moveX = e.touches[0].clientX; //滑动时候的X
  distanceX = moveX - startX; //计算移动的距离
  //计算当前定位  -index*width+distanceX
  removeTransition(); //清除过渡
  setTranslateX(-index * width + distanceX / 100); //实时的定位
  isMove = true; //证明滑动过
});

//在模拟器上模拟的滑动会有问题 丢失的情况  最后在模拟器的时候用window
imageBox.addEventListener("touchend", function(e) {
  // 滑动超过 1/3 即为滑动有效,否则即为无效,则吸附回去
  if (isMove && Math.abs(distanceX) > width / 3) {
    //5.当滑动超过了一定的距离  需要 跳到 下一张或者上一张  (滑动的方向)*/
    if (distanceX > 0) {
      //上一张
      index--;
    } else {
      //下一张
      index++;
    }
  }
  addTransition(); //加过渡动画
  setTranslateX(-index * width); //定位

  if (index > imageCount) {
    index = 1;
  } else if (index <= 0) {
    index = imageCount;
  }
  setPoint();

  //重置参数
  startX = 0;
  moveX = 0;
  distanceX = 0;
  isMove = false;
  //加定时器
  clearInterval(timer); //严谨 再清除一次定时器
  timer = setInterval(function() {
    index++; //自动轮播到下一张
    addTransition(); //加过渡动画
    setTranslateX(-index * width); //定位
  }, 3000);
});

由以上代码可以实现一个轮播图效果。

全部代码

HTML

<div class="banner">
    <ul class="clearfix">
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner2.png"></a></li>
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner1.png"></a></li>
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner2.png"></a></li>
        <li><a href="#"><img
                    src="./assets/images/loginPage/banner1.png"></a></li>
    </ul>
    <ul>
        <li class="now"></li>
        <li></li>
    </ul>
</div>

JS

/*
 * 1.自动轮播  定时器  无缝衔接  动画结束瞬间定位
 * 2.点需要随着轮播的滚动改变对应的点  改变当前样式  当前图片的索引
 * 3.手指滑动的时候让轮播图滑动   touch事件  记录坐标轴的改变 改变轮播图的定位(位移css3)
 * 4.当滑动的距离不超过一定的距离的时候  需要吸附回去  过渡的形式去做
 * 5.当滑动超过了一定的距离  需要 跳到 下一张或者上一张  (滑动的方向) 一定的距离(屏幕的三分之一)
 * */

/*定义的一个命名空间*/
window.my = {};
/*封装一个事件 过渡结束事件*/
my.transitionEnd = function(dom,callback){
    //1.给谁加事件
    //2.事件触发后处理什么业务
    if(!dom || typeof dom != 'object'){
        //没dom的时候或者不是一个对象的时候 程序停止
        return false;
    }
    // 非webkit内核
    dom.addEventListener('transitionEnd', function(){
        callback && callback();
    });
    // webkit内核
    dom.addEventListener('webkitTransitionEnd', function(){
        callback && callback();
    });
}
var imageCount = 2; //页面中用来轮播的图片有2张不同的
//轮播图大盒子
var banner = document.querySelector(".banner");
//图片的宽度
var width = 7.5;
//图片盒子
var imageBox = banner.querySelector("ul:first-child");
//点盒子
var pointBox = banner.querySelector("ul:last-child");
//所有的点
var points = pointBox.querySelectorAll("li");
//公用方法
//加过渡
var addTransition = function() {
  imageBox.style.transition = "all 0.3s";
  imageBox.style.webkitTransition = "all 0.3s"; /*做兼容*/
};
//清除过渡
var removeTransition = function() {
  imageBox.style.transition = "none";
  imageBox.style.webkitTransition = "none";
};
//定位
var setTranslateX = function(translateX) {
  imageBox.style.transform = "translateX(" + translateX + "rem)";
  imageBox.style.webkitTransform = "translateX(" + translateX + "rem)";
};

//功能实现
//自动轮播  定时器  无缝衔接  动画结束瞬间定位
var index = 1;
var timer = setInterval(function() {
  index++; //自动轮播到下一张
  //改变定位  动画的形式去改变  transition transform translate
  addTransition(); //加过渡动画
  setTranslateX(-index * width); //定位
}, 3000);

//等过渡结束之后来做无缝衔接
my.transitionEnd(imageBox, function() {
  //处理事件结束后的业务逻辑
  if (index > imageCount) {
    index = 1;
  } else if (index <= 0) {
    index = imageCount;
  }
  removeTransition(); //清除过渡
  setTranslateX(-index * width); //定位
  setPoint(); //设置底部显示当前图片对应的圆角
});

//改变当前样式  当前图片的索引
var setPoint = function() {
  //清除上一次的now
  for (var i = 0; i < points.length; i++) {
    points[i].className = " ";
  }
  //给图片对应的点加上样式
  points[index - 1].className = "now";
};

/*
  手指滑动的时候让轮播图滑动   touch事件  记录坐标轴的改变 改变轮播图的定位(位移css3)
  当滑动的距离不超过一定的距离的时候  需要吸附回去  过渡的形式去做
  当滑动超过了一定的距离  需要 跳到 下一张或者上一张  (滑动的方向) 一定的距离(屏幕的三分之一)
  */
//touch事件
var startX = 0; //记录起始  刚刚触摸的点的位置 x的坐标
var moveX = 0; //滑动的时候x的位置
var distanceX = 0; //滑动的距离
var isMove = false; //是否滑动过

imageBox.addEventListener("touchstart", function(e) {
  clearInterval(timer); //清除定时器
  startX = e.touches[0].clientX; //记录起始X
});

imageBox.addEventListener("touchmove", function(e) {
  moveX = e.touches[0].clientX; //滑动时候的X
  distanceX = moveX - startX; //计算移动的距离
  //计算当前定位  -index*width+distanceX
  removeTransition(); //清除过渡
  setTranslateX(-index * width + distanceX / 100); //实时的定位
  isMove = true; //证明滑动过
});

//在模拟器上模拟的滑动会有问题 丢失的情况  最后在模拟器的时候用window
imageBox.addEventListener("touchend", function(e) {
  // 滑动超过 1/3 即为滑动有效,否则即为无效,则吸附回去
  if (isMove && Math.abs(distanceX) > width / 3) {
    //5.当滑动超过了一定的距离  需要 跳到 下一张或者上一张  (滑动的方向)*/
    if (distanceX > 0) {
      //上一张
      index--;
    } else {
      //下一张
      index++;
    }
  }
  addTransition(); //加过渡动画
  setTranslateX(-index * width); //定位

  if (index > imageCount) {
    index = 1;
  } else if (index <= 0) {
    index = imageCount;
  }
  setPoint();

  //重置参数
  startX = 0;
  moveX = 0;
  distanceX = 0;
  isMove = false;
  //加定时器
  clearInterval(timer); //严谨 再清除一次定时器
  timer = setInterval(function() {
    index++; //自动轮播到下一张
    addTransition(); //加过渡动画
    setTranslateX(-index * width); //定位
  }, 3000);
});

CSS

*,
::before,
::after{
    padding: 0;
    margin: 0;
    -webkit-box-sizing: border-box;/*兼容移动端主流浏览器*/
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;/*清除移动端点击高亮效果*/
}
body{
    font-family:Microsoft YaHei,sans-serif;/*移动端默认的字体*/
    font-size: 14px;
    color: #333;
}
ol,ul{
    list-style: none;
}
/*清除浮动*/
.clearfix::before,
.clearfix::after{
    content: "";
    display: block;
    height: 0;
    line-height: 0;
    visibility: hidden;
    clear: both;
}

.banner{
    width: 7.5rem;
    overflow: hidden;
    position: relative;
}
.banner ul:first-child{
    width: 1000%;
    -webkit-transform: translateX(-10%);
    transform: translateX(-10%);
}
.banner ul:first-child li{
    width: 10%;
    float: left;
}
.banner ul:first-child li a{
    display: block;
    width: 7.5rem;
}
.banner ul:first-child li a img{
    width: 7.5rem;
    display: block;
}
.banner ul:last-child{
    position: absolute;
    bottom: 6px;
    width: 100%;
    text-align: center;
}
.banner ul:last-child li{
    width: 6px;
    height: 6px;
    border: 1px solid #fff;
    border-radius: 0.02rem;
    width: 0.24rem;
    height: 0.04rem;
    display: inline-block;
    margin-left: 10px;
}
.banner ul:last-child li:first-child{
    margin-left: 0;
}
.banner ul:last-child li.now{
    background: #fff;
}

原文地址:https://www.cnblogs.com/Jacob98/p/11491442.html

时间: 2024-10-12 19:19:07

告别组件之教你使用原生js和css写移动端轮播图的相关文章

js原生选项(自动播放无缝滚动轮播图)二

今天分享一下自动播放轮播图,自动播放轮播图是在昨天分享的轮播图的基础上添加了定时器,用定时器控制图片的自动切换,函数中首先封装一个方向的自动播放工能的小函数,这个函数中添加定时器,定时器中可以放向右走的代码,也可以放向左走的代码,然后在js加载的时候先执行一次,保证页面加载的时候轮播图是自动播放的,当然在鼠标悬停在遮罩层的时候我们需要清除这个定时器,让自动播放功能关闭,然后在鼠标再次移出遮罩层的时候再次开启定时器,这样就实现了自动播放的功能.然后今天的轮播图中我添加了开关的功能,这个开关是为了避

js实现可配置参数的轮播图

一个轮播图做了一天多,期间各种小错误层出不穷,为自己的功力感到压力好大,却也在这艰难挣扎中体会了不少知识点,更加求知若渴. get到的点:js来添加.修改.去除css样式  对setTimeout 或setInterval 函数队列里事件的清除 1 var show = document.getElementById("show"); 2 var pic = show.getElementsByTagName('img'); 3 var timer; 4 var start_index

未学习JS也可以通过bootstrap做出轮播图的实际应用

由于本人新手 还没学JS 我是用bootstrap来做的 很简单 直接把那坨代码复制到 webstorm里面 下面我会用我的某一次作业 来做实际解释里面的某部分各代表什么意思 (由于这个代码到底什么意思 老师没有教过 我自行理解 有错的地方 望海涵)“男友秋装上新”这个地方 就是个轮播 一共3个小点 也就是三张图 可通过左右的箭头 左右翻动 接下来 奉上源代码:并在代码后给各部分做出解释 <div class="col-md-9 lunbo"> <div id=&qu

原生js和css写虚拟键盘

代码来源忘记是哪个大神的了,抱歉抱歉 放上源码: <!-- 虚拟键盘 --> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>虚拟键盘</title> <style> #inputArea{position: absolute; top: 30%; left: 20%;} .keyboardBox{position:

原生js三种选项卡效果(轮播)

第三种:定时轮播切换(我这边定时是2s) <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>选项卡-自动播放效果</title> <style type="text/css"> *{ margin: 0; padding: 0; list-style: none; } body{ background: #58

每天一个JS 小demo之韩雪冬轮播图。主要知识点:html,css布局,对于数组和对象的理解和运用

1 @charset "utf-8"; 2 /* CSS Document */ 3 4 * { padding: 0; margin: 0; } 5 li { list-style: none; } 6 img { border: none; } 7 body { background: #ececec; padding-top: 50px; } 8 9 #automatic { width: 970px; height: 344px; position: relative; mar

用 js封装以左右滑动的轮播图,调用任意

<!DOCTYPE html><html><head> <meta charset="utf-8"> <title></title> <style> .tab{ width: 500px; height: 300px; margin: 0 auto; background: yellow; position: relative; overflow: hidden; } *{ margin: 0; pad

JS纯生实现无缝滚动轮播图

1.定时器加上以后需要进入一次才能引用,所以在上面提前调用一次定时器: 2.当在实现下标小按钮的时候一定要给第三部的num赋值: 3.切记谁做动画谁加定位

js写的简单轮播图

这个轮播图代码是从网上找来的,专门找了个写法简单的,只是作为一个小练习,大概原理如下: 1.首先是图片切换2.自动播放3.调用自动播放4.移动到容器上边停止播放,离开自动播放5.移动到导航上停止播放,离开自动播放6.移动到导航上,切换相对应的导航 然后贴代码: <!doctype html><html lang="en"><head> <meta charset="UTF-8"> <title>Docume