作为一个前端工程师,无论公司是什么行业,无论你做什么,基本都会遇到一个无法回避的动画效果:圆形旋转木马。做旋转木马并不难。市面上有很多轮播插件,其中swiper是最著名的一个,使用起来非常简单。但是轮播插件总是不够灵活,一些简单的场景可以处理,而更复杂的场景处理起来就比较麻烦。今天我就带大家一路写一个圆形的旋转木马。使用的技术有:html,css,JavaScript,jQuery,这些都是前端最基础的技术。如果你有基础,爱学,一定要听。如果你什么都不会,你会做什么?然后多看几遍。
1. 效果展示以小米官网的图片轮播为例。其实是一样的。嗯,看下图:
好吧,看效果,别看妹子,虽然妹子长得很好看!
2. 原理分析无限循环轮播的原理是在显示内容的前后各放一组图片。以三张图片的无限循环显示为例。我把这三张图片命名为1.jpg、2.jpg和3.jpg,图片如下:
示意图显示:
其实原理就是分别复制前后两套相同的照片(其实我们不需要完全复制两套,只要能看到前面的1.jpg和后面的1.jpg就行,这里我用这个方法是为了方便大家理解)。当你点击左边的按钮,当图片被旋转到第一张1.jpg的时候,让装图片的容器瞬间拉回第二张1.jpg照片的位置。注意必须是瞬间的。同样,当点击右边的按钮时,当图片被旋转到第三张1.jpg时,保存图片的容器被立即拉回到第二张1.jpg照片的位置。这是实现图片循环轮播的关键,后面会详细说明。
3. 代码Html代码:
<div class="slideImageContainer"> <div class="slideImageLists"> <img src="1.jpeg" /> <img src="2.jpeg" /> <img src="3.jpeg" /> <img src="1.jpeg" /> <img src="2.jpeg" /> <img src="3.jpeg" /> <img src="1.jpeg" /> <img src="2.jpeg" /> <img src="3.jpeg" /> </div> <div class="slideLeftBtn" id="slideLeftBtn"></div> <div class="slideRightBtn" id="slideRightBtn"></div> </div>
& ltdiv class = & # 34slideImageContainer & # 34& gt
& lt;div class = & # 34幻灯片列表& # 34;& gt
& lt;img src = & # 341.jpeg & # 34/& gt;
& lt;img src = & # 342.jpeg & # 34/& gt;
& lt;img src = & # 343.jpeg & # 34/& gt;
& lt;img src = & # 341.jpeg & # 34/& gt;
& lt;img src = & # 342.jpeg & # 34/& gt;
& lt;img src = & # 343.jpeg & # 34/& gt;
& lt;img src = & # 341.jpeg & # 34/& gt;
& lt;img src = & # 342.jpeg & # 34/& gt;
& lt;img src = & # 343.jpeg & # 34/& gt;
& lt;/div & gt;
& lt;div class = & # 34slideLeftBtn & # 34id = & # 34slideLeftBtn & # 34& gt<;/div & gt;
& lt;div class = & # 34sliderrightbtn & # 34;id = & # 34sliderrightbtn & # 34;& gt<;/div & gt;
& lt;/div & gt;
Css代码:
*{ padding: 0; margin: 0; } @font-face { font-family: 'iconfont'; /* project id 208314 */ src: url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.eot'); src: url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.eot?#iefix') format('embedded-opentype'), url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.woff') format('woff'), url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.ttf') format('truetype'), url('//at.alicdn.com/t/font_208314_2l9oi1sn4hmh1tt9.svg#iconfont') format('svg'); } .slideImageContainer{ position: relative; width: 600px; height: 300px; margin: 0 auto; border: solid 1px red; overflow: hidden; } .slideImageLists{ position: absolute; left: -1800px; top: 0; width: 10000px; height: 300px; } .slideImageLists img{ display: block; width: 600px; height: 300px; } .slideLeftBtn,.slideRightBtn{ position: absolute; font-family: "iconfont"; font-size: 60px; top: 120px; color: #191f25; opacity: 0.3; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } .slideLeftBtn:hover,.slideRightBtn:hover{ opacity: 0.6; } .slideLeftBtn{ left: 10px; } .slideRightBtn{ right: 10px; }
*{
填充:0;
margin:0;
}
@ font-face {
font-family:& # 39;iconfont & # 39;/*项目id 208314 */
src:URL(& # 39;//at . alicdn . com/t/font _ 208314 _ 2 L9 oi 1 sn 4 hm h1 TT 9 . eot & # 39;);
src:URL(& # 39;//at . alicdn . com/t/font _ 208314 _ 2 L9 oi 1 sn 4 hm h1 TT 9 . eot?# iefix & # 39)格式(& # 39;嵌入式-opentype & # 39;)、
URL(& # 39;//at . alicdn . com/t/font _ 208314 _ 2 L9 oi 1 sn 4 hm h1 TT 9 . woff & # 39;)格式(& # 39;woff & # 39)、
URL(& # 39;//at . alicdn . com/t/font _ 208314 _ 2 L9 oi 1 sn 4 hm h1 TT 9 . TTF & # 39;)格式(& # 39;truetype & # 39)、
URL(& # 39;//at . alicdn . com/t/font _ 208314 _ 2 L9 oi 1 sn 4 hm h1 TT 9 . SVG # icon font & # 39;)格式(& # 39;svg & # 39);
}
。slide image container {
position:relative;
宽度:600px
高度:300px
margin: 0自动;
边框:纯色1px红色;
溢出:隐藏;
}
。slideImageLists{
位置:绝对;
left:-1800 px;
top:0;
宽度:10000px
高度:300px
}
。slide imagelists img {
display:block;
宽度:600px
高度:300px
}
。slideLeftBtn,。sliderrightbtn {
position:绝对;
font-family:& # 34;iconfont & # 34;
font-size:60px;
top:120 px;
color:# 191 f25;
不透明度:0.3;
cursor:指针;
用户选择:无;
-WebKit-用户选择:无;
-moz-user-select:无;
-ms-user-select:无;
}
。slideLeftBtn:悬停,。sliderrightbtn:hover {
不透明度:0.6;
}
。slide left BTN {
left:10px;
}
。sliderrightbtn {
right:10px;
}
页面布局是内容中非常重要的一部分,它是页面的基石。一个写得好的页面布局在达到效果的时候可以带来很大的便利。因此,这里我们强调几个应该注意的点:
1.所有的图片都要放在一个长容器里,这里是slideImageList,每一次移动实际上都意味着相对于它的父元素slideImageContainer在移动,所以需要给slideImageContainer一个position:relative,给slideImageList一个position:absolute。
2.slideImageList应该放在一个相对较小的容器中,在本例中是slideImageContainer,用于显示您想要显示的区域。注意添加overflow:hidden属性,这样就不会显示不必要的内容。
3.左右键我用的是iconfont,比较简单,这里就不细说了。不会用iconfont的同学可以直接在上面粘贴两张图片或者左右箭头符号。
4.容器slideImageList中的图片要排成一条直线,最初,我们需要给slideImageList一个左值,因为一开始我们希望显示第四张照片,所以此时的左值是-1800px,所以记住这个值,因为后面我们会频繁使用这个值。
5.@font-face是指与iconfont相关的资源内容,没有iconfont可以忽略。
接下来,看看javascript代码:
var slideIndex = 3; //记录初始图片的下标( 默认最初展示第四张图片,下标从0开始,所以初始值为3 ) //左边按钮的点击事件 $("#slideLeftBtn").on("click",function(){ // 点击左按钮的时候想要显示当前图片的前一张,所以slideIndex值要减去1 slideIndex--; // animateLength表示想要让slideImageLists移动到什么位置,slideImageLists 的位置由 left属性来控制 var animateLength = slideIndex * (-600) + "px"; $(".slideImageLists").animate({"left":animateLength},"slow",function(){ // animate的回调函数(即执行完动画之后才会执行函数里面的内容) if(slideIndex <= 0){ $(".slideImageLists").css({"left":"-1800px"}); slideIndex = 3; } }); }) //右边按钮的点击事件 $("#slideRightBtn").on("click",function(){ // 点击右按钮的时候想要显示当前图片的后一张,所以slideIndex值要加上1 slideIndex++; var animateLength = slideIndex * (-600) + "px"; $(".slideImageLists").animate({"left":animateLength},"slow",function(){ if(slideIndex >= 6){ $(".slideImageLists").css({"left":"-1800px"}); slideIndex = 3; } }) })
var slide index = 3;//记录初始图片的下标(默认初始显示第四张图片,下标从0开始,所以初始值为3 )
//左键的Click事件
$(& # 34;# slideLeftBtn & # 34).打开(& # 34;点击& # 34;,function(){
//当你点击左键时,你想显示当前图片的上一张图片,所以需要减去1
slide index-;[/h
// animateLength表示您希望slide imagelist移动到的位置,slide imagelist的位置由left属性
var animate length = slide index *(-600)+& # 34;px & # 34;
$(& # 34;。幻灯片列表& # 34;).动画({ & # 34;左& # 34;:animateLength},& # 34;慢& # 34;,function () {
/Animate的回调函数(即函数中的内容直到动画结束才会执行)
if(slide index < = 0){
$(& # 34;。幻灯片列表& # 34;).CSS({ & # 34;左& # 34;:"-1800像素& # 34;});
slide index = 3;
}
});
})
//右键点击事件
$(& # 34;# sliderrightbtn & # 34;).打开(& # 34;点击& # 34;,function(){
//当你点击右键时,你想显示当前图片的下一张图片,那么在slideIndex的值上加1
slide index ++即可;
var animate length = slide index *(600)+& # 34;px & # 34;
$(& # 34;。幻灯片列表& # 34;).动画({ & # 34;左& # 34;:animateLength},& # 34;慢& # 34;,function(){
if(slide index & gt;= 6){
$(& # 34;。幻灯片列表& # 34;).CSS({ & # 34;左& # 34;:"-1800像素& # 34;});
slide index = 3;
}
})
})
现在让我们关注JavaScript代码。还有几个要点需要注意,其中一些我已在准则中注明:
1.全局变量slideIndex指的是图片的下标。有九张图片,下标从0开始,所以九张图片的下标值分别是0-8。在这里,我们默认显示第四张图片,因此slideIndex的初始值设置为3。此外,需要注意的是,slideIndex是一个全局变量,因此可以在函数内部和外部访问它,并且只初始化一次。
2.animateLength是一个局部变量,指的是您希望slideImageLists移动的位置。注意添加单元,并将它们分配给slideimagelists的left属性。
3.jquery的animate方法,详见下图:
接下来,以点击左键为例,全面分析流程:
1.最初显示第四张图片,下标3。(var slideIndex = 3)
2.将单击事件绑定到左侧按钮。
3.当你点击左按钮时,你想显示当前照片的上一张照片,所以你需要在图片的下标上减去1 (slideIndex -)。
4.计算slideImageLists应该移动的位置(slide index *(-600)+& # 34;px & # 34),记得加单位。为什么要乘以-600?首先,600是一张照片的宽度。上面我们分析过,如果要默认显示第四张照片,slideImageLists的left属性值是-1800px。同样,如果点击左按钮,想要显示第三张照片,需要slideImageLists的左属性值为-1200px,所以是(3-1) * (-600)。px & # 34=-1200像素.
5.使用“动画”来执行动画。将上一步中计算的值赋给slideImageLists的left属性。请注意,animate方法本身包含过渡,因此请记住,无需向slideImageLists添加过渡属性来实现过渡。
6.实现圆形转盘的关键点来了。以上步骤实现了轮播,但没有实现圆形轮播。回想刚才说的,有三组1.jpg、2.jpg、3.jpg的照片。默认情况下,显示第四张照片,即第二组照片中的1.jpg。如果你点击左边的按钮,第一组照片中的3.jpg、2.jpg和1.jpg将分别显示出来。假设你一直点击左键。当我们展示第一张照片,也就是第一组的1.jpg时,图片的下标slideIndex为0。当此时显示的图片下标slideIndex为0,动画结束时,我们需要做一个操作,将slideImageLists的左值瞬间改为-1800px。正如我们在上面强调的,当第四个图片,即第二组中的1.jpg最初显示时,该值是slideImageLists的左值,并且当前显示的图片的下标slideIndex被更改为3。
Animate非常方便,因为他提供了一个回调函数,动画完成后会自己执行。
另外,这里还有一个需要特别注意的地方。我们一直强调,一定要瞬间把slideImageLists拉回左边值为-1800px的地方。那是因为如果类似于使用animate,用户会看到一个动画过程,这是我们无法接受的。所以我在瞬间拉回的时候,用jQuery的css方法来改变left属性。
不完美的地方但在这一点上,还是有不完善的地方。如果你多次点击按钮,就会出现混乱。这时候我们需要做的是,动画过程中点击按钮是无效的,只有动画结束后才能继续点击实现动画。这里我采用的方案是引入一个布尔变量isClickable,初始值为true,表示可以初始点击。当用户点击按钮时,他将判断isClickable的当前值。如果值为true,将执行slideIndex -的操作;否则,它将返回false,并且不会执行下面的代码。
我们来分析一下此时的过程:
1.最初,isClickable的值为true,这意味着可以单击当前按钮。
2.这时,我们点击左键,isclick的值为true,slideIndex -的操作将被执行。并将isClickable的值设置为false,这表示它现在在动画中。此时再次点击左键,停止slideIndex -的操作,但输入return false终止当前代码。
3.需要注意的是,我们需要在动画结束后,也就是在回调函数中,将isClickable的值改为true,这样在动画结束后点击按钮时,就可以进行下一个动画了。
具体代码如下:
var isClickable = true//是否可以点击,默认点击 var slide index = 3; $(& # 34;# slideLeftBtn & # 34).打开(& # 34;点击& # 34;,function(){ if(is clickable = = true){ slide index-; }else{ 返回false } is clickable = false; var animate length = slide index *(600)+& # 34;px & # 34; $(& # 34;。幻灯片列表& # 34;).动画({ & # 34;左& # 34;:animateLength},& # 34;慢& # 34;,function(){ is clickable = true; if(slide index & lt;= 0){ $(& # 34;。幻灯片列表& # 34;).CSS({ & # 34;左& # 34;:"-1800像素& # 34;}); slide index = 3; } }); })xxxxxxxxxxbr var is clickable = true;//是否可以点击,默认可以点击br var slide index = 3;br $(& # 34;# slideLeftBtn & # 34).打开(& # 34;点击& # 34;,function(){ br if(is clickable = = true){ br slide index-;br }else{br返回falsebr } br isClickable = falsebr var animate length = slide index *(600)+& # 34;px & # 34;br $(& # 34;。幻灯片列表& # 34;).动画({ & # 34;左& # 34;:animateLength},& # 34;慢& # 34;,function(){ br is clickable = true;br if(slide index & lt;= 0){ br $(& # 34;。幻灯片列表& # 34;).CSS({ & # 34;左& # 34;:"-1800像素& # 34;});br slide index = 3;br } br });Br})以上是点击左键的思路。点击右键和点击左键的思路是一样的。我相信你足够聪明,能够立刻明白。有问题欢迎大家和我交流。
祝你工作顺利~