css3+jquery制作3d旋转相册
首先来看一下今天的炫酷效果:
首先分析一下这张图片:
1.每张图片都有倒影
2.这11张图片呈圆形均匀排列
3.可旋转,上下移动(当然这是效果做出来以后,图片是分析不出来的)
那下面就开始吧。
一。准备
新建三个文件夹分别命名为css,js,img分别存放demo.css,jquery.js、demo.js,11张示例图片。新建demo.html将demo.css,jquery.js,demo.js引入。
二。图片倒影制作
1 <div id="wrap"> 2 <img src="img/1.jpg"> 3 <img src="img/2.jpg"> 4 <img src="img/3.jpg"> 5 <img src="img/4.jpg"> 6 <img src="img/5.jpg"> 7 <img src="img/6.jpg"> 8 <img src="img/7.jpg"> 9 <img src="img/8.jpg"> 10 <img src="img/9.jpg"> 11 <img src="img/10.jpg"> 12 <img src="img/11.jpg"> 13 </div>
首先我们新建一个大的div来包裹这11张图片
*{ padding:0; margin:0; } body{ background:#000; overflow:hidden; } #wrap{ width:133px; height:200px; margin: 200px auto; position:relative; transform-style:preserve-3d; transform:perspective(900px) rotateX(-10deg) rotateY(0deg); } #wrap img{ position:absolute; top:0; left:0; box-shadow: 0 0 10px #FFFFFF; border-radius:10px; box-reflect:below 8px linear-gradient(top,rgba(0,0,0,0) 40%,rgba(0,0,0,.7) 100%); -webkit-box-reflect:below 8px -webkit-linear-gradient(top,rgba(0,0,0,0) 40%,rgba(0,0,0,.7) 100%); }
(1)*这里就不多说了,是为了消除浏览器默认的间距。
(2)body属性设置背景颜色为黑色,溢出隐藏(这里主要是为了不出现滚动条影响图片整体效果)。
(3)#wrap它的宽高大家一定很好奇为什么会那么小,他的宽高是等同于一张图片的宽高,这里是为了使后期制作旋转时候它能够以图片自身旋转而不跑偏(这里大家不明白的话,可以写完所有代码后设置一个较大的值,试试就知道了哦)。
margin主要是为了让图片水平居中距上下200px。
transform-style:preserve-3d主要是让图片展示出3d效果。
transform:perspective(900px)[这个属性设置镜头到元素平面的距离(大家如果不好理解的话就记住这个是利用近大远小的道理后期可以调节他的大小实验哦)] rotateX(-10deg)[围绕x轴旋转-10°] rotateY(0deg)[围绕y轴旋转0°]。告诉大家一个简单易懂的方法,画一个平面直角坐标系,这是非常直观的。
(4)#wrap img是规定了#wrap里面的img属性,前面的绝对定位是为了让所有图片重叠在一起。
box-shadow设置设置了他的阴影效果
border-radius设置了它的圆角大小
box-reflect设置它的倒影效果
这里就不过多陈述css3属性的用法了,大家可以在w3c查看。
二。使图片均匀分布
$(function(){ $(\'#wrap img\').each(function(i) { //遍历 $(\'#wrap img\')----改变他们的css样式 $(this).css(\'transform\', \'rotateY(\'+ i*Deg +\'deg) translateZ(350px)\').attr(\'ondragstart\',\'return false\'); //旋转以及禁止拖拽复制 }); })
如果设置css属性有疑问的话,可以这样想:translateZ(350px)设置了Z轴的距离,把他看成以(0,0)为圆心,350px为半径的圆,把图片均匀分布在圆上。
这里设置了图片禁止拖拽的属性,与之相呼应的是我们需要的html页面加上这个属性
<html onselectstart=\'return false\'>
不加这个的话页面会报错。当然如果不加的话不影响现在图片的显示,但是会影响下面做图片的旋转。
进行到这步为止,图片上的效果就展示出来了,但是现在是生硬的,没有动画,只是静态的显示。
三。旋转、移动图片
思路:
当鼠标按下并滑动的时候wrap的整体也是跟着滑动的,所以需要记录鼠标开始到结束的位置,根据鼠标x轴和y轴之间的差值,计算#wrap需要旋转和移动的大小
$(function(){ var imgL = $(\'#wrap img\').length; //获取当前的img 长度 var Deg = 360 / imgL; // 360/imgL 和角度有关系 var roY = 0,roX = -10,xN,yN; $(document).mousedown(function(ev){ //绑定事件 鼠标按下时触发的时间 var x_ = ev.clientX; //获取当前鼠标相对于浏览器页面(或客户区)的 x 方向的位置 保存在变量 x_ var y_ = ev.clientY; //………………y方向的位置 保存在变量y_ $(this).bind(\'mousemove\',function(ev){ //给当前元素 (这里的当前元素是document )绑定 mousemove(鼠标在当前元素内移动的事件) var x = ev.clientX; //获取当前鼠标相对于浏览器页面(或客户区)的 x 方向的位置 保存在变量 x var y = ev.clientY; //………………y方向的位置 保存在变量y xN = x - x_; //计算鼠标在当前元素内 相对 上次鼠标按下时的 x轴距离 并保存在变量 yN = y - y_; //计算鼠标在当前元素内 相对 上次鼠标按下时的 y轴距离 并保存在变量 roY += xN*0.2; //按照比例换算 并在变量基础上增加(围绕Y轴旋转的角度,之所以乘0.2是为了不让自己的鼠标动作太敏感,可以改变数值试一下,理解个中含义) roX +=yN*0.07; //按照比例换算 并在变量基础上增加(围绕x轴旋转的角度,意义同上) $(\'#wrap\').css(\'transform\',\'perspective(800px) rotateX(\'+ roX +\'deg) rotateY(\'+ roY +\'deg)\'); //$(\'#wrap\') 改变css动画transform样式 值为…………角度是变量roY,roX的 x_ = ev.clientX; //并将鼠标按下的位置设置成当前移动到的位置 y_ = ev.clientY; //并将鼠标按下的位置设置成当前移动到的位置 }); }).mouseup(function(){ //绑定事件 鼠标松开时触发的时间 $(this).unbind(\'mousemove\'); // 移除 当前元素(这里的当前元素是document )的 mousemove(鼠标在当前元素内移动的事件) });
});
注释讲的很清楚,这里就不过多赘述了,到现在已经可以看到效果了,按住鼠标左键上下拖动试试吧。
但是到此为止看到的效果又显得很生硬,不流畅,所以为他加个定时器,来让图片真正的转动起来。
$(function(){ var imgL = $(\'#wrap img\').size(); //获取当前的img 长度 console.log($(\'#wrap img\').size()); var Deg = 360 / imgL; // 360/imgL 和角度有关系 var roY = 0,roX = -10,xN,yN,play=null; //挨个赋值 $(\'#wrap img\').each(function(i) { //遍历 $(\'#wrap img\')----改变他们的css样式 $(this).css(\'transform\', \'rotateY(\'+ i*Deg +\'deg) translateZ(350px)\') .attr(\'ondragstart\',\'return false\'); //旋转以及禁止拖拽复制 }); $(document).mousedown(function(ev){ //绑定事件 鼠标按下时触发的时间 clearInterval( play ); //关闭计时器(play) var x_ = ev.clientX; //获取当前鼠标相对于浏览器页面(或客户区)的 x 方向的位置 保存在变量 x_ var y_ = ev.clientY; //………………y方向的位置 保存在变量y_ $(this).bind(\'mousemove\',function(ev){ //给当前元素 (这里的当前元素是document )绑定 mousemove(鼠标在当前元素内移动的事件) var x = ev.clientX; //获取当前鼠标相对于浏览器页面(或客户区)的 x 方向的位置 保存在变量 x var y = ev.clientY; //………………y方向的位置 保存在变量y xN = x - x_; //计算鼠标在当前元素内 相对 上次鼠标按下时的 x轴距离 并保存在变量 yN = y - y_; //计算鼠标在当前元素内 相对 上次鼠标按下时的 y轴距离 并保存在变量 roY += xN*0.2; //按照比例换算 并在变量基础上增加 roX +=yN*0.07; //按照比例换算 并在变量基础上增加 $(\'#wrap\').css(\'transform\',\'perspective(800px) rotateX(\'+ roX +\'deg) rotateY(\'+ roY +\'deg)\'); //$(\'#wrap\') 改变css动画transform样式 值为…………角度是变量roY,roX的 x_ = ev.clientX; //并将鼠标按下的位置设置成当前移动到的位置 y_ = ev.clientY; //并将鼠标按下的位置设置成当前移动到的位置 }); }).mouseup(function(){ //绑定事件 鼠标松开时触发的时间 $(this).unbind(\'mousemove\'); // 移除 当前元素(这里的当前元素是document )的 mousemove(鼠标在当前元素内移动的事件) play = setInterval(function(){ //开始周期性计时器 xN = xN * 0.95; //按照比例换算 yN = yN * 0.95; //按照比例换算 if ( Math.abs(xN) <= 0.5 && Math.abs(yN)<= 0.5 ) //判断 (xN的绝对值<=0.5)而且 yN的绝对值也要<= 0.5)的时候就执行下面的语句 { clearInterval( play ); //关闭计时器(play) } roY += xN*0.2; //按照比例换算 并在变量基础上增加 roX +=yN*0.07; //按照比例换算 并在变量基础上增加 $(\'#wrap\').css(\'transform\',\'perspective(800px) rotateX(\'+ roX +\'deg) rotateY(\'+ roY +\'deg)\'); //$(\'#wrap\') 改变css动画transform样式 值为…………角度是变量roY,roX的 },30); //计时器每30毫秒触发一次 }); });
这里为了比较直观定时器放在哪里,重复了上面的代码。
解释一下定时器:
当鼠标松开的时候如果没有定时器的话,旋转就到此为止了,但是这并不是这个效果想要的,当鼠标滑动幅度较大的时候,图片整体也会旋转不同角度,距离越大旋转的角度也就越大,并且到一定数值后让定时器停下来,代码与上面旋转的类似,这里不过多赘述。这里注意的是,一定要定时器停下来。乘不同数值会有不同的效果,如果不是很理解的话,改变数值看效果是你最好的选择,最近状态不好,思路可能没有之前写的好,请见谅/(ㄒoㄒ)/~~