鼠标跟随的3D转动
首先,甩一枚简单的demo看下要实现的效果。点击右下角可查看源码。
ok,直接开干,这个demo里面主要用到了两个属性:transform
和perspective
。分别可以设置3D和透视投影的效果。
3D变换效果
首先介绍下transform
,写过一丢丢动画的孩子都会接触过的属性。CSS3
的3D效果是使用transform
的rotateX(Y, Z)
,translateX(Y, Z)
,scaleX(Y, Z)
方法进行设置的。
上图就是一个3D坐标系,需要注意的是,3D元素的原点应该是在元素的中心,而不是像上图一样在立方体的一个角上。如果只是单单一个元素的话,它的形状就是一个平面区域。下面简单介绍一下transform
中相关的3D方法。
rotateX(Y, Z)
顾名思义就是绕着X轴(Y轴或者Z轴)旋转。注意:逆时针为正方向(如图)
translateX(Y, Z)
默认情况下,开启的是平面投影,所以此时设置translateZ
是没有什么luan用的。那怎么生效呢,看下去才告诉你(╭(╯^╰)╮)。
scaleX(Y, Z)
缩放,好理解。偶尔会用来做字号的特殊处理,比如像chrome默认的最小字号是12px
,要是你家视觉非要设置10px
大小的字体咋整,那就给他一巴掌,叫他要求这么多(现实情况是可以用这个属性来解决……)。
题外话:chrome的默认最小字号可以在设置中更改,不过你的用户可不管这些。
transform-style属性
它有两个值:
flat
(默认,顾名思义就是平面状态,所以上面说的设置translateZ才会失效。)preserve-3d
聪明如你马上明白preserve-3d
才是主角,设置了transform-style: preserve-3d
的父元素会生成一个3D空间,把所有的子元素都包括在这个3D空间内。
注意:上面说的是子元素 ,不是后代元素,看看demo中的我是preserve-3d的孙子
这行字所在的元素,Z值和它爸爸黑月
是不同的,但是转动卡片发现,视觉效果上他们是在同一个Z值平面的。那要让孙子上的Z值也生效呢?啥,你还不知道!那你再看一遍上面的两段话- -。(答案:在黑月
上再设置一次这个属性,可以在demo上尝试修改下看看)。
对于父元素设置的transform
属性,都会应用到生成的这个3D空间,对整个空间进行3D操作(旋转,平移,缩放)。最后会把所有的元素投影到屏幕
上,不是父元素上!
当transform-style
的值为flat
时,子元素和父元素是互相独立的,并没有在父元素的3D空间内,他们各自做各自的3D变换,然后按照先后顺序投影到父元素上。这也是flat
时,translateZ失效的原因。
tips:设置在transform属性上的rotateX(Y, Z)
,translateX(Y, Z)
,scaleX(Y, Z)
方法是从右向左执行的。
透视投影
透视投影是模拟人眼的图像观察方式,让平面上的物体呈现现实的视觉效果。
有两种设置方式:
perspective: none | <length>;
transform: perspective(<length>) method(p) method(p) ...;
第一种:可以将子元素(不包含自身,不包括后代元素)的投影效果设置为透视投影。
第二种:为这个元素自身开启透视投影模式。
先看下3D视角的原理图,来自这里
图中淡蓝色部分即电脑屏幕所在的平面(z=0的平面),眼睛所在的位置就是通过perspective
设置的模拟焦点位置,焦点到z=0平面的距离就是perspective
的值,而橘红色部分就是设置了translateZ
为负值的3D元素的所在平面,3D元素到z=0平面的距离就是3D元素上translateZ
的值,如图为负值,如果在焦点和z=0及平面之间,则为正值。
这是透视的平面原理图,来自这里。
通过这两张图,应该能够很直观的看出perspective
和translateZ
的设置对于3D元素在屏幕上产生的投影的效果了。当元素的z值大于’perspective’的值时,你就看不见它了,就像你的boss站在你的脑袋后面一样一样。一般情况下,’perspective’设置500px到1000px在视觉上比较合理。
在demo中,如果取消perspective
透视属性,你会发现,卡片就像一个没固定好的相框在转动,这就算是透视属性的必要性。
透视投影还可以设置焦点的位置(默认在中心),因为你的脑袋也是可以动的:
perspective-origin: x y;
到这里,3d和透视投影的相关属性就介绍完了,有什么不清楚的你可以改改demo测试下。
对不起,还没完……
鼠标跟随的实现
关键是理清前面的属性,最后的鼠标跟随转动效果通过js实现应该比较简单了,监听mousemove
事件,根据鼠标位置到3D元素的中心的距离
,除以
一定的系数
,实时改变元素的rotateX
和rotateY
的值来达到效果。你可以通过改变系数
的大小来控制转动的灵敏度
。
贴一下代码:
var o = $("#card");
$("#top").on("mousemove", function(t) {
var e = -($(window).innerWidth() / 2 - t.pageX) / 20,
n = ($(window).innerHeight() / 2 - t.pageY) / 10;
o.attr("style",
"transform: rotateY(" + e + "deg) rotateX(" + n + "deg);
-webkit-transform: rotateY(" + e + "deg) rotateX(" + n + "deg);
-moz-transform: rotateY(" + e + "deg) rotateX(" + n + "deg)"
)
})
THE END……能看到这里的人真是让俺感动啊~
养成好习惯,顺手打广告:这个动效用在了网易有数的首页。网易有数是一款敏捷数据分析平台,欢迎使用体验。
参考自: