更多的 CSS3 变形 (transformation)

在 Kayo 之前所写的一篇文章《CSS3的变形与过渡样式》中,曾经对 CSS3 的变形 (transformation) 和转换 (transition) 作出详细介绍,但关于变形的部分内容仍可以扩展说明一下,因此写了本文补充一下变形的相关内容。

在前文中,已经说明了 transform 属性的两个用法 rotate 和 scale ,分别用于对象的旋转和缩放,具体的内容可以阅读前文。而现在要补充说明的,是 transform 的另外 3 个方法,translate、skew 以及 matrix 。

这些方法都有 2D 和 3D 的方式,在这里 Kayo 首先说明 2D 情况下的效果,并以此为基础再拓展说明 3D 下的效果。

一. translate

translate 为指定对象的平移,具有两个参数,第一个为 x 轴方向平移,第二个为 y 轴方向平移。如果第二个参数未提供,则默认值为 0 。

例如,需要设置一个元素在鼠标悬停时进行 x 轴方向 30px 和 y 轴方向 20px 的平移,可以这样编写:

#translate-demo:hover {
	-webkit-transform: translate(30px, 20px);
	-moz-transform: translate(30px, 20px);
	-o-transform: translate(30px, 20px);
	-ms-transform: translate(30px, 20px);
	transform: translate(30px, 20px);
}

translate

也可以浏览 Demo(请使用 Chrome、Firefox、Safari 或 Opera 浏览,下同)。

这里必须说明一点,最新版本的主流现代浏览器(Kayo 测试的是 Chrome 22.0.1229.94 , Firefox 17.0.1 , Safari 5.1.7 , Opera 12.12)除 webkit 内核的 Chorme 和 Safari 外都不需要通过私有属性才能支持 transform 了,但由于早期的现代浏览器中 transform 属性都需要通过各自的私有属性支持,因此为了尽量兼容早期版本的浏览器,在实际项目中使用 transform 时最好使用各自的私有属性,同时为了向后兼容,需要加上没有私有属性的调用。

二. skew

skew 指定元素斜切扭曲,即元素围绕 x 轴和 y 轴进行倾斜,具有两个参数,第一个对应 x 轴方向的倾斜角度,第二个对应 y 轴方向倾斜角度。如果第二个参数未提供,则默认值为 0 。skew 与 scale 有点相似,但 scale 只旋转元素,不会对元素形状作出改变,而 skew 则会使到元素的形状发生改变。

例如,需要设置一个元素在鼠标悬停时进行 x 轴方向 30 度和 y 轴方向 30 度的斜切扭曲,可以这样编写:

#skew-demo:hover {
	-webkit-transform: skew(30deg, 30deg);
	-moz-transform: skew(30deg, 30deg);
	-o-transform: skew(30deg, 30deg);
	-ms-transform: skew(30deg, 30deg);
	transform: skew(30deg, 30deg);
}

skew

也可以浏览 Demo

值得注意的是,由于 translate、skew 以及上文提到的 scale 都是以 x、y 轴相关的值作为参数,因此为了方便起见,W3C 还提供了 translateX 和 translateY 、skewX 和 skewY 以及 scaleX 和 scaleY 方法,分别用于独立设置 x 轴和 y 轴方向上的效果。

三. matrix

matrix 即矩阵,这里具体使用的是一个 3*3 矩阵。

用矩阵表示属性值?

是的,除了 transform 外,CSS3 中另外还有一些属性以 matrix 作为属性值,实际上,matrix 是 transform 中最基本而又最强大的值,上面的 translate 和 skew 以及之前介绍过的 rotate 和 scale 在底层都是通过 matrix 实现的,因此实际上所有的 transform 值都可以通过一个 3*3 矩阵表示。

我们知道,transform 是在 x、y 坐标系上的 2D 变换,因此实际上变换就是元素上每一个点通过一个变换等式进行变化,再产生新的坐标值的过程。因此我们设置旧的 x、y 坐标值分别为 XprevCoordSys 和 YprevCoordSys ,新的 x、y 坐标值分别为 XnewCoordSys 和 YnewCoordSys ,由于变换在 2D 中进行,因此 z 坐标值设为 1 即可。这时再另设 matrix 为如下的一个矩阵,

