面向对象编程js原生实现轮播图效果

1.先看效果图

2.需要实现的功能:

  • 自动轮播
  • 点击左右箭头按钮无缝轮播
  • 点击数字按钮切换图片

分析:如何实现无缝轮播?

在一个固定大小的相框里有一个ul标签,其长度是几个图片宽度的总和,通过translateX()的方法来实现左右移动动画。

如何实现无缝呢?比如有三张图片,可以在把第一张图片通过cloneNode的方法克隆下来放到第三张图片后面。图片顺序 1,2,3,1,看下面的HTML结构,结构中并没有4张图,第四张图是生成的。

3.html结构

<!-- ul是图片盒子,ol是数字按钮盒子,最下面的div是左右箭头按钮盒子 -->
<div class="container">
<div id="screen">
<ul>
<li><img src="./img/1.jpg" alt=""></li>
<li><img src="./img/2.jpg" alt=""></li>
<li><img src="./img/3.jpg" alt=""></li>
</ul>
<ol>
<!--<li class="active">1</li>-->
<!--<li>2</li>-->
<!--<li>3</li>-->
</ol>
</div>
<div>
<span>&lt;</span>
<span>&gt;</span>
</div>
</div>

4.功能实现

4.1 创建对象

创建一个对象,需要传入一个相框盒子元素,通过这个元素来获取盒子中其他需要的元素,并把这些作为这个Carousel对象的属性:

function Carousel(el) {
this.screen = el; // 相框
this.width = this.screen.offsetWidth; // 相框宽度
this.ulBox = this.screen.children[0]; // ul盒子
this.list = this.ulBox.children; // ul下面所有li
this.olBox = this.screen.children[1]; // 数字按钮盒子
this.arrow = this.screen.nextElementSibling; // 箭头盒子
this.leftArraw = this.arrow.children[0]; // 左箭头
this.rightArraw = this.arrow.children[1]; // 右箭头
this.index = 0; // 数字按钮的索引
this.timeId = null; // 定时器的id
this.activeClass = 'active'; // 数字按钮class名
this.durtion = '.35s'; // 动画持续时间
}

4.2动画效果由translateX实现

// 动画
Carousel.prototype.animate = function (target) {
this.ulBox.style.transform = 'translateX(' + target + 'px)'
};

4.3根据轮播图片个数生成数字按钮节点

生成节点后,为新生成的节点添加点击事件,实现每次点击根据节点对应的index切换图片,这里实现的需求的第三个功能。

// 创建节点
Carousel.prototype.createNodes = function () {
let self = this;
// 创建按钮节点
for (let i = 0; i < self.list.length; i++) {
let liObj = document.createElement('li');
liObj.innerText = i + 1;
self.olBox.appendChild(liObj); // 为生成的数字按钮添加点击事件
liObj.onclick = function () {
self.index = this.innerText - 1; // 获取当前点击对象的索引值
self.switch_sel();
self.animate(-self.index * self.width);
};
}
// 默认显示第一张图片,第一个数字按钮默认选中状态
self.olBox.children[0].className = self.activeClass;
// 克隆第一张图放到ulBox后面,实现无缝轮播
self.ulBox.appendChild(self.ulBox.children[0].cloneNode(true));
};

4.4轮播图数字按钮点击切换状态

因为多次用到这段代码,所有就写成一个方法挂在Carousel对象上了

// 切换数字按钮的选中状态
Carousel.prototype.switch_sel = function(){
let self = this;
for (let i = 0; i < self.olBox.children.length; i++) {
self.olBox.children[i].removeAttribute('class');
}
self.olBox.children[self.index].className = self.activeClass;
};

4.5轮播事件,也是点击右箭头的事件

// 轮播事件
Carousel.prototype.clickHandle = function () {
let self = this;
// 如果是最后一张图,直接跳到第一张
if (self.index === self.list.length - 1) {
self.index = 0; // 当点击到最后一张时直接跳到第一张
self.ulBox.style.transitionDuration = '0s';
self.animate(-self.index * self.width);
} // 必须有时间延迟,否则图片跳转切换不成功,因为self.animate()没有来得及执行就被后面的self.animate()函数覆盖了。
setTimeout(function () {
self.ulBox.style.transitionDuration = self.durtion;
self.index++;
self.animate(-self.index * self.width); // 如果是最后一张图,则去掉最后一个的class属性,切换到第一个
if (self.index === self.list.length - 1) {
self.olBox.children[self.olBox.children.length - 1].removeAttribute('class');
self.olBox.children[0].className = self.activeClass;
} else { // 切换当前选中状态
self.switch_sel();
}
}, 20);
};

4.6事件绑定

为左右箭头点击绑定事件,同时当鼠标hover在相框上时自动轮播取消,鼠标离开相框时自动轮播开始执行。

// 事件绑定
Carousel.prototype.bindEvent = function () {
let self = this;
// 又点击下一张
self.rightArraw.onclick = function () {
self.clickHandle();
};
// 左点击上一张
self.leftArraw.onclick = function(){
if(self.index === 0){
self.index = self.list.length - 1; // 直接跳到最后一张
self.ulBox.style.transitionDuration = '0s';
self.animate(-self.index * self.width);
} setTimeout(function(){
self.ulBox.style.transitionDuration = self.durtion;
self.index--;
self.animate(-self.index * self.width);
self.switch_sel();
}, 20);
}; // 鼠标悬停清除定时器
self.screen.parentElement.onmouseover = function(){
self.timeId && clearInterval(self.timeId);
self.arrow.style.display = 'flex'; };
// 鼠标离开打开定时器
self.screen.parentElement.onmouseout = function(){
self.timeId = setInterval(self.clickHandle.bind(self), 2000);
self.arrow.style.display = 'none';
}
};

