利用CSS实现3D效果

css主要利用transform-style:preserve-3d实现3D效果。

一个平面图形,通过增加三位空间变量Z轴可以实现视觉上的立体效果。

不管实现多复杂、多巧妙3D效果,我们要做一定是先处理二维空间的基本变换,之后再将它准确的“推”三维空间应在的位置去。

一 立方体

实现一个立方体也是这样,首先将6方体的6个面旋转到合适的位置,最后将它“推”到空间中。

实现代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CSS3D - 立方体</title>
    <style>
        .view{
            width: 200px;
            height: 200px;
            margin: 50px auto;
        }
        .container{
            transform-style: preserve-3d;
            transform-origin: 100px 100px;
            perspective-origin: center;
            animation-name: animation;
            animation-timing-function: ease-in-out;
            animation-iteration-count: infinite;
            animation-duration: 3s;
        }

        .box{
            width: 200px;
            height: 200px;
            line-height: 200px;
            text-align: center;
            font-size: 120px;
            color: white;
            border: 5px solid #666;
            background: hsla( 40, 100%, 50%, 0.8);
            position: absolute;
        }
        .box:nth-child(1){
            transform: translateZ(100px);
        }
        .box:nth-child(2){
            transform: translateZ(-100px);
        }
        .box:nth-child(3){
            transform: rotateX(90deg) translateZ(100px);
        }
        .box:nth-child(4){
            transform: rotateX(-90deg) translateZ(100px)
        }
        .box:nth-child(5){
            transform: rotateY(90deg) translateZ(-100px);
        }
        .box:nth-child(6){
            transform: rotateY(-90deg) translateZ(-100px);
        }
        @keyframes animation {
            16%{transform: rotateY(-90deg)}
            33%{transform: rotateY(-90deg) rotateZ(135deg)}
            50%{transform: rotateY(225deg) rotateZ(135deg)}
            66%{transform: rotateY(135deg) rotateZ(135deg)}
            83%{transform: rotateX(135deg)}
        }
    </style>
</head>
<body>

    <div class="view">
        <div class="container">
            <div class="box">A</div>
            <div class="box">B</div>
            <div class="box">C</div>
            <div class="box">D</div>
            <div class="box">E</div>
            <div class="box">F</div>
        </div>
    </div>

</body>
</html>

这里最重要的代码就是每个面的变形。

每个面以图形中心点为变形中心,除了前、后面只需要在三维的空间中前后移动位置外,左右、面需绕Y轴、上下面需绕轴X轴旋转后再推入空间中。

      .box:nth-child(3){
            transform: rotateX(90deg) translateZ(100px);
       }

如上述代码,rotateX表示旋转,请注意旋转后该平面的坐标轴位置已经发生了变化,此时该平面的Z轴已成为我们页面上的水平方向。

3D轮播图

立方体虽然已经呈现了立体效果,使用场景非常有限,因为它不符合人类的习惯。

人眼呈像近大远小,符合人的视觉习惯才会觉得逼真,3D轮播图的效果就更好一点。

在这里,我们加入了perspective的值,它设置了人眼到图形的观察距离,自动帮我们呈现符合我们习惯的视觉效果。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3D - 轮播图</title>
    <style>
        .view{
            perspective: 1000px;

        }
        .container{
            width: 210px;
            height: 120px;
            font-size: 80px;
            color: white;
            text-align: center;
            transform-style: preserve-3d;
            margin: 0 auto;

            animation: animation 10s linear infinite;
        }
        .box{
            width: 200px;
            height: 110px;
            line-height: 120px;
            position: absolute;
            border: 5px solid #000;
            top: 100px;
        }
        .box-1{
            background: hsla(  0, 100%, 50%, 0.8);
            transform: rotateY(0deg) translateZ(288px);
        }
        .box-2{
            background: hsla( 40, 100%, 50%, 0.8);
            transform: rotateY(40deg) translateZ(288px);
        }
        .box-3{
            background: hsla( 80, 100%, 50%, 0.8);
            transform: rotateY(80deg) translateZ(288px);
        }
        .box-4{
            background: hsla(120, 100%, 50%, 0.8);
            transform: rotateY(120deg) translateZ(288px);
        }
        .box-5{
            background: hsla(160, 100%, 50%, 0.8);
            transform: rotateY(160deg) translateZ(288px);
        }
        .box-6{
            background: hsla(200, 100%, 50%, 0.8);
            transform: rotateY(200deg) translateZ(288px);
        }
        .box-7{
            background: hsla(240, 100%, 50%, 0.8);
            transform: rotateY(240deg) translateZ(288px);
        }
        .box-8{
            background: hsla(280, 100%, 50%, 0.8);
            transform: rotateY(280deg) translateZ(288px) ;
        }
        .box-9{
            background: hsla(320, 100%, 50%, 0.8);
            transform: rotateY(320deg) translateZ(288px);
        }

        @keyframes animation {
            100%{
                transform: rotateY(360deg);
            }
        }
    </style>