Matrix

则旧的坐标值、新的坐标值与 matrix 中存在如下关系:

MatrixMultiply

即新旧值之间可以通过矩阵连成等式,因此开发者只需要设定好 matrix 的值,就可以写出自定义的变换了。接下来需要注意,虽然 matrix 是一个 3*3 矩阵,在实际使用时只需填写6个参数(另外3个与 x、y 轴无关),并且调用时需要用如下的顺序 [a b c d e f]

例如编写如下语句:

#matrix-demo:hover {
	-webkit-transform: matrix(1, 1, 0, 1, 0, 0);
	-moz-transform: matrix(1, 1, 0, 1, 0, 0);
	-o-transform: matrix(1, 1, 0, 1, 0, 0);
	-ms-transform: matrix(1, 1, 0, 1, 0, 0);
	transform: matrix(1, 1, 0, 1, 0, 0);
}

这样在鼠标悬停时元素会在 y 轴方向上拉伸(即相当于 skewY(45deg) 的效果)。

也可以浏览 Demo

另外如果同时使用两个或以上的 transform 方法,可以把它们合并书写。

四. 3D transformation

上面讨论的是 2D 下的 CSS3 变形,实际上有部分 transform 方法支持 3D 变形,包括 scale()、translate()、scale() 和 matrix() ,W3C 增加了一些附加方法实现 3D 效果,包括增加了相应的 3D 方法 scale3d()、translate3d()、scale3d() 和 matrix3d() ,这些方法的参数也增加了一个 “z” ,定义 z 方向的效果。定义变形中心的 transform-origin() 方法也增加了 z 参数,用于设置 z 方向上的变形中心。另外还增加了 scaleZ()、translateZ() 和 scaleZ() ,用于单独设置 z 方向上的效果。

值得一提的是,W3C 还为 3D transform 定义了 perspective() 方法和 transform-style() 方法。

transform-style() 方法用于设置元素的子元素是否参与 3D 变形,它具有两个可选值,flat 和 preserve-3d ,分别设置子元素不参与 3D 转换和子元素将显示在 3D 环境中。

perspective() 的作用则复杂很多,在说明 perspective() 的作用之前,我们首先说明一下 transform 产生 3D 效果的方式:

  • transform 使用透视方式,即近大远小的方式在视觉上产生 3D 效果。
  • 所有元素都是假设被放置在 z = 0 的平面上,我们直视屏幕的方向(镜头方向)只能是平行 z 轴向屏幕内,也就是从屏幕正前方向里看
  • 可以通过 transform-origin 调整镜头与元素所在平面的角度

视觉 3D 是通过镜头距离和角度的调整达到更加真实的效果,因此结合 transform 实现 3D 的方式,除了使用 transform-origin 调整镜头中心外,我们还需要一个方法调整镜头与元素所在平面的距离,这个就是 perspective() 方法。

从定义上讲,perspective() 定义了镜头到元素的距离;从 3D 的效果来说,它对于 3D 效果的真实程度具有重要的影响。

例如,我们要使元素在 y 轴方向旋转 90 度,添加 perspective() 前后的效果如下:

#threed-demo:hover {
	-webkit-transform: rotateY(75deg);
	-moz-transform: rotateY(75deg);
	transform: rotateY(75deg);
}

增加 perspective() 之后

#threed-perspective-demo:hover {
	-webkit-transform: perspective(300px) rotateY(75deg);
	-moz-transform: perspective(300px) rotateY(75deg);
	transform: perspective(300px) rotateY(75deg);
}

具体的变化请浏览 Demo (请使用 Chrome、Firefox 或 Safari ,如果发现没有效果,请升级浏览器版本)。

可以看出,增加 perspective(300px) 后 3D 的效果真实很多了。但是,3D 效果的浏览器支持情况仍旧很差,下面会详细说明。

另外 perspective 方法需要写在其他方法之前才会有效果,关于这一点 W3C 以及浏览器文档都没有声明原因,使用时按照这个顺序书写即可。

五. 浏览器兼容

这里分开说明 2D 和 3D transform 的浏览器支持情况。

1. 2D

