下面的代码用纯js封装一个轮播组件。功能如下:

可上滑、下滑、左滑、右滑。无缝轮播。

移动端支持手势滑动。

可指定第一个显示的轮播图。

支持放置文字、图片和视频。带导航器。

导航器可自定义样式。若不想自定义样式,系统自带一个样式。

自适应元素大小。图片大小尺寸不限。

如果轮播图只有一张,或者不是轮播而只是一张图片,也处理其样式使其适应窗口。

自动处理了超高图和超宽图,以适应轮播区域。

这个功能大都用在首页顶部,或者商品详情。你甚至不需要写其它代码,通过这个组件你就能正确处理商品详情页顶部轮播或图片的样式问题。一句话调用即可!

用户不需要写额外代码,仅提供要轮播的html元素,以及一句话调用即可实现如上功能。

2022-3-11更新:

增加height参数,用来指定轮播的高度。height可以取数字,也可以带单位px。例如:200 或 '200px' 均可。

修复只有2张轮播图时左右滚动的问题。

先上个效果图:

系统默认的导航器样式也不难看。所以您可以省一段导航器样式的代码了

封装实现:

function wm_Carousel(param) {this.id = param.id;this.container = document.getElementById(this.id);if (this.container == null) {console.warn("container not found");return false;}this.filter = param.filter;this.container_box = this.container.querySelector(this.filter);if (this.container_box == null) {console.warn("container_box not found");return false;}if (typeof param.height == 'undefined') {this.height = window.innerWidth;} else {var reg = /^\d+$/;if (reg.test(param.height) != false) {this.height = param.height;} else {this.height = param.height.replace(/px/ig, "");}}this.container_box.style.backgroundColor = '#f2f2f2';this.interval = (param.interval < 1000 && param.interval > 0) ? param.interval * 1000 : (param.interval == 0 ? 1500 : param.interval);this.item_el = param.item_element;this.child = this.container_box.querySelectorAll(this.item_el);
//下面的if语句意思是,如果轮播图只有一个,或者没有轮播图,只有一个封面,
//那么我们可以不认为它是一个轮播,只当作是一个图片。
//这些代码就让这个图片也自适应窗口。
//那么,即使不是轮播,只是一张图片,也可以使用本系统渲染。
//只不过在一句话调用的时候,只实例化对象,不要调用create()方法。
//如果你不想让系统处理这种情况,把下面的if语句删除即可。if (this.child.length == 1) {this.container_box.style.height = this.height + 'px';this.child[0].style.height = this.height + 'px';this.child[0].style.display = 'flex';this.child[0].style.alignItems = 'center';this.child[0].style.justifyContent = 'center';var img = this.container_box.querySelectorAll('img');for (var i = 0; i < img.length; i++) {img[i].style.maxHeight = '100%';img[i].style.maxWidth = '100%';}var video = this.container_box.querySelectorAll('video');for (var i = 0; i < video.length; i++) {video[i].style.maxHeight = '100%';video[i].style.maxWidth = '100%';}return;}this.index = (typeof param.index == 'undefined' || param.index == '') ? 0 : param.index - 1;if(this.index > this.child.length){this.index = 0;}if(this.child.length == 0){console.warn("carousel item not found");return false;}this.child_length = this.child.length;this.direction = typeof param.direction != 'undefined' ? param.direction : 'left';["up", "down", "left", "right"].indexOf(this.direction) == -1 ? this.direction = "left" : '';this.item_width = 0;this.item_height = 0;this.duration = param.duration ? param.duration : '0.7s';this.navigator_class = param.navigator_class;this.touch_source = {};
}
wm_Carousel.prototype = {create: function () {if (this.container == null) {console.warn("container is null");return false;}if (this.container_box == null) {console.warn("container_box is null");return false;}if (this.child_length == 0) {console.warn("carousel item is empty");return false;}this.container.style.overflow = 'hidden';this.container.style.position = "relative";this.container.style.height = this.height + 'px';this.container_box.style.position = "absolute";if (this.direction == "left" || this.direction == "right") {this.container_box.style.width = ((this.child_length + 2) * this.container.offsetWidth) + 'px';this.container_box.style.height = "100%";} else {this.container_box.style.height = ((this.child_length + 2) * this.container.offsetHeight) + 'px';this.container_box.style.width = "100%";}this.navigator_element = document.createElement("div");if (this.navigator_class == null || this.navigator_class == '' || typeof this.navigator_class == 'undefined') {this.navigator_element.style.position = "absolute";this.navigator_element.style.bottom = "20px";this.navigator_element.style.backgroundColor = "rgba(0,0,0,0.2)";this.navigator_element.style.padding = "5px";this.navigator_element.style.display = "flex";this.navigator_element.style.justifyContent = "space-between";this.navigator_element.style.left = "50%";this.navigator_element.style.transform = "translate(-50%,0)";this.navigator_element.style.borderRadius = "10px";} else {this.navigator_element.className = this.navigator_class;}this.container.appendChild(this.navigator_element);var img = this.container_box.querySelectorAll('img');for (var i = 0; i < img.length; i++) {img[i].style.maxHeight = '100%';img[i].style.maxWidth = '100%';}var video = this.container_box.querySelectorAll('video');for (var i = 0; i < video.length; i++) {video[i].style.maxHeight = '100%';video[i].style.maxWidth = '100%';}for (i = 0; i < this.child_length; i++){this.child[i].style.width = this.container.offsetWidth + 'px'this.child[i].style.height = this.container.offsetHeight + 'px';this.child[i].style.display = 'flex';this.child[i].style.alignItems = 'center';this.child[i].style.justifyContent = 'center';if (this.direction == "left" || this.direction == "right") {this.child[i].style.float = "left";}if (this.navigator_class == null || this.navigator_class == '' || typeof this.navigator_class == 'undefined') {this.navigator_element.innerHTML += "<div style='margin: 0 3px;width: 10px;height: 10px;border-radius: 50%;background: rgba(255,255,255,0.5);"+ (i == 0 ? "background:rgba(255,255,255,1)" : "background:rgba(255,255,255,0.5)") +";' data-index='" + i + "'></div>";} else {this.navigator_element.innerHTML += "<div class='wm_carousel_navigator_item" + (i == 0 ? " current" : "") + "' data-index='" + i + "'></div>";}}this.item_width = this.child[0].offsetWidth;this.item_height = this.child[0].offsetHeight;var first = this.child[this.child_length - 1].cloneNode(true);var last = this.child[0].cloneNode(true)this.container_box.appendChild(last)this.container_box.insertBefore(first, this.child[0]);this.index += 1;if (this.direction == "left" || this.direction == "right") {this.container_box.style.left = -this.item_width * (this.index) + 'px';} else {this.container_box.style.top = -this.item_height *  (this.index) + 'px';}this.navigator(this.index - 1)this.index -= 1;var that = this;this.container_box.addEventListener('touchstart', function (e) {that.touch_source['x'] = e.changedTouches[0].clientX;that.touch_source['y'] = e.changedTouches[0].clientY;})this.container_box.addEventListener('touchend', function (e) {var x = e.changedTouches[0].clientX;var y = e.changedTouches[0].clientY;if (that.direction == "left" || that.direction == "right") {var distance = x - that.touch_source.x;if(Math.abs(distance) > 50){that.calcIndex(distance > 0 ? 'right' : 'left');}} else {var distance = y - that.touch_source.y;if(Math.abs(distance) > 50){that.calcIndex(distance > 0 ? 'down' : 'up');}}})this.startInterval();},startInterval: function () {var that = this;setInterval(function () {that.calcIndex(that.direction);}, that.interval);},calcIndex: function (direction) {var nextIndex = 0;if(this.child_length == 1){return;}if(direction == 'left' || direction == 'up'){if (this.index < this.child_length){nextIndex = this.index + 1;} else {nextIndex = 1;}} else if(direction == 'right' || direction == 'down'){if (this.index > -1){nextIndex = this.index - 1;} else {nextIndex = this.child_length - 2;}}this.carousel(direction, nextIndex);this.navigator(nextIndex);},carousel: function (direction, nextIndex) {this.container_box.style.transitionDuration = "";var target;console.log("this.index=" + this.index + ",nextIndex=" + nextIndex)if(direction == 'left' || direction == 'up'){if (Math.abs(this.index - nextIndex) == 1) {if (this.index - nextIndex == 1) {this.container_box.style.transitionDuration = '0s';if(direction == 'left'){this.container_box.style.left = -this.item_width + 'px';target = this.container_box.offsetLeft;target = -this.item_width * 2;this.container_box.style.transitionDuration = this.duration;this.container_box.style.left = target + 'px';} else {this.container_box.style.top = -this.item_height + 'px';target = this.container_box.offsetTop;target = -this.item_height * 2;this.container_box.style.transitionDuration = this.duration;this.container_box.style.top = target + 'px';}} else {if (direction == 'left') {target = -this.item_width * (nextIndex + 1);} else {target = -this.item_height * (nextIndex + 1);}}this.container_box.style.transitionDuration = this.duration;if(direction == 'left'){this.container_box.style.left = target + 'px';} else {this.container_box.style.top = target + 'px';}} else {this.container_box.style.transitionDuration = '0s';if(direction == 'left'){this.container_box.style.left = -this.item_width + 'px';target = this.container_box.offsetLeft;target = -this.item_width * 2;this.container_box.style.transitionDuration = this.duration;this.container_box.style.left = target + 'px';} else {this.container_box.style.top = -this.item_height + 'px';target = this.container_box.offsetTop;target = -this.item_height * 2;this.container_box.style.transitionDuration = this.duration;this.container_box.style.top = target + 'px';}}} else if(direction == 'right' || direction == 'down'){if (Math.abs(this.index - nextIndex) == 1) {if (this.index - nextIndex == 1) {if(direction == 'right'){target = -this.item_width * (nextIndex + 1);} else {target = -this.item_height * (nextIndex + 1);}this.container_box.style.transitionDuration = this.duration;if(direction == 'right'){this.container_box.style.left = target + 'px';} else {this.container_box.style.top = target + 'px';}    } else {this.container_box.style.transitionDuration = '0s';if(direction == 'right'){this.container_box.style.left = -this.item_width * this.child_length + 'px';target = this.container_box.offsetLeft;target = -this.item_width;this.container_box.style.transitionDuration = this.duration;this.container_box.style.left = target + 'px';} else {this.container_box.style.top = -this.item_height * this.child_length + 'px';target = this.container_box.offsetTop;target = -this.item_height;this.container_box.style.transitionDuration = this.duration;this.container_box.style.top = target + 'px';}}} else {this.container_box.style.transitionDuration = '0s';if(direction == 'right'){this.container_box.style.left = -this.item_width * (this.child_length) + 'px';target = this.container_box.offsetLeft;target = -this.item_width * (this.child_length - 1);this.container_box.style.transitionDuration = this.duration;this.container_box.style.left = target + 'px';} else {this.container_box.style.top = -this.item_height * (this.child_length) + 'px';target = this.container_box.offsetTop;target = -this.item_height * (this.child_length - 1);this.container_box.style.transitionDuration = this.duration;this.container_box.style.top = target + 'px';}}}this.index = nextIndex;},navigator: function (thisIndex) {var navigator_child = this.navigator_element.querySelectorAll("div");var navigator_class = this.navigator_class;var current = null;if (navigator_class == null || navigator_class == '' || typeof navigator_class == 'undefined') {for (i = 0; i < navigator_child.length; i++) {navigator_child[i].style.background = "rgba(255,255,255,0.5)";}} else {for (i = 0; i < navigator_child.length; i++) {navigator_child[i].classList.remove("current");}}if(thisIndex > 0 && thisIndex < this.child_length){current = navigator_child[thisIndex];} else if (thisIndex == -1) {current = navigator_child[navigator_child.length - 1]} else if (thisIndex == 0){current = navigator_child[0];} else if(thisIndex == this.child_length){current = navigator_child[0];}if (navigator_class == null || navigator_class == '' || typeof navigator_class == 'undefined') {current.style.background = "rgba(255,255,255,1)";} else {current.classList.add("current");}}
}

