天猫首页迷思之-jquery实现左侧广告牌图片轮播

本次要实现的是天猫首页每个楼层左侧的图片轮播效果。见图:

功能点有:点击右箭头向右滑动;点击左箭头向左滑动;什么都不点自动滑动。

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

posted @ 2015-08-12 01:40  石沉溪涧  阅读(966)  评论(0编辑  收藏  举报