最近做Engine的官网,有个3D的Gallery效果,网上倒是有一些3D效果的插件,但元素尺寸基本都是写死的,不能满足我们响应式的需求……

索性就自己写了一个。效果图如下:

3d

如果浏览器不支持3D的transform那么我们就降级一下(这里使用了modernizr来检测CSS的属性支持),使用scale,如下图:

2d

这里有个问题,插件的轮播动画用的是CSS3的transition,IE9是不支持transition的,但是却支持transform2D,所以在IE9里你将不会看到动画效果。当然,你可以修改插件让它的兼容性无与伦比,只是目前这样对我来讲是够用了。

来说一下实现的思路吧。这是一个jQuery和CSS3并用的插件,元素的布局是用流动的百分比布局,也用到了media queries的一些分界点。就是外层容器在最宽的时候里面是放5个item,相应每个item的宽度应该是20%;同样在某个分界点(我这里是1000px)里面的item宽度变成了33.33%,也就是说变成显示3个item了;最终到了手机版上,就只显示1个item了。item都是绝对定位,所以无法撑起外层容器的高度,因此需要给外层容器的padding-top一个适当的百分比来撑开它的高度,否则透视效果是不对的,这个百分比在不同的分界点会有会变化,一般是在某个状态下取当中最大那个item的高度除以外层容器的当前宽度得到的,当然你可以做适当的调整来满足自适应。每个item的初始位置都是left:0; top:0; 通过动态修改它们的translateX来让其显示在正确的位置上。translate里的参数是百分比,注意这个百分比是相对当前这个item的width的。假设现在显示的是3个item,那么0%就是第1个,100%,就是中间那个,200%就是最后一个,-100%就最前面隐藏的那一个,同理400%就是最后面隐藏的那一个。这些百分比的东西是实现自适应的关键。所有的尺寸控制都可以通过修改CSS文件来达到,插件只会在window.onresize里检测当前容器里能放得下多少个item,然后选择预设的transfrom CSS来初始化。目前插件里只有1,3,5这几个数目的情况,我并没有处理html中item数量不能满足基本显示数量的情况,还是那句话,如果你需要,你可以修改它,直到满足你的需求,或者你一不高兴自己重写一个,那再好不过了,你会学到更多。另外还有一点,我们可以把指示当前显示哪些item理解成一个游标,只是这个游标的宽度可能是1,3,5中的某个,这个游标来回地在item的数据上移动取出要显示的那几个item,当然要判断临界的索引。取到后把预设好的相应数量的transform CSS对应地加给它们,剩下的事就交给transition了,它会让gallery动起来。

好吧,说这么多废话会有几个人看……只是,我个人觉得思路往往比实现更重要。

下面是html代码,默认使用的是ul>li结构,插件会自动寻找this下的li元素当做item:

<ul class="responsiveGallery-wrapper"> 
    <li class="responsiveGallery-item">
      <a href="http://www.codingserf.com" target="_blank" class="responsivGallery-link"><img src="images/0.jpg" height="320" width="320" alt="" class="responsivGallery-pic"></a>
      <div class="w-responsivGallery-info">
        <h2 class="responsivGallery-name">Google</h2>
        <h3 class="responsivGallery-position">www.google.com</h3>
      </div>
    </li>
    <li class="responsiveGallery-item">
      <a href="http://www.codingserf.com" target="_blank" class="responsivGallery-link"><img src="images/1.jpg" height="320" width="320" alt="" class="responsivGallery-pic"></a>
      <div class="w-responsivGallery-info">
        <h2 class="responsivGallery-name">Baidu</h2>
        <h3 class="responsivGallery-position">www.baidu.com</h3>
      </div>
    </li>

    ……

</ul>

接下来是核心地CSS代码 :

/*responsiv 3D gallery*/
.responsiveGallery-container{
	width: 100%;
	position: relative;
}
.responsiveGallery-btn{
	position:absolute;
	top: 0;
	z-index: 3;
	display: block;
	width: 5%;
	height: 100%;
}
.responsiveGallery-btn_prev{
	background:url(images/arrow-left.png) center center no-repeat;
	left:1%;
}
.responsiveGallery-btn_next{
	background:url(images/arrow-right.png) center center no-repeat;
	right:1%;
}

.responsiveGallery-wrapper{
	position: relative;
	width: 90%;
	margin: 0 auto;
	padding-top: 25%;/*用padding撑开容器高度*/

	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	-o-transform-style: preserve-3d;
	-ms-transform-style: preserve-3d;
	transform-style: preserve-3d;
	-webkit-perspective: 1000px;
	-moz-perspective: 1000px;
	-o-perspective: 1000px;
	-ms-perspective: 1000px;
	perspective: 1000px;
}
.responsiveGallery-item{
	position: absolute;
	left: 0;
	top: 0;
	z-index: 0;
	display: block;
	width: 20%; /*默认显示5个*/
	opacity: 0;
	visibility: hidden;
}
@media (max-width: 1000px){
	.responsiveGallery-item{
		width: 33.33%; /*此宽度下显示3个*/
	}
	.responsiveGallery-wrapper{
		padding-top: 45%;/*相应调整容器高度*/
	}
}
@media (max-width: 560px){
	.responsiveGallery-wrapper{
		width: 60%;
	}
	.responsiveGallery-item{
		width: 100%; /*最终显示1个,但上条样式决定其宽度为窗口宽度的60%*/
	}
	.responsiveGallery-wrapper{
		padding-top: 80%;/*相应调整容器高度*/
	}
	.responsiveGallery-btn{
		width: 8%;
	}
}
.responsivGallery-link{
	display: block;
	width: 100%;
	box-shadow: 0px 0px 20px rgba(0,0,0,0.3);
}
.responsivGallery-pic{
	width: 100%;
	height: auto;
}
.w-responsivGallery-info{
	width: 80%;
	margin: 0 auto;
	padding-top: 5%;
	text-align: center;
	color: #fff;
}
.responsivGallery-name{
	font-size: 1.25em;
}
.responsivGallery-position{
	padding-top: 4%;
	font-size: 0.875em;
	line-height: 1.3;
}
/*responsiv 3D gallery end*/

插件调用的时候需要传入动画执行时长和两个翻页按钮的jQuery对象。如果你愿意可以开放更多的接口:

$('.responsiveGallery-wrapper').responsiveGallery({
	animatDuration: 400, //动画时长 单位 ms
	$btn_prev: $('.responsiveGallery-btn_prev'),
	$btn_next: $('.responsiveGallery-btn_next')
});

你可以戳这里查看DEMO,并改变浏览器窗口的大小来看下自适应的效果。此外你可以在github上查看此插件的最新版本 。如果你愿意可以为它加上手机操作中的swipe手势。这个插件应该可以拿来直接给zepto用。