写这篇文章的原因是由于看到了这个页面:css
运用 CSS3 完成的 3D 视角,虽然有一些晕3D,可是令人置身于其中的交互体验感受很是棒,运用在移动端制做一些 H5 页面可谓十分博人眼球。git
而且掌握原理以后制做起来也并不算废力,好好的研究了一番后将一些学习过程共享给你们。github
下面进入正文:(一些 Gif 图片较大,须要等待一会)app
百闻不如一见,先直观感觉一下上述我所说的效果:ide
最好能点进去看看,这里我使用了带背景色的 div 做为示例,咱们的视角处于一个正方体中,正方体的旋转动画让咱们有了 3D 的感受。函数
那么本来的图长什么样呢?咱们把距离拉远,一探究竟:布局
是长这样的:学习
相较于第一种效果,其实所作的只是将咱们的视角推动到了正方体当中,有了一种身临其景的感受。动画
而合理的运用 CSS3 所提供的一些 3D 属性,很容易就能达到上述的效果。
制做这样一个 3D 图形,我在以前的文章已经很详细的讲述了过程,感兴趣的能够戳进去看看:
再简单复述一下,主要是运用到了两个 CSS 属性:
要利用 CSS3 实现 3D 的效果,最主要的就是借助 transform-style 属性。
transform-style 只有两个值能够选择:
// 语法: transform-style: flat|preserve-3d; transform-style: flat; // 默认,子元素将不保留其 3D 位置 transform-style: preserve-3d; // 子元素将保留其 3D 位置。
当父元素设置了 transform-style:preserve-3d 后,就能够对子元素进行 3D 变形操做了,3D 变形和 2D 变形同样能够,使用 transform 属性来设置,或者能够经过制定的函数或者经过三维矩阵来对元素变型操做:当咱们指定一个容器的 transform-style 的属性值为 preserve-3d 时,容器的后代元素便会具备 3D 效果,这样说有点抽象,也就是当前父容器设置了 preserve-3d 值后,它的子元素就能够相对于父元素所在的平面,进行 3D 变形操做。
使用 translateX(length) 、translateY(length) 、 translateZ(length) 来进行 3D 位移操做,与 2D 操做同样,对元素进行位移操做,也能够合并为 translate3d(x,y,z) 这种写法;
使用 scaleX() 、scaleY() 、scaleY() 来进行3D 缩放操做,也能够合并为 scale3d(number,number,number) 这种写法;
使用 rotateX(angle) 、rotateY(angle) 、rotateZ(angle) 来进行 3D 旋转操做,也能够合并为 rotate3d(Xangle,Yangle,Zangle) 这种写法。
// 语法 perspective: number|none;
简单来讲,当元素没有设置 perspective 时,也就是当 perspective:none/0 时全部后代元素被压缩在同一个二维平面上,不存在景深的效果。perspective 为一个元素设置三维透视的距离,仅做用于元素的后代,而不是其元素自己。
而若是设置 perspective 后,将会看到三维的效果。
咱们上面之因此可以在正方体外围看到正方体,以及深刻正方体内,都是由于 perspective
这个属性。它让咱们可以选择推动视角,仍是远离视角,所以便有了 3D 的感受。
为了完成这样一个效果,须要一个灵活的布局,去控制整个 3D 效果的展现。
下面是我以为比较好的一种方式:
<!-- 最外层容器,控制图形的位置及在整个页面上的布局--> <div class="container"> <!-- 舞台层,设置 preserve-3d 与 perspective 视距 --> <div class="stage"> <!-- 控制层,动画的控制层,经过这一层能够添加旋转动画或者触摸动画 --> <div class="control"> <!-- 图片层,装入咱们要拼接的图片 --> <div class="imgWrap"> <div class="img img1"></div> <div class="img img2"></div> <div class="img img3"></div> <div class="img img4"></div> </div> </div> </div> </div>
container
,控制图形的位置及在整个页面上的布局;stage
层,舞台层,从这里开始设置 3D 景深效果,添加 perspective 视距;control
层,动画的控制层,经过这一层能够添加旋转动画或者在移动端的触摸动画,经过更改translateZ
属性也能够拉近拉远视角;imgWrap
层,图片层,装入咱们要拼接的图片,下文会说起。图片拼接其实才是个技术活,须要许多的计算。
以上述 Demo 中的正方体为例子,class 为 img
的 div 块的高宽为 400px*400px。那么要利用 4 个 这样的 div 拼接成一个正方体,须要分别将 4 个 div 绕 Y 轴旋转 [90°, 180°, 270°, 360°],再 translateY(200px)
。
值得注意的是,必定是先旋转角度,再偏移距离,这个顺序很重要。
看看俯视图,也就是这个意思:
这是最简单的状况了,都是直角。
若是是一张图须要分割成八份,假设每张图分割出来的高宽为 400 400 , 8 张图须要作的操做是依次绕 Y 轴旋转 [45°, 90°, 135°, 180°, 225°, 270°, 315°, 360°] ,偏移的距离为 translateY(482.84px)
,也就是 (200 + 200√2)。
看看俯视图:
效果图:
上面的示例都是使用的带背景色的 div 块,如今咱们选取一张真正的图片,将其拼接成一个柱体。
下面这张图,大小为 3480px * 2000px
:
咱们把它分割为 20 份,拼成一个正 20 边形,固然不用一块一块切图下来,利用 background-position
就能够完成了。并且分割的份数越多,最终作出来的效果越像一个圆柱,效果也更加真实。
正 20 边形,须要 20 个 div ,假设容器是 .img-bg1 ~ .img-bg20 ,那么每块图片的宽度为 174px
,依次须要递增的角度为 18° ,而且咱们须要计算出须要偏移的距离为 translateZ(543px)
。
能够利用一些 CSS 预处理器处理这段代码,下面是 Sass 的写法:
// Sass 的写法 $imgCount : 20 !default; @for $i from 1 through $imgCount { .img-bg#{$i}{ background-position:($i * -174px + 174px) 0; transform: rotateY($i * 18deg) translateZ(543px); } }
看看效果: Demo能够戳这里
能够看到,图中近视为一个圆柱形,不过有一些小问题:
control
层,进入到圆柱画面内作到这一步,只剩下最后一步,就是推动咱们的视角,进入到圆柱内部,产生 3D 视图的感受。
咱们经过 class 为 control
这个 div 控制这个效果,不过这里控制咱们进入圆柱内部的属性不是调整修改 perspective
属性,而是调整 translateZ
属性。经过控制 translateZ 获得的画面更加真实,能够本身尝试一下分别控制 perspective
与 translateZ
获得的效果,便会有深入的感觉。
最后的效果: Demo能够戳这里,因为是移动端效果,打开模拟器观看更佳
整个效果图太大,只截取了部分制做成 GIF:
还有一个小问题,那就是进入到圆柱内部以后,整个图片都反了过来,因此咱们可能须要利用PS将原图进行一次左右翻转,这样进入内部以后,看到的就是原图效果。
至此,整个页面就算完工了,接下来的就是添加一些 touch 事件,增添一些细节。可能写的过程当中遗漏了一些细节,有什么很难一下理解过来的地方能够在评论留言。
本文示例 Demo 已上传在个人 Github 上:
到此本文结束,若是还有什么疑问或者建议,能够多多交流,原创文章,文笔有限,才疏学浅,文中如有不正之处,万望告知。