translate()、skew()、matrix() 三个方法与在前文中说明的 transform 的浏览器兼容性相当。

兼容浏览器:Firefox 3.5+、Chrome 2.0+、Safari 3.1+、Opera 10.50+、IE9 (早期版本通过浏览器各自的私有属性支持)

另外最新版本的 Chorme 和 Safari 仍需通过私有属性支持,最新版本的 Opera 则仍不支持 rotateY 等独立属性。

2. 3D

3D 的支持情况则糟糕很多,除了 webkit 内核外,其他主流浏览器对于 3D transform 的支持都比较晚,即使是最新版本的几个主流现代浏览器(Chrome 22.0.1229.94 , Firefox 17.0.1 , Safari 5.1.7 , Opera 12.12),支持情况也不良好,具体如下:

IE 和 Opera 并不支持任何 3D transform 。

最新版本的 Chrome、Firefox、Safari 都已经支持 3D transform 的变换方法,并且无需私有属性。

最新版本的 Chrome、Firefox、Safari 需要通过各自的私有属性支持 perspective() 。

最新版本的 Chrome、Safari 需要通过各自私有属性支持 3D transform-origin ,Firefox 则无需使用私有属性。

六. 总结

可以看出,2D transform 已经在现代浏览器甚至新版本的 IE 中获得良好的支持,开发者不妨使用 2D transform 为网页元素添加一些渐进增强的效果,使用时若需要兼顾较低版本的现代浏览器,需要使用以下方式调用(以文章开头的 translate 为例):

#translate-demo:hover {
	-webkit-transform: translate(30px, 20px);
	-moz-transform: translate(30px, 20px);
	-o-transform: translate(30px, 20px);
	-ms-transform: translate(30px, 20px);
	transform: translate(30px, 20px);
}

若只需考虑较新版本的浏览器(实验性网站),只按以下方式调用即可:

#translate-demo:hover {
	-webkit-transform: translate(30px, 20px);
	transform: translate(30px, 20px);
}

而 3D transform 的浏览器支持情况并不良好,只建议用于实验性网站,并通过以下方式调用(以 perspective 的例子说明):

#translate-demo:hover {
	-webkit-transform: perspective(300px) rotateY(75deg);
	-moz-transform: perspective(300px) rotateY(75deg);
	transform: perspective(300px) rotateY(75deg); /* 往后兼容 */
}

但是,3D transform 仍可以有很大的作用,由于, Chrome 和 Safari 都对 3D transform 有着良好的支持,因此,同样使用 webkit 内核的 Android 4.0 和 iphone/ipad 的默认浏览器对 3D transform 也有着良好的支持,只要设计的效果能被移动设备负担,用 3D transform 做一些比较酷的 Web Apps 会是一个不错的选择。

本文由 Kayo Lee 发表,本文链接:http://kayosite.com/more-about-css3-transformation.html

评论列表

  • 评论者头像
    回复

    css3很炫啊,希望浏览器都赶快升级,我很喜欢旋转滚动效果 :mrgreen:

  • 评论者头像
    回复

    还是很少用css3来实现这些效果,懒+觉得麻烦

    • 评论者头像
      回复

      @zwwooooo 比起PS,CSS我更加熟练,所以有些效果就习惯用CSS3了!

  • 评论者头像
    回复

    demo最后2个貌似有点抽搐。。。chrome看的 :mrgreen:

    • 评论者头像
      回复

      @向日葵媒体设计 其实是因为旋转后图片的面积太小了,鼠标很容易就超出了图片,所以很容易感觉抽搐!自己写 Demo 时也觉得有点难操作!

  • 评论者头像
    回复

    文章看完后没有上一篇了和下一篇的链接还真不方便,每次都要返回目录列表,感觉很不爽!!!

  • 评论者头像
    回复

    3D matrix 都用了…強大了

    • 评论者头像
      回复

      @Kkstxforkamancerman 可惜浏览器支持度不高,开发者想用也有很多制约,不过还是个挺值得学习的功能!

回复

你正在以游客身份访问网站,请输入你的昵称和 E-mail
:wink: :roll: :oops: :mrgreen: :idea: :cry: :?: :-| :-o :-P :-? :) :( 8-O