本次要实现的是天猫首页每个楼层左侧的图片轮播效果。见图:
功能点有:点击右箭头向右滑动;点击左箭头向左滑动;什么都不点自动滑动。
1.实现样式。简单分析一下大概的html结构。一个大的div里面包含两个箭头以及轮播的容器。图片是由三个p标签组成,每个p标签中包含3个图片。css见github
1 <div class="floor-show-middle"> 2 <a class="floor-show-middle-arrow arrow-left" title="上一个幻灯片"></a> 3 <a class="floor-show-middle-arrow arrow-right" title="下一个幻灯片"></a> 4 <div class="brand-slide-content"> 5 <div class="brand-slide-bg" is-animating="false"> 6 <p class="pt-page page-current"> 7 <a href=""><img src="images/1-1.jpg"></a> 8 <a href=""><img src="images/1-2.jpg"></a> 9 <a href=""><img src="images/1-3.jpg"></a> 10 </p> 11 <p class="pt-page"> 12 <a href=""><img src="images/2-1.jpg"></a> 13 <a href=""><img src="images/2-2.jpg"></a> 14 <a href=""><img src="images/2-3.jpg"></a> 15 </p> 16 <p class="pt-page"> 17 <a href=""><img src="images/3-1.jpg"></a> 18 <a href=""><img src="images/3-2.jpg"></a> 19 <a href=""><img src="images/3-3.jpg"></a> 20 </p> 21 </div> 22 </div> 23 </div>
得到的效果是:
2. 图片轮播动画效果的实现。
为了方便描述,给三个需要展示的p编个号:①②③。
轮播的难点1:图片没法成圆圈式排列,怎么才能让处于边界的p①在向右滑动的时候左边有个③在向右滑动,and 怎么让处于边界的p③在向左滑动的时候右边有个①在向右滑动。
轮播的难点2:由于无法控制用户点击箭头的速度,如果前一个图片移动没完成就进行下一个图片移动,会造成混乱。解决办法很简单,为每个div增加一个属性is_animating,当动画开始设置为true,监听动画结束事件,结束后设置为false;每次在执行动画之前都需要判断这个变量。
如果三个p标签按照从左至右依次不叠加排列①②③,需要做到滑动效果的话②是很好实现,而①在从左至右滑动时因为左边没有元素了,所以无法循环滑动,同理③也是。好了,想办法。
方法一:p标签从左至右排列,头尾添加副本法。为了保证每张图片都有顺滑的从左至右滑动的动画效果,可以在在头部前面加上p③,在尾部加上p①;最后p标签的排列效果就是③①②③①;举个例子:
1.将div.brand-slide-bg中的样式设置为position:absolute;这样就可以使用left,right属性来让该div移动;
2.当第一个①在可视区域内时,点击左箭头 -> div向左移动1个单位 -> 移动完成后,将div的left的值改为-300px,让第二个③迅速处于可视区域
实现方法一:使用jquery中,animate方法移动(未添加动画原子性判断,刚开始写复用性还不太好,可以参考下思想):
右箭头处理函数animate()
1 function autoMove(){ 2 var p_length=100;//p元素的宽度 3 var slide_div=$(".brand-slide-bg");//class为brand-slide-bg的div 4 var pic_index=slide_div.attr("index");//当前图片的索引 5 var p_quantities=slide_div.children("p").length; 6 slide_div.clearQueue(); 7 if (pic_index==1) { 8 pic_index=p_quantities; 9 var last_p=slide_div.children("p").last(); 10 slide_div.css("left","-100px"); 11 slide_div.children("p").first().before(last_p.clone()); 12 13 slide_div.animate({ 14 left:0 15 },700, 16 function(){ 17 //回调函数,删除添加的p 18 slide_div.children("p").first().remove();//删除为了滑动而添加的元素 19 var left=getLeft(p_length,pic_index); 20 slide_div.css("left",left); 21 }); 22 }else{ 23 pic_index--; 24 var left=getLeft(p_length,pic_index);//相对于父容器向左移动的值 25 slide_div.animate({ 26 left:left 27 },800); 28 } 29 slide_div.attr("index",pic_index); 30 autoTask=setTimeout("autoMove()",2000); 31 }
自动轮播处理函数animate()
实现方法二:使用css3的属性transition来移动:
CSS3特性:transition+transform
以下是一个点击右边箭头的幻灯片向右翻动的代码,通过监听webkitTransitionEnd方法监听transition的结束时间,结束的时候快速将幻灯片的位置换到-100px的初始位置。
1 $(".arrow-right").click(function(){ 2 var slide_div=$(this).siblings(".brand-slide-content").children(".brand-slide-bg");//滑动幻灯片的父div 3 var index=slide_div.attr("index");//当前图片的索引,默认为1 4 index++; 5 var position=index*(-100)+"px"; 6 if(index==2){ 7 slide_div.css("-webkit-transform-origin","-100px 0 0"); 8 } 9 slide_div.css("-webkit-transition-duration","0.5s"); 10 slide_div.css("-webkit-transform","translate3d("+position+",0,0)"); 11 slide_div.attr("index",index); 12 }); 13 /*小的滑动的幻灯片end*/ 14 15 $(".brand-slide-bg").bind(‘webkitTransitionEnd‘, function(){ 16 index=$(this).attr("index");//监听动画完成的动作 17 if(index==4){ 18 index=1; 19 $(this).css("-webkit-transition-duration","0s"); 20 $(this).css("-webkit-transform","translate3d(-100px,0,0)"); 21 $(this).attr("index",index); 22 } 23 }); 24
transition右箭头处理函数
方法二:p标签叠加排列,为每个p添加每个滑动方向的动画事件。
这种方式不需要新增p的副本,只有需要展示的p显示,其余都隐藏。
这次用css3的新特性,@ keyframes来实现。通过 @keyframes 规则,能够创建动画。配合css属性animation来使用。
css样式定义:
由于要支持不同浏览器,@-moz-keyframes在火狐中被解释,@-webkit-keyframes在chrome等webkit为核心的浏览器中被解释。
keyframe中需要定义from和to两个key的值,表示动画开始时元素的样式和动画结束时元素的样式。from,to也可以用百分比来代替,更精确
animate属性定义使用哪个动画、动画时常、动画执行次数。
设计上,为每个p元素在不同场景下划分不同css类,定义不同的动画。
.moveToLeft表示从当前位置向左移动。.moveFromLeft表示从左移动到指定位置。依次类推。
在定义一个类.page_current将该元素不隐藏展示
举个例子:p有①②③三个,默认都是隐藏状态。当前可视的只有②,点击左箭头。给p赋值的场景如下:②新增.moveToLeft,③新增moveFromRight,动画完成后,②去掉.moveToLeft;③去掉moveFroRight,③加上.page_current类
1 .moveFromRight{ 2 animation:moveFromRight 0.5s ease 1; 3 -moz-animation:moveFromRight 0.5s ease 1; /* Firefox */ 4 -webkit-animation:moveFromRight 0.5s ease 1; /* Safari and Chrome */ 5 -o-animation:moveFromRight 0.5s ease 1; /* Opera */ 6 } 7 .moveToLeft{ 8 animation:moveToLeft 0.5s ease 1; 9 -moz-animation:moveToLeft 0.5s ease 1; /* Firefox */ 10 -webkit-animation:moveToLeft 0.0.5s ease 1; /* Safari and Chrome */ 11 -o-animation:moveToLeft 0.5s ease 1; /* Opera */ 12 } 13 .moveFromLeft{ 14 animation:moveFromLeft 0.5s ease 1; 15 -moz-animation:moveFromLeft 0.5s ease 1; /* Firefox */ 16 -webkit-animation:moveFromLeft 0.5s ease 1; /* Safari and Chrome */ 17 -o-animation:moveFromLeft 0.5s ease 1; /* Opera */ 18 } 19 .moveToRight{ 20 animation:moveToRight 0.5s ease 1; 21 -moz-animation:moveToRight 0.5s ease 1; /* Firefox */ 22 -webkit-animation:moveToRight 0.5s ease 1; /* Safari and Chrome */ 23 -o-animation:moveToRight 0.5s ease 1; /* Opera */ 24 } 25 26 @-webkit-keyframes moveToLeft { 27 to { -webkit-transform: translateX(-100%); } 28 } 29 @-moz-keyframes moveToLeft { 30 to { -moz-transform: translateX(-100%); } 31 } 32 @keyframes moveToLeft { 33 to { transform: translateX(-100%); } 34 } 35 @-webkit-keyframes moveFromLeft { 36 from { -webkit-transform: translateX(-100%); } 37 } 38 @-moz-keyframes moveFromLeft { 39 from { -moz-transform: translateX(-100%); } 40 } 41 @keyframes moveFromLeft { 42 from { transform: translateX(-100%); } 43 } 44 45 @-webkit-keyframes moveToRight { 46 to { -webkit-transform: translateX(100%); } 47 } 48 @-moz-keyframes moveToRight { 49 to { -moz-transform: translateX(100%); } 50 } 51 @keyframes moveToRight { 52 to { transform: translateX(100%); } 53 } 54 55 @-webkit-keyframes moveFromRight { 56 from { -webkit-transform: translateX(100%); } 57 } 58 @-moz-keyframes moveFromRight { 59 from { -moz-transform: translateX(100%); } 60 } 61 @keyframes moveFromRight { 62 from { transform: translateX(100%); } 63 }
keyframes样式定义
1 $(document).ready(function(){ 2 $(".brand-slide-bg").children("p").bind(‘webkitAnimationStart‘, function() { 3 $(this).parent(".brand-slide-bg").attr("is-animating",true); 4 }); 5 $(".brand-slide-bg").children("p").bind(‘webkitAnimationEnd‘, function() { 6 if($(this).hasClass("moveToLeft")){ 7 $(this).removeClass("page-current"); 8 $(this).removeClass("moveToLeft"); 9 } 10 if($(this).hasClass("moveToRight")){ 11 $(this).removeClass("page-current"); 12 $(this).removeClass("moveToRight"); 13 } 14 if($(this).hasClass("moveFromRight")){ 15 $(this).addClass("page-current"); 16 $(this).removeClass("moveFromRight"); 17 } 18 if($(this).hasClass("moveFromLeft")){ 19 $(this).addClass("page-current"); 20 $(this).removeClass("moveFromLeft"); 21 } 22 $(this).parent(".brand-slide-bg").attr("is-animating",false); 23 }); 24 $(".arrow-right").click(function() { 25 slide_div=$(this).siblings(".brand-slide-content").children(".brand-slide-bg"); 26 moveLittlePage(slide_div,"right","moveFromLeft","moveToRight"); 27 }); 28 $(".arrow-left").click(function() { 29 slide_div=$(this).siblings(".brand-slide-content").children(".brand-slide-bg"); 30 moveLittlePage(slide_div,"left","moveFromRight","moveToLeft"); 31 }); 32 page_auto_move(); 33 }); 34 35 function page_auto_move(){ 36 $(".brand-slide-bg").each(function(){ 37 moveLittlePage($(this),"right","moveFromLeft","moveToRight"); 38 }); 39 setTimeout("page_auto_move()",2000); 40 } 41 function moveLittlePage(slide_div,way,from_css,to_css){ 42 if(slide_div.attr("is-animating")=="true"){return;}//动画未结束不能开始 43 var current_css="page-current"; 44 var current_p=slide_div.children(".page-current"); 45 current_p.addClass(to_css); 46 if(way=="left"){ 47 if (current_p.next().length<=0) { 48 slide_div.children().first().addClass(from_css); 49 slide_div.children().first().addClass(current_css); 50 }else{ 51 current_p.next().addClass(from_css); 52 current_p.next().addClass(current_css); 53 } 54 }else if(way=="right"){ 55 if (current_p.prev().length<=0) { 56 slide_div.children().last().addClass(from_css); 57 slide_div.children().last().addClass(current_css); 58 }else{ 59 current_p.prev().addClass(from_css); 60 current_p.prev().addClass(current_css); 61 } 62 } 63 }
keyframes完整版js方法
最终我采用了css3得keyframes方法,源代码传送门:https://github.com/HappyBangs/bang_plugins/tree/master/plugin-p-slide