调用方法:

var carousel = new wm_Carousel({id:'carousel', filter: '.carousel_ul', item_element: 'li', direction:'left', interval: 2, duration:'0.7s', navigator_class:'navigator', index: 1});if(carousel.child_length > 1){carousel.create();
}/*
如果只有一张轮播图,或者不是轮播而只有一张图片,不要调用create()方法,这样就不会出现导航器了。
*//*参数说明
id:外层容器。必须的
filter:要滚动的元素。必须的。
item_element: 要滚动的元素的子元素的类型,必须的。比如 div li。这个要根据具体是什么来设置
direction:滚动方向,可以不设置,默认为left。只有4个选项:up、down、left、right。即上下左右
interval:多少秒滚动一次。可以不设置。默认1.5秒。单位嘛凭你感觉来设置即可。比如你觉得是秒,那可以设置为3,你要是觉得是毫秒,那可以设置为3000
duration:缓动时长。也就是多长时间滚动就位。可以不设置,默认为0.7秒。
navigator_class 导航器样式类名。可以不设置,系统自带一个。如果这一项设置了值,就需要写针对导航器的样式。具体写法请参见下面的测试代码。
index:第一个界面显示哪一个条目。可以不设置。默认为第一个。若要设置,第一个为1,第二个为2。以此类推。
height:轮播的高度。单位为px。但是可以不写单位。例如: 200 或 '200px'
*/