</head>
<body>
    <div class="view">
        <div class="container">
            <div class="box box-1">1</div>
            <div class="box box-2">2</div>
            <div class="box box-3">3</div>
            <div class="box box-4">4</div>
            <div class="box box-5">5</div>
            <div class="box box-6">6</div>
            <div class="box box-7">7</div>
            <div class="box box-8">8</div>
            <div class="box box-9">9</div>
        </div>
    </div>

</body>
</html>

我们选择从上向下看,在拥有了上帝视角之后很明显会看到这是一个正多边形组成的立方体。

上图多边形的每条变是我们每个图形的长,总共有9张图,得到每张图的旋转角度是360/9 = 40,通过上图右三角星所示意我们可以可以得到Z轴应该“推”开的距离是288。

沉浸式3D效果

旋转的轮播图加上交互手势确实给我们带来了实实在在的真实感,但是这还不够,它像天边的云看得见摸不着,总有隔靴搔痒之感。

人们更喜欢身临其境的沉浸式体验,如果我们能“进入”我们自己缔造的3D世界,不就可以沉底沉浸其中了么。

第一个想通这事的人他可真是个小精灵鬼!

实现很简单,但是这个想法是真是大胆又高超,我们只需要在上个轮播图的基础上,把自己“拽”到空间中央看图,就可以被3D环绕。

我们就是搬了个马扎,进入到了图形中间找了个地方坐下了而已,不信你看:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3D - 轮播图</title>
    <style>
        .view{
            perspective: 500px;
            transform: translateZ(715px);

        }
        .container{
            width: 200px;
            height: 120px;
            font-size: 80px;
            color: white;
            text-align: center;
            transform-style: preserve-3d;
            margin: 100px auto;

            /*这个观赏距离是我自己找的  你大可以再往胡乱挪挪 爱坐哪坐哪*/
            transform:  translateZ(250px) rotateY(0deg);

            animation: animation 10s linear infinite;
        }
        .box{
            width: 200px;
            height: 110px;
            line-height: 120px;
            position: absolute;
            border: 5px solid #000;
        }
        .box-1{
            background: hsla(  0, 100%, 50%, 0.8);
            transform: rotateY(0deg) translateZ(288px);
        }
        .box-2{
            background: hsla( 40, 100%, 50%, 0.8);
            transform: rotateY(40deg) translateZ(288px);
        }
        .box-3{
            background: hsla( 80, 100%, 50%, 0.8);
            transform: rotateY(80deg) translateZ(288px);
        }
        .box-4{
            background: hsla(120, 100%, 50%, 0.8);
            transform: rotateY(120deg) translateZ(288px);
        }
        .box-5{
            background: hsla(160, 100%, 50%, 0.8);
            transform: rotateY(160deg) translateZ(288px);
        }
        .box-6{
            background: hsla(200, 100%, 50%, 0.8);
            transform: rotateY(200deg) translateZ(288px);
        }
        .box-7{
            background: hsla(240, 100%, 50%, 0.8);
            transform: rotateY(240deg) translateZ(288px);
        }
        .box-8{
            background: hsla(280, 100%, 50%, 0.8);
            transform: rotateY(280deg) translateZ(288px) ;
        }
        .box-9{
            background: hsla(320, 100%, 50%, 0.8);
            transform: rotateY(320deg) translateZ(288px);
        }

        @keyframes animation {
            100%{
                transform: translateZ(250px) rotateY(360deg);
            }
        }
    </style>
</head>
<body>
    <div class="view">
        <div class="container">
            <div class="box box-1">1</div>
            <div class="box box-2">2</div>
            <div class="box box-3">3</div>
            <div class="box box-4">4</div>
            <div class="box box-5">5</div>
            <div class="box box-6">6</div>
            <div class="box box-7">7</div>
            <div class="box box-8">8</div>
            <div class="box box-9">9</div>
        </div>
    </div>

</body>
</html>

能否能更加天衣无缝的呈现身临其境之感,还需要图形拉满屏幕、需要尽可能多的图片减少多面体每个边的弧度、需要良好的人机交互体验等等。

上述理解起来不太难,但真想写的得心应手、深刻理解,需要不断练习和思考,共勉~

-------end-------

编辑于 2021-05-16 15:02