4.7初始化方法

初始化方法中创建节点,绑定事件,同时设定定时器实现自动轮播效果。

// 初始化
Carousel.prototype.init = function () {
this.createNodes();
this.bindEvent();
this.timeId = setInterval(this.clickHandle.bind(this), 2000);
// 注意这里要bind(this) 否则clickHandle中的this指向window
};

4.8实例化Carousel对象,大功告成

实例化一个轮播图对象,然后调该对象的init方法。

只要html结构相同,只需要传入不同的相框元素,就可以在同一个页面中实例化多个轮播图对象。也就是说,同一个页面的多处轮播效果。

let carousel = new Carousel(document.getElementById('screen'));
carousel.init();

5备注

全部的代码和css样式可参考我的github中的轮播图仓库,菜鸟程序猿一枚,程序设计如果有不妥的地方欢迎提出意见或建议,当然啦,如果你喜欢并star了我的这个仓库,我会很开心的 : )

[1]: https://github.com/jiangleiundo/carousel

js原生实现轮播图效果(面向对象编程)的更多相关文章

  1. JS学习笔记--轮播图效果

    希望通过自己的学习收获哪怕收获一点点,进步一点点都是值得的,加油吧!!! 本章知识点:index this for if else 下边我分享下通过老师教的方式写的轮播图,基础知识实现: 1.css代 ...

  2. jquery.flexslider-min.js实现banner轮播图效果

    实现方法 引用jQuery和flexslider.js到你的页面 <script type="text/javascript" src="js/jquery-1.7 ...

  3. js原生的轮播图

    <!DOCTYPE html>   <html>   <head>   <meta charset="UTF-8">   <t ...

  4. JS+css3焦点轮播图PC端

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 自己用原生JS写的轮播图,支持移动端触屏滑动,面向对象思路。分页器圆点支持click和mouseover。

    自己用原生javascript写的轮播图,面向对象思路,支持移动端手指触屏滑动.分页器圆点可以选择click点击或mouseover鼠标移入时触发.图片滚动用的setInterval,感觉setInt ...

  6. js实现轮播图效果(附源码)--原生js的应用

    1.js实现轮播图效果 <!DOCTYPE html><html lang="en"><head> <meta charset=" ...

  7. 原生JS实现简易轮播图

    原生JS实现简易轮播图(渐变?) 最近做网页总是会用到轮播图,我就把之前写的轮播图单独拿出来吧,如果有...如果真的有人也需要也可以复制去用用啊..哈~.. window.onload = funct ...

  8. js 实现淘宝无缝轮播图效果,可更改配置参数 带完整版解析代码[slider.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 需求分析: ...

  9. jQuery与原生js实现banner轮播图

    jQuery与原生js实现banner轮播图: (jq需自己加载)(图片需自己加载) <!DOCTYPE html> <html> <head> <meta ...

随机推荐

  1. JavaScript常用函数以及语法

    $("#dwid").val(checkedVal.join(',')); .字符串(String) trim() //去掉空格   1.声明      var myString ...

  2. beans.factory.BeanCreationException beans.factory.annotation.Autowired(required=true)

    主要是这三个方面排查: 1,注入写成这样 @Autowired   private BrandServiceImpl      brandServiceImpl; 2,jar冲突,在pom.xml中 ...

  3. 图解Skip List——本质是空间换时间的数据结构,在lucene的倒排列表,bigtable,hbase,cassandra的memtable,redis中sorted set中均用到

    Skip List的提出已有二十多年[Pugh, W. (1990)],却依旧应用广泛(Redis.LevelDB等).作为平衡树(AVL.红黑树.伸展树.树堆)的替代方案,虽然它性能不如平衡树稳定, ...

  4. Agc012_E Camel and Oases

    传送门 题目大意 坐标轴上有$n$个坐标,第$i$个坐标是$x_i$,初始你有一个容量$V$,当两个给定的坐标距离不超过$V$时,你可以从一个坐标到达另一个坐标,同时你还可以令$V=\lfloor \ ...

  5. Dockerfile创建MySQL容器

    本文目的是创建一个MySQL的image,并且在新创建出来的容器里自动启动mysql服务接受外部连接 步骤: 1. 首先创建一个目录并在目录下创建一个Dockerfile,文件内容如下 FROM ce ...

  6. 【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版

    目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖 ...

  7. MongoDB分析工具之二:MongoDB分析器Profile

    MongoDB优化器profile 在MySQL 中,慢查询日志是经常作为我们优化数据库的依据,那在MongoDB 中是否有类似的功能呢?答案是肯定的,那就是MongoDB Database Prof ...

  8. 【转】Ruby on Rails中select使用方法

    在Ruby on Rails中真的有一堆Select helper可以用,我们经常容易混淆.常见的有三个..select, select_tag, collection_select(其余的什么sel ...

  9. java中的equals方法

    这个方法首先比较的是两个对象的地址是否相同,如果相同直接返回true, 否则, (1)如果是string类型的先比较是否是string类型,是的话,再比较是否长度相同,相同的话再比较,每个字符是否相同 ...

  10. shell入门-shell特性

    1.关于! 命令:!! 说明: 执行上一条命令 [root@wangshaojun ~]# pwd/root[root@wangshaojun ~]# !!pwd/root 命令:!n (n表示数字) ...