CSS3 3D转换入门篇

概述

为了对CSS3中的3D transform 有个基本概念,首先我们来看个Demo,由四个DIV经过3D转换而来。可以通过上下左右键来改变视角方向,+ — 键来改变视角深度。

    http://followyourheart.sinaapp.com/Demos/css3_3d_transform.html
上面的Demo简单地演示了由4个div组成的空间形状,说到3D转换,最重要的是先要有坐标概念。传统2D页面中,我们知道坐标轴的大致方向如下:

在3D转换中我们常常会将袁绍向某个方向移动,或者绕某个轴旋转,其中大致的坐标系如下:

这个是3D转换的核心,下面我们再来看看相关的CSS语法与一些概念。

重要属性

perspective 与 perspective-origin

透视这一说法对于大部分刚接触的人来说确实有点云里雾里,这个属性是规定其子元素被查看的位置。打个比方,就是说假如屏幕显示的图像是一个摄像机距离其“perspective”的距离拍摄出来的。同时只要该属性值大于0,该元素的子元素即呈现被现实中3D的效果。不理解?看看下面的对比图


图中都是一大一小两个DIV,小DIV嵌套在大的里面。两图中的黄色DIV均沿X轴方向旋转了45度(至于旋转的过程,请参考之前提到的坐标轴自行脑补),但是明显第一幅图中黄色DIV只是宽度变小而已,准确来说像是投影,而第二副图却呈现出了3D的视觉效果。两者最大的区别在于“深度”,这也就是perspective属性所起的作用。外层的DIV通常我们会给它一个视角的距离与位置。

perspective 设置视角距离,perspective-origin 设置视角的偏移量默认值为perspective-origin: 50% 50%;说到这两个属性,我们首先必须要有个舞台的概念,所有3D的元素均处于舞台之中,这两个属性是设置在舞台上,来表示观看者的位置。

transform-style

这是我认为非常重要的一个属性,这是设置在3D元素上,表示它的子元素是否保留其3D转换,虽然它的作用看起来很好理解。基本用法是给某个3D元素设置transform-style: preserve-3d后,其子元素也具有3D效果。若设置为flat,这其子元素类似于投影的方式显示在父元素表面。给个对比图:

 

左侧transform-style: preserve-3d,右侧为transform-style: flat。三个DIV的关系为外层为舞台,需要指定perspective属性,内部均为3D元素,红色DIV由于其包含子元素,所以需要指定其子元素黄色DIV的显示方式。

关于TRANSFORM-STYLE的特殊用法 

还是看图做对比,找茬中去真正去理解。下图是文章一开始Demo中的内容。

    

左图中,我定义了一个“舞台”DIV,在其内部放置了四个相同大小的DIV,再将这些子DIV进行3D转换(移动与旋转),结果出现了左图这种看不明白的视图。仔细一看你会发现,下方的DIV遮住了左侧的DIV,然而左侧被遮住的部分本应该出现在前面。这就涉及到显示的优先级问题,大家都知道z-index的概念,z-index越大,就显示在越前面。从左图我们明显可以发现底部蓝色DIV的z-index是要比左侧红色DIV大的,但是这并不符合我们现实中的认知。

所以这里要用到transform-style属性,这个属性加在"舞台"上可以吗?答案是否定的,因为前面我提到过,这个属性是加在3D元素上的,所谓3D元素,本质就是舞台的子元素,所以我们需要再定义一个DIV容器,给其添加  transform-style: preserve-3d 属性,然后将四个DIV放入这个容器,这样这四个DIV就会以现实中的视距来决定内容先后顺序,而不是z-index。

 转换:

前面这些奇怪的属性介绍完了,我们就要开始转换了。转换用到一个属性 transform,使用方法为

transform: translateX(-100px) translateY(-100px) rotateX(90deg) rotateY(90deg);

注意空格,意思为沿x轴反向移动100px,向y轴反向移动100px,绕x轴旋转90度,绕Y轴旋转90度。这便是最常用的转换。更多API请参考:

http://www.w3school.com.cn/css3/css3_3dtransform.asp

以下是文章一开始提到的demo的源码,下一篇博客我会介绍一些更实用的用法与场景。

 

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Web 3D 入门</title>
</head>
<style>
    .stage {
        position: absolute;
        left: 50%;
        top: 50%;
        margin: -200px -200px;
        width: 400px;
        height: 400px;
        perspective: 500px;
        perspective-origin: 10% 10%;
    }

    .container {
        transform-style: preserve-3d;
    }

    .container div {
        position: absolute;
        width: 200px;
        height: 200px;
        color: white;
        border: solid #ffef4c 2px;
        font-size: 100px;
        word-break: break-all;
    }

    .description {
        text-align: center;
        color: #7e2015;
    }

    #floor {
        transform: rotateX(90deg);
        background-color: lightseagreen;
    }

    #wall_left {
        transform: translateX(-100px) translateY(-100px) rotateX(90deg) rotateY(90deg);
        background-color: #b23239;
    }

    #wall_right {
        transform: translateX(100px) translateY(-100px) rotateX(90deg) rotateY(90deg);
        background-color: #12b21b;
    }

    #top {
        transform: translateY(-200px) rotateX(90deg);
        background-color: #a65efe;
    }
</style>
<body>
<div class="description">
    <h1>Use directiion keys to change your position and "+" "-" to change your distance.</h1>
</div>

<div class="stage">
    <div class="container">
        <div id="wall_left">Hello</div>
        <div id="floor">World</div>
        <div id="wall_right">Hello</div>
        <div id="top">World</div>
    </div>
</div>
<script>
    var LEFT = 37, RIGHT = 39, UP = 38, DOWN = 40, PLUS = 187, MINUS = 189,
            container = Q(".stage")[0],
            perspective = 500, originX = 10, originY = 10;
    document.addEventListener("keydown", function (event) {
        switch (event.keyCode) {
            case LEFT:
                originX -= 10;
                break;
            case RIGHT:
                originX += 10;
                break;
            case UP:
                originY -= 10;
                break;
            case DOWN:
                originY += 10;
                break;
            case PLUS:
                perspective -= 50;
                break;
            case MINUS:
                perspective += 50;
        }
        perspective = perspective < 50 ? 50 : perspective;
        container.style.perspective = perspective + "px";
        container.style["perspective-origin"] = originX + "% " + originY + "%";
    });

    function Q(selector) {
        if (selector.charAt(0) == "#") {
            return document.getElementById(selector.slice(1, selector.length));
        }
        if (selector.charAt(0) == ".") {
            return document.getElementsByClassName(selector.slice(1, selector.length));
        }
    }
</script>
</body>
</html>






  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值