이 글을 쓴 이유는 이 페이지를 봤기 때문입니다:
클릭해서 살펴보세요(모바일 페이지, 시뮬레이터를 사용하여 시청하세요)
CSS3를 사용하여 얻은 3D 관점은 비록 약간의 3D 흐림이 있지만 사람들을 몰입하게 만드는 인터랙티브 경험을 모바일 측에서 일부 H5 페이지를 만드는 데 사용하는 것은 매우 눈길을 끕니다. .
그리고 원리를 터득한 후에는 만드는 노력이 헛되지 않습니다. 주의 깊게 연구한 후 몇 가지 학습 과정을 여러분과 공유하겠습니다.
아래 텍스트를 입력하세요: (일부 Gif 사진은 크기가 더 크므로 잠시 기다려야 합니다.)
보는 것이 듣는 것보다 먼저 위에서 말씀드린 효과를 직관적으로 느껴보겠습니다.
클릭해서 살펴보는 것이 가장 좋습니다. 여기서는 배경색이 있는 div를 예로 사용합니다. 우리의 관점은 큐브에 있고 큐브의 회전 애니메이션은 3D 느낌을 줍니다.
그럼 원본 사진은 어떤가요? 화면을 축소하여 살펴보겠습니다.
은 다음과 같습니다.
첫 번째 효과와 비교하면 실제로는 우리의 관점을 큐브 안으로 밀어넣어 몰입감을 주는 것입니다.
CSS3에서 제공하는 일부 3D 속성을 합리적으로 사용하면 위의 효과를 쉽게 얻을 수 있습니다.
이러한 3D 그래픽을 만드는 과정은 이전 기사에서 자세히 설명했습니다. 관심이 있으시면 클릭하여 살펴보세요.
【CSS3 Advanced】멋진 3D 회전 시점
간단히 다시 말하면 두 가지 CSS 속성이 주로 사용됩니다.
CSS3를 사용하여 3D 효과를 얻으려면 가장 중요한 것은 변환 스타일 속성을 사용하는 것입니다.
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); } }
효과 보기: 여기에서 데모를 클릭할 수 있습니다.
보시다시피 사진 속 근거리 모습은 원통형이지만, 약간의 문제가 있습니다.
control
레이어를 제어하고 원통형 화면으로 들어갑니다이 단계 이후 남은 마지막 단계는 관점을 발전시켜 원통 내부로 들어가 3D 뷰의 느낌을 만드는 것입니다.
클래스를 통해 control
div에 대해 이 효과를 제어하지만 여기서 실린더에 들어가도록 제어하는 속성
은 perspective
속성을 수정하도록 조정되지 않습니다. translateZ
속성을 조정하려면 TranslateZ를 제어하여 얻은 그림은 perspective
및 translateZ
를 각각 제어하는 효과를 시도해 볼 수 있으며 깊은 느낌을 갖게 됩니다.
최종 효과: 데모는 여기를 클릭하면 볼 수 있습니다. 모바일 버전이므로 시뮬레이터를 열어서 보는 것이 좋습니다.
전체 렌더링이 너무 커서 일부만 잘라서 GIF로 만들었습니다.
또 다른 작은 문제가 있습니다. 즉, 원통 내부에 들어가면 전체 그림이 뒤집어지기 때문에 PS를 사용하여 원본 그림을 좌우로 뒤집어야 할 수도 있습니다. 내부로 들어가면 원본 이미지 효과가 보입니다.
이제 전체 페이지가 완성되었습니다. 다음 단계는 터치 이벤트를 추가하고 세부 정보를 추가하는 것입니다. 작성 과정에서 누락된 부분이 있을 수 있으니, 단번에 이해하기 어려운 부분이 있다면 댓글로 남겨주시면 됩니다.
이 기사의 샘플 데모가 내 Github에 업로드되었습니다:
Css33DView
아직 궁금한 점이나 제안사항이 있으면 더 많은 내용을 소통할 수 있습니다. 글의 내용이 제한되어 있고 잘못된 부분이 있으면 이 글을 마치겠습니다. 기사로 알려주세요.