测试代码如下(把上面封装的代码保存到js文件里。我这里取名为c.js):

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><script src="c.js" type="text/javascript" charset="utf-8"></script><title></title><style>*{margin: 0; padding: 0;}ul li{color:white; list-style: none;}/*以下代码是自定义导航器样式用的。可以不写。如果不写,在调用的时候,不要指定导航器样式类名*/.navigator{position: absolute;bottom: 10px;background-color: rgba(0, 0, 0, 0.2);padding: 5px;display: flex;justify-content: space-between;left: 50%;transform: translate(-50%, 0px);border-radius: 10px;}.navigator .wm_carousel_navigator_item{margin: 0 2px;width: 10px;height: 10px;border-radius: 50%;background: rgba(255,255,255,0.5);}.navigator .current{background: rgba(255,255,255,1);}</style>
</head>
<body>
<!--不要对下面的div、ul设置高度宽度。以便让系统可以正确适应各种尺寸的图片--><div id="carousel"><ul class="carousel_ul"><li style="background-color: #f00;"><img src="1.jpg" alt=""></li><li style="background-color:blueviolet;"><img src="2.png" alt=""></li><li style="background-color:aqua;"><video src="4.mp4" controls="controls"></video></li><li style="background-color:#ff00ff;">5555555555</li><li style="background-color:#ffaa7f;">66666666666</li></ul></div><script>var carousel = new wm_Carousel({id:'carousel', filter: '.carousel_ul', item_element: 'li', direction:'left', interval: 2, duration:'0.7s', navigator_class:'', index: 1}).create();</script>
</body>
</html>
<!--background-color 这个可以不设置。我加上主要是为了好测试。直接写<li>xxxx</li>即可。
头部的 style 部分也可以不写,navigator 类是自定义导航器样式用的。
-->

