原生JS实现"旋转木马"效果的图片轮播插件
一、写在最前面
最近都忙一些杂七杂八的事情,复习软考、研读经典...好像都好久没写过博客了。。。
我自己写过三个图片轮播,一个是简单的原生JS实现的,没有什么动画效果的,一个是结合JQuery实现的,淡入淡出切换的。现在想做一个酷一点的放在博客或者个人网站,到时候可以展示自己的作品。逛了一下慕课网,发现有个旋转木马的jquery插件课程,有点酷酷的,于是就想着用原生JS封装出来。做起来才发现,没有自己想象中的那么容易。。。不啰嗦了,讲解一下实现过程吧。
二、效果
由于自己的服务器还没弄好。在线演示不了(ORZ...)。。。只能放一张效果图了。。。

从图片上还是可以看出大概效果的,我就不多说了。想看真实代码效果的,欢迎到我的github上面download代码,别忘了给我的github项目点个星星噢^_^
三、实现过程
html结构
<div class="carrousel-main" data-setting='{"width":1000,"height":400,
"carrouselWidth":750,
"carrouselHeight":400,
"scale":0.9,
"verticalAlign":"middle"}'>
<div class="carrousel-btn carrousel-btn-pre"></div>
<ul class="carrousel-list">
<li class="carrousel-item">
<a href="#"><img src="img/1.jpg"></a>
</li>
<li class="carrousel-item">
<a href="#"><img src="img/2.jpg"></a>
</li>
<li class="carrousel-item">
<a href="#"><img src="img/3.jpg"></a>
</li>
<li class="carrousel-item">
<a href="#"><img src="img/4.jpg"></a>
</li>
<li class="carrousel-item">
<a href="#"><img src="img/5.jpg"></a>
</ul>
<div class="carrousel-btn carrousel-btn-next"></div>
</div>
这个结构和一般轮播的html代码结构是一样的,稍有不同就是,主轮播div上面有一个data-setting的属性,这个属性里面就是一些轮播效果的参数。参数的具体意义稍后再讲解。
css部分的代码就不贴了,最重要就是要注意元素的绝对定位,由效果图可以看出来,每张图片的位置、大小都不一样,所以这些都是通过js控制的,因此需要绝对定位。下面重点讲一下js实现过程。
JS实现过程
下面讲几个JS的关键步骤,做好了这几个步骤之后,应该就没有什么难点了。
①默认参数
既然是封装插件,那么肯定会有一些参数的默认值需要配置的啦。这个插件中,主要有如下参数:
width:1000, //幻灯片区域的宽度
height:400, //幻灯片区域的高度
carrouselWidth:700, //幻灯片第一帧的宽度
carrouselHeight:400, //幻灯片第一帧的高度
scale:0.9,//记录显示比例关系,例如第二张图比第一张图显示的时候宽高小多少
autoPlay:true,//是否自动播放
timeSpan:3000,//自动播放时间间隔
verticalAlign:'middle' //图片对齐方式,有top\middle\bottom三种方式,默认为middle
②封装对象
因为一个网站可能有多个地方都会用到同一个轮播插件,所以封装很关键。定义了这个对象之后,如果给对象定义一个初始化方法是可以创建多个对象的,只需要把所有类相同的dom传进去就可以了。所以,我的初始化方法如下:
Carousel.init=function(carrousels){
var _this=this;
//将nodeList转换为数组
var cals= toArray(carrousels);
/*因为原生JS获取所有的类,得到的是一个nodeList,是一个类数组,如果想要使用数组的方法则需要转化为真正的数组。这里toArray为转化方法。*/
cals.forEach(function(item,index,array){
new _this(item);
});
}
这样的话,我在window.onload的时候,调用Carrousel.init(document.querySelectorAll('.carrousel-main'));这样就可以创建多个轮播啦!
③初始化好第一帧的位置参数
因为,第一帧之后的所有帧的相关参数都是参照第一帧来定义的,因此,定义好第一帧很关键。
setValue:function(){
this.carrousel.style.width=this.Settings.width+'px';
this.carrousel.style.height=this.Settings.height+'px';
/*左右按钮设置,这里要让左右按钮平均地瓜分轮播区域宽减去第一帧宽度之后的区域,z-index要比除第一帧外所有图片都高,而图片刚好左右分放置,因此z-index的值就是图片数量的一半。*/
var btnW=(this.Settings.width-this.Settings.carrouselWidth)/2;
this.preBtn.style.width=btnW+'px';
this.preBtn.style.height=this.Settings.height+'px';
this.preBtn.style.zIndex=Math.ceil(this.carrouselItems.length/2);
this.nextBtn.style.width=btnW+'px';
this.nextBtn.style.height=this.Settings.height+'px';
this.nextBtn.style.zIndex=Math.ceil(this.carrouselItems.length/2);
//第一帧相关设置
this.carrouselFir.style.left=btnW+'px';
this.carrouselFir.style.top=this.setCarrouselAlign(this.Settings.carrouselHeight)+'px';
this.carrouselFir.style.width=this.Settings.carrouselWidth+'px';
this.carrouselFir.style.height=this.Settings.carrouselHeight+'px';
this.carrouselFir.style.zIndex=Math.floor(this.carrouselItems.length/2);
},
这里,就是new对象的时候,就到dom结点中获取data-setting参数,然后更新默认参数配置。这里有个地方需要注意的,获取dom的参数不能直接以赋值的方式更新默认参数,因为用户配置参数的时候,不一定会所有参数都配置一次。如果直接赋值而用户刚好不是所有参数都配置的话就会造成参数丢失。这里我是自己写了一个类似JQuery中的$.extend方法的对象扩展方法来更新参数的。具体就不列举了,感兴趣的可以去下载。
④其他图片位置设置
这里的图片实际上就是把除第一张之外的图片,平均地分到左右两则,而左边的图片位置和右边的是不同的,因此需要分别配置:
//设置右边图片的位置关系
var rightIndex=level;
rightSlice.forEach(function(item,index,array){
rightIndex--;
var i=index;
rw=rw*carrouselSelf.Settings.scale;//右边的图片是按照scale比例逐渐变小的
rh=rh*carrouselSelf.Settings.scale; item.style.zIndex=rightIndex;//越往右边z-index的值越小,可以用图片数量的一般逐渐递减
item.style.width=rw+'px';
item.style.height=rh+'px';
item.style.opacity=1/(++i);//越往右边透明度越小
//这里的gap计算方法为:轮播区域减去第一帧宽度,除2,再除左边或者右边的图片张数
item.style.left=(constOffset+(++index)*gap-rw)+'px';//left的值实际上就是第一帧的left+第一帧的宽度+item的间距减去item的宽度
item.style.top=carrouselSelf.setCarrouselAlign(rh)+'px';
});
左边的设置方法类似且更为简单,就不细说了。
⑤旋转时所有图片的位置大小调整
这一步很关键,点击右边按钮下一张的即为左旋转,而点击左边按钮上一张即为右旋转。此时,我们只需要把所有的图片看成一个环形那样,点击一次,换一次位置即完成旋转。具体为左旋转的时候,令第二张的参数等于第一张,第三张等于第二张...而最后一张等于第一张即可。右旋转的时候,令第一张的参数等于第二张,第二张的参数等于第三张...而最后一张的参数等于第一张即可。
这里就说说左旋转吧
if(dir=='left'){
toArray(this.carrouselItems).forEach(function(item,index,array){
var pre;
if(index==0){//判断是否为第一张
pre=_this.carrouselLat;//让第一张的pre等于最后一张
var width=pre.offsetWidth; //获取相应参数
var height=pre.offsetHeight;
var zIndex=pre.style.zIndex;
var opa=pre.style.opacity;
var top=pre.style.top;
var left=pre.style.left;
}else{
var width = tempWidth;
var height = tempHeight;
var zIndex = tempZIndex;
var opa = tempOpacity;
var top = tempTop;
var left = tempLeft;
}
//这里需要注意,因为第二张图片是参照第一张的,而这样改变的时候,第一张是首先被改变的,因此必须先把第一张的相关参数临时保存起来。
tempWidth = item.offsetWidth;
tempHeight = item.offsetHeight;
tempZIndex = item.style.zIndex;
tempOpacity = item.style.opacity;
tempTop = item.style.top;
tempLeft = item.style.left;
item.style.width=width+'px';
item.style.height=height+'px';
item.style.zIndex=zIndex;
item.style.opacity=opa;
item.style.top=top;
// item.style.left=left;
animate(item,'left',left,function(){//自定义的原生js动画函数
_this.rotateFlag=true;
});
});
}
这里的旋转,如果不使用一些动画过度,会显得很生硬。但是原生JS并没有动画函数,这里我是自己写了一个模仿的动画函数。其原理就是获取dom原来的样式值,与新传入的值比较。用一些方法定义一个速度。我这里的速度就是用其差值除18.然定义一个计时器,参考了一下jquery源码里面的时间间隔为每13毫秒执行一次。然后才原来的样式值每次加上speed后等于传入的值的时候清楚计时器即可。具体可以看这里。
好啦,关键的地方都差不多啦,如果明白这些过程应该就很容易了!
四、总结思考
总结:
个人感觉这还是一个比较好理解的插件。如果能结合JQuery来做就相当简单了。但是用原生来写的话,还是有一些不那么流畅的感觉。应该是自定义动画比不上JQuery封装好的动画吧。
还有,这个插件因为图片需要平均分到左右两边,于是对于偶数数量的图片来说,这里用的方法是克隆第一张,然后加到最后,形成一个奇数。
思考:
如果说有bug的话,那就是我定义了一个rotateFlag的标志去判断当前能否旋转,就是预防快速点击的时候跟不上。我在按下的时候把rotateFlag设置为false,然后在动画结束后再把rotateFlag设置为true,但是好像作用并不明显。。。希望有关大神可以指教一下。。。
本轮播插件下载地址:我的github!
原生JS实现"旋转木马"效果的图片轮播插件的更多相关文章
- 纯js写图片轮播插件
最近终于写成了自己创作的图片轮播插件,使用原生js编写.与目前网上流行的轮播插件相比,功能和效果稍弱,但是使用起来相当方便. 先看html代码 <!DOCTYPE html> <ht ...
- Javascript和jQuery WordPress 图片轮播插件, 内容滚动插件,前后切换幻灯片形式显示
用于在有限的网页空间内展示一组产品图片或者照片,同时还有非常吸引人的动画效果.本文向大家推荐12款实用的 jQuery 图片轮播效果插件,帮助你在你的项目中加入一些效果精美的图片轮播效果,希望这些插件 ...
- PgwSlideshow-基于Jquery的图片轮播插件
0 PgwSlideshow简介 PgwSlideshow是一款基于Jquery的图片轮播插件,基本布局分为上下结构,上方为大图轮播区域,用户可自定义图片轮播切换的间隔时间,也可以通过单击左右方向按键 ...
- 图片轮播插件-carouFredSel
carouFredSel图片轮播插件基于Jquery,比较常规的轮播插件,支持滚轮及键盘左右按键,加入其它插件可实现更加复杂的特效. 主页地址:http://caroufredsel.dev7stud ...
- JQuery插件之图片轮播插件–slideBox
来源:http://www.ido321.com/852.html 今天偶然发现了一个比较好用的图片轮播插件—slideBox 先看看效果:http://slidebox.sinaapp.com/ 代 ...
- 图片轮播插件Nivo Slider
推荐:图片轮播插件Nivo Slider 因为项目需要一款切换样式多一些的轮播插件,不经意找到了NivoSlider,非常好用,比bootstrap要好用,而且样式丰富.值得注意的是, ...
- 12款经典的白富美型—jquery图片轮播插件—前端开发必备
图片轮播是网站中的常用功能,用于在有限的网页空间内展示一组产品图片或者照片,同时还有非常吸引人的动画效果.本文向大家推荐12款实用的 jQuery 图片轮播效果插件,帮助你在你的项目中加入一些效果精美 ...
- Nivo Slider - 世界上最棒的 jQuery 图片轮播插件
Nivo Slider 号称世界上最棒的图片轮播插件,有独立的 jQuery 插件和 WordPress 插件两个版本.目前下载量已经突破 1,800,000 次!jQuery 独立版本的插件主要有如 ...
- 结构-行为-样式-requireJs实现图片轮播插件
最近工作需要,就自己写了一个图片轮播插件,不过想到要集成到框架中,于是又用RequireJs改了一遍. 主要文件: style.css jquery-1.11.1.min.js require.js ...
随机推荐
- jquery和Js的区别和基础操作
jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库
在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...
- MIP开发常见问题解答
校验相关 1. MIP 页面的 <a>链接校验报错,MIP 是强制 target="_blank" 吗? 如果想直接跳转MIP页,可以用mip-link 组件:MIP ...
- C++中的事件分发
本文意在展现一个C++实现的通用事件分发系统,能够灵活的处理各种事件.对于事件处理函数的注册,希望既能注册到普通函数,注册到事件处理类,也能注册到任意类的成员函数.这样在游戏客户端的逻辑处理中,可以非 ...
- c#语言规范
0x00 分类 C#语言规范主要有两个来源,即我们熟知的ECMA规范和微软的规范.尽管C#的ECMA规范已经前后修订4次,但其内容仅仅到C# 2.0为止.所以慕容为了方便自己和各位方便查询,在此将常见 ...
- ASP.NET SignaiR 实现消息的即时推送,并使用Push.js实现通知
一.使用背景 1. SignalR是什么? ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指 ...
- H3 BPM让天下没有难用的流程之产品概述
一.产品简介 BPM(Business Process Management),是指根据业务环境的变化,推进人与人之间.人与系统之间以及系统与系统之间的整合及调整的经营方法与解决方案的IT工具. H3 ...
- Android中ListView实现图文并列并且自定义分割线(完善仿微信APP)
昨天的(今天凌晨)的博文<Android中Fragment和ViewPager那点事儿>中,我们通过使用Fragment和ViewPager模仿实现了微信的布局框架.今天我们来通过使用Li ...
- asp.net core 负载均衡集群搭建(centos7+nginx+supervisor+kestrel)
概述 本文目的是搭建三台asp.net core 集群, 并配上 nginx做负载均衡 首先准备要运行的源码 http://pan.baidu.com/s/1c20x0bA 准备三台服务器(或则虚 ...
- 二叉树的递归实现(java)
这里演示的二叉树为3层. 递归实现,先构造出一个root节点,先判断左子节点是否为空,为空则构造左子节点,否则进入下一步判断右子节点是否为空,为空则构造右子节点. 利用层数控制迭代次数. 依次递归第二 ...