css3 の 3D 変換を使用すると、平らな Web ページにクールな 3 次元の視覚効果を追加でき、とても快適です。
3D 変換は CSS の一部にすぎず、3D エンジンではないことに注意してください。 3 次元エンジンは一般に次のようになります (ゲーム エンジン Unity3D):
JavaScript 3D ライブラリ three.js を含めると、以下を含めて 3 次元エンジンと呼ぶことができます。 🎜>
3D 変換の 3 次元空間機能は不足していますが、それでも優れた 3 次元効果を作成できます。これには、私たち開発者が注意を払う必要があります。
以下のコンテンツを開始する前に、遠近法などの 3D 変換に関連する CSS プロパティについてまだ何も知らない場合は、以前に書いた CSS の 3D 変換に関する記事を読むことができます。
3D 変換の座標系
初期座標系): 各 DOM 要素には、このような初期座標系があります。このうち、原点は要素の左上隅に位置し、z 軸は観察者 (つまり、画面の外にいる私たち) を指します。初期座標系の Z 軸は 3 次元空間とは見なされませんが、Web ページ要素の描画順序を決定するための Z インデックスと同様に参照として使用され、後の描画順序の要素は前の要素を上書きします。描く順番で。
transform を使用する場合は状況が異なります。変換が参照するのは、初期の座標系ではなく、新しい座標系です:変換で使用されるこの座標系では、初期の座標系と比較して、x、y、z 軸の方向は残ります。原点位置は要素の正確な中心に移動されました。この座標系の原点を変更したい場合は、transform-origin を使用します。変換原点のデフォルト値は 50% 50% であるため、デフォルトでは、変換座標系の原点は要素の中心になります。
変換の順序
私たちは皆、transform のような複数の変換関数を使用することがあります。このとき、変換関数の順序に注意する必要があります。これは、各変換関数が要素を変更するだけでなく、その要素に関連付けられた変換座標系も変更するためです。変換関数が順番に実行される場合、後の変換関数は常に前の変換後の新しい変換座標系に基づくからです。
2 つの変換関数の順序を入れ替えると、効果は次のようになります:
変換ごとに座標系が変化するため、要素の最終的な位置も順序が異なると異なることがわかります。
これには別の説明があります。つまり、変換関数は数学的な行列の乗算によって完成され、行列の乗算は交換法則を満たさないということです。座標空間内の任意の変換関数または変換関数の組み合わせを行列に変換できます (この変換を支援する行列ガジェットもあります)。
3D オブジェクトの作成
前述したように、3D 変換は、3D エンジンのような 3D シーンを作成するための包括的なリソースを提供しません。したがって、3 次元オブジェクトを作成するという点では、Web ページの既存のコンテンツを使用し、自分で方法を見つけるしかありません。
実際、3D エンジンでは、3D オブジェクトは一連の平面 (ポリゴン) で囲まれています (そして、テクスチャやマップを平面に追加できます)。
立方体
今は遠近感を気にせず立方体を作りましょう。立方体には 6 つの側面があり、これら 6 つの側面を保持するために要素を使用する必要があるため、HTML は次のとおりです:
および対応する CSS は (側面の長さ 120px、ブラウザーのプライベート プレフィックスは省略されています) 、以下同様) :
<div class="cube"> <div class="surface surface-1">1</div> <div class="surface surface-2">2</div> <div class="surface surface-3">3</div> <div class="surface surface-4">4</div> <div class="surface surface-5">5</div> <div class="surface surface-6">6</div></div>
このうち、transform-style:preserve-3d; は、すべての子要素が同じ 3 次元空間にあることを保証します (ここでは 3 次元レンダリング コンテキスト 3D)これは、単一要素の単純な 3D 効果だけでなく、これらの要素を使用して 3D シーンを作成したいことをブラウザに伝えることを意味します。
position: absolute;是一个习惯做法,因为三维物体并不符合一般平面网页内容的排版,所以我们会比较多地希望它不要占据布局空间。
6个面位置都不一样,但却都有 translateZ(60px);,你已经知道这是因为巧妙搭配了在它之前的变换函数。
一旦构成正方体的6个 div.surface的位置确定后,就可以操作它们的父元素 div.cube来整体移动、旋转这个正方体。
只是有了这样的一个三维物体,我们就可以说有了一个三维场景了。但是,三维场景和平面图不同,比如这个正方体,我从不同的位置,不同的角度去观察它,我眼里看到的都是不一样的:
那么,这样的三维场景要如何呈现在平面的网页里呢?
这就是三维引擎里的摄像机的概念来源了。就像电影里表现同一个场景会用不同的镜头那样,我们需要定义场景里的摄像机来生成最终呈现在屏幕里的二维画面。比如three.js里的摄像机是这样的感觉:
这个图里标明的是摄像机定义时使用的参数,其中包括视野范围,图像宽高比等。可以感受到还是有很多内容的。
相比之下,网页里的三维场景摄像机就弱多了,你需要用的是 perspective和 perspective-origin。
perspective定义摄像机(也就是作为观众的我们)到屏幕的距离, perspective-origin定义摄像机观察到的画面中的灭点(vanishing point)的位置。虽然它们并不能方便地让你直接定义摄像机的位置和观察角度等,但只要适当地应用它们,是可以一定程度上控制摄像机的画面效果的。
网页里的摄像机一般是这样用的:
<div class="camera"> <div class="cube1"></div> <div class="cube2"></div> <!-- more 3d objects... --></div>
.camera{ position: relative; perspective: 1200px; perspective-origin: 50% 50%; transform-style: preserve-3d;}
在网页里,无论你搭建了怎样的三维场景,只要你希望它显示出来,就应该像这样把构成场景的三维物体都放在一个容器元素里,然后为容器元素添加摄像机属性( perspective和 perspective-origin)。
此外,还需要注意添加 transform-style: preserve-3d;以保证多个三维物体都位于同一空间(这样才有三维引擎的味道,对吧?)。
下面这个场景里有三个正方体,然后摄影师正在做弹跳练习(限支持3d transform的浏览器):
http://runjs.cn/detail/daqoq5tf
这段动作的动画代码是这样:
.camera{ animation: cameraMove 2s ease-out infinite alternate both;}@keyframes cameraMove{ 0%{ perspective-origin: 50% 180px; } 100%{ perspective-origin: 50% -200px; }}
可以看出, perspective-origin虽然是指三维透视的灭点的位置,但它的确和我们理解的摄像机的位置是紧密关联的。如果摄像机在空间里的位置是 (x, y, z)的话, perspective-origin的两个值有一点像指定 x和 y的感觉。这里只说“有一点像”,是因为灭点位置和摄像机的位置毕竟是不同的概念,这可能还需要多看一些三维空间来体会。
那么,在上面的例子中,摄影师不只是这样跳起来,而是想要向更深处前进,应该怎么做呢?
答案是,在网页里,你不能这样移动摄像机,你需要换一个思路,参照相对运动的关系,改为让整个三维场景向你移动。不过,说到这里,前面提到的摄像机的另一个属性, perspective,为什么它不行呢?
perspective代表摄像机距离屏幕的距离,看上去和z轴深度非常近似。但是,它并不等同于摄像机的 z坐标位置( perspective还只能取正值),而是会影响摄像机本身的其他属性。下面用这个图说明 perspective的值变化的效果(修改自w3c的配图):
图中 d1和 d2分别表示两个不同的 perspective的值,其中 d2小于 d1。然后,你会惊奇地发现,一个原本位于屏幕之后( z坐标为负值)的物体,竟然是随着“走近”而变得更小了!显然,这不符合我们在三维空间里运动的基本感受。其原因是,网页的三维投影平面是固定的, perspective在改变摄像机的位置的同时,也同时改变了摄像机本身的其他属性(类似前面的three.js的摄像机那张图里的各种参数)。
所以,一般来说, perspective应维持一个固定的值。想要用3d transform做出在三维空间里自由移动的效果(就像各种3d游戏),应该通过相对运动的方法实现。
transform影响的是视觉渲染,而不是布局。因此,除以下情况外,transform不会影响到布局:
这个因为 overflow生成滚动条从而影响布局的反例,也发生于 position: relative;再进行偏移的情况。
translate3d() などの空間位置を変更する変換関数と比較すると、CSS の元の位置属性 left や top は、状況は複雑になります。
これに関して、より推奨される分析方法があります。実際には、3 次元空間内の位置に関する限り、従来の属性 left、top、さらには margin-left が有効です。効果は 1 つだけです。それは、要素の初期位置を変更し、それによって要素の変換原点の位置を変更することです。その後、3 次元空間での変換が後で有効になり、引き続き変更が行われます。前の変換原点に基づく位置。
これで、遠近原点はカメラのプロパティであり、遠近イメージの消失点を定義する一方、変換原点はカメラのプロパティであることを学びました。原点は任意の要素に存在し、要素の変換座標系の原点を定義します。
この記事は、Web ページ上に 3 次元空間を作成するために私が現在使用している 3D 変換の概要をまとめたもので、3 次元エンジンに関する知識が組み込まれており、それらを 1 つずつ説明しています。比較を通じて。 3D 変換は、3D エンジンと比較すると非常に粗雑ですが、Web ページに魅力的な 3D 効果を追加するには十分です。
3D 変換を使用して、もう少し複雑な 3 次元空間を作成したいと考えている場合は、この記事が役立つことを願っています。
(ブログを再編集、元のアドレス: http://acgtofe.com/posts/2015/12/xyz-3d-in-css/)