注意调用代码:

var carousel = new wm_Carousel({id:'carousel', filter: '.carousel_ul', item_element: 'li', direction:'left', interval: 2, duration:'0.7s', navigator_class:'', index: 1}).create();

里面的 navigator_class,如果你不想自定义导航器样式,这里不要赋值,也可以直接不写这个配置。如果想自定义样式,样式类名请和style里写的一样(navigator 这个类名可以随便取名,wm_carousel_navigator_item和current必须这样写,不能取别的名字)。并且在这里指定类名。即:

var carousel = new wm_Carousel({id:'carousel', filter: '.carousel_ul', item_element: 'li', direction:'left', interval: 2, duration:'0.7s', navigator_class:'这里写导航器样式类名', index: 1}).create();

上面这是一种方法,还有另外一种方法,就是不滚动ul,而是每次取需要参与滚动的2个条目,只滚动这两个。有兴趣的可以自己写写。

当然,也可以用canvas来写轮播。用canvas的效率是最高的。

我在项目中是这样使用的:

<div id="carousel"><ul class="carousel_ul" v-if="sliders.length>0"><li v-for="sl in sliders"><img :src="sl" /></li></ul><ul class="carousel_ul" v-else><li class="goods_detail_img"><img :src="upload_dir + coverimage"></li></ul></div>

上面是vue的html部分。

if(data.result.slider_image != null && data.result.slider_image != ''){thisdata.sliders = data.result.slider_image;setTimeout(function () {var carousel = new Carousel({id: 'carousel', filter: '.carousel_ul', item_element: 'li', direction: 'left', interval: 2, duration: '0.7s', navigator_class: '', index:2});if(carousel.child_length > 1){carousel.create();}}, 0)} else {thisdata.sliders = [];thisdata.coverimage = data.result.coverimage;new Carousel({id: 'carousel', filter: '.carousel_ul', item_element: 'li'});}

上面是获取轮播数据后的处理。

如有问题,请在评论中指出,谢谢。

csdn博客原创首发,转载需要注明出处。

纯js封装一个无缝轮播相关推荐

  1. vue如何使用原生js写动画效果_原生js写一个无缝轮播图插件(支持vue)

    轮播图插件(Broadcast.js) 前言:写这个插件的原因 前段时间准备用vue加上网易云的nodejs接口,模拟网易云音乐移动端.因为想自己写一遍所有的代码以及加固自己的flex布局,所以没有使 ...

  2. html怎么引轮播图插件,原生js写一个无缝轮播图插件(支持vue)

    轮播图插件(Broadcast.js) 前言:写这个插件的原因 前段时间准备用vue加上网易云的nodejs接口,模拟网易云音乐移动端.因为想自己写一遍所有的代码以及加固自己的flex布局,所以没有使 ...

  3. 左右无缝轮播html,JS实现左右无缝轮播图代码

    废话不多说了,直接给大家贴代码了. 无缝轮播图: 无缝轮播图 *{margin: 0;padding:0; } ul{list-style: none;} .banner{width: 600px;h ...

  4. 纯js封装一个多功能弹出框

    不借助其它的css代码和图片资源,可直接调用. 原创内容,请勿转载. 注意,不要直接复制文章里的封装代码,因为编辑器的原因,无论怎么编辑,它还是给修改了代码.文末提供了封装代码的下载地址(无需积分) ...

  5. js实现左右无缝轮播图

    今天让我们再来做一个左右无缝的轮播图吧! 一.准备html代码 html代码也叫结构 <!DOCTYPE html> <html lang="zh-CN"> ...

  6. 前端全栈大佬是如何使用javaScript实现一个无缝轮播优化

    效果图: 代码如下: <!DOCTYPE html> <html> <head lang="en"><meta charset=" ...

  7. 前端全栈大佬是如何使用javaScript实现一个无缝轮播

    效果图: 代码如下: <!DOCTYPE html> <html> <head lang="en"><meta charset=" ...

  8. 前端全栈大佬是如何使用javaScript实现一个无缝轮播(最终版)

    效果图: 代码如下: <!DOCTYPE html> <html> <head lang="en"><meta charset=" ...

  9. 原生纯js完美缓冲运动轮播图

    预览图 -..兄弟们相信我绝对效果很好, gif图片太大了传不上来-, 第一次录是22M,第二次录是44M, -..激动的我说不出话来-.谁有好用的gif软件推荐推荐. 讲解以及介绍写在代码的注释中了 ...

最新文章

  1. OpenCV学习中遇到的小问题—关于图像赋值
  2. 剖析 Linux hypervisor
  3. KANO模型分析与使用
  4. ROS入门笔记(五):ROS中运行rqt_plot的问题(kinetic)
  5. 1. 初识 Lucene
  6. 用PHP做服务器接口客户端用http协议POST访问安全性一般怎么做
  7. MySQL安装包下载地址(含所有版本)
  8. 遗传算法工具箱约束优化例题
  9. 网络抓包工具之Wireshark
  10. MySQL数据备份与IDE工具介绍
  11. 商空间的理解(Quotient space)
  12. cortex a7 a53_镜头测试:蔡司红T28/2.8+索尼微单A7实拍北京景山公园
  13. 如何提升电脑开机速度?
  14. 爱快固件是Linux系统吗,爱快硬路由和软路由系统有什么区别
  15. python通过Tkinter库实现的一个简单的文本编辑器源码
  16. 向 Oracle 数据库添加 ST_Geometry 类型
  17. WINPE WIN10 测试i9-9900k+2080TI\i9-9980XE+P5000\i7-8086k+titanX\E5-2678+128G跑分
  18. 大师们的投资之道(十三)
  19. 华为开发者联盟 -- 测试中心
  20. 【ACMMM 2022】Learning Hierarchical Dynamics with Spatial Adjacency for Image Enhancement

热门文章

  1. 鞋企批量鞋子发霉翻箱除霉方法(不再霉变)
  2. 先根遍历二叉树c语言程序,二叉树先序遍历C语言实现
  3. scrapy爬虫演示---爬取中国新闻网
  4. php抽象工厂模式开发,php抽象工厂模式开发思路
  5. salesforceの各種エディションと料金と機能
  6. 数学基础(五)最优化理论(最优化,无约束,有约束,拉格朗日乘子的意义,KKT条件)
  7. 自己制作的视频,如何转换成二维码?
  8. android手机背景变黑怎么办,Android png透明图片转jpg时背景变黑的解决方法
  9. 短信查询与健康码实现精准防控,是否造成信息泄露?
  10. mysql 双机 热备,mysql双机热备 my