【譯】box-shadow美化3D轉換效果

在線預覽 下載源碼程序員

當使用 3D 轉換來對元素進行格式化的時候,您可能會注意到它們沒有任何陰影而且看起來很是平坦。 在現實生活中,物體會阻擋光線併產生陰影。 物體表面多是啞光,反光,或者介於二者之間。因此,咱們能夠作得更好。後端

若是你須要將光線投射到複雜的幾何體上,能夠選擇Photon等引擎,但它們處理器很是複雜。 在本文中,我將向您展現一個能夠應用於只有幾個面的元素的解決方案。 咱們的例子將是一個帶有光澤海報的3D電影畫廊,當海報旋轉時,兩側將包含電影的相關介紹。瀏覽器

HTML結構

咱們的頁面將有幾個不一樣的部分。 首先,咱們須要一個簡單的父元素來居中頁面上的全部內容。 接下來,咱們將建立一個包含全部3D海報的無序列表。 咱們給ul添加類「stage」,給每一個li添加類「scene」。 在咱們的CSS中,ul將充當全部li元素的容器,每一個li元素會設置perspective屬性用於構成透視圖。bash

<div class="wrapper">
  <ul class="stage">
    <li class="scene"></li>
    <li class="scene"></li>
    <li class="scene"></li>
  </ul> 
</div>

複製代碼

對於每一個li,咱們須要添加至關多的子元素。 這將包含咱們的電影海報以及每部電影的全部相關介紹。 在一個更強大的電影庫中,這可使用一些後端代碼動態完成。 出於本示例的目的,咱們將保持簡單。app

<li class="scene">
  <div class="movie">
    <div class="poster"></div>
    <div class="info">
      <header>
        <h1>It's a Wonderful Life</h1> <span class="year">1946</span> <span class="rating">PG</span> <span class="duration">130 minutes</span> </header> <p> In Bedford Falls, New York on Christmas Eve, George Bailey is deeply troubled. Prayers for his well-being from friends and family reach Heaven. Clarence Odbody, Angel Second Class, is assigned to visit Earth to save George, thereby earning his wings. Franklin and Joseph, the head angels, review George's life with Clarence.
      </p>
    </div>
  </div>
</li>

複製代碼

咱們的畫廊將包含至少兩部電影。 元數據有點冗長,還有一些您須要的圖像資源,但全部內容都包含在下載的代碼中。 讓咱們開始寫相關的CSS部分。post

CSS樣式

請注意,示例CSS不包含任何瀏覽器前綴,但您能夠在下載的文件中找到它們。動畫

首先,讓咱們作一些基本的操做。 咱們須要將咱們的父元素居中,而後刪除默認的列表樣式。網站

.wrapper {
	margin: 0 auto 100px auto;
	max-width: 960px;
}

.stage {
	list-style: none;
	padding: 0;
}
複製代碼

接下來,咱們將給.scene類設置明確的寬度和高度(與咱們的海報相同)。 若是您想在高分辨率顯示器上有更好的視覺效果,那麼您可使用兩倍大的圖像。ui

每一個.scene類之間將提供足夠大的外邊距,使得它們不會彼此重疊。 而後咱們將設置全部列表項浮動到左側,以便它們在一行中彼此相鄰排列。 這相似於建立大多數網站的導航條的方式。url

最後,咱們將添加perspective屬性。 這將容許咱們在嵌套元素中建立3D場景,1000px的值將爲對象提供至關大的景深。 較低的值會有點過於戲劇化,但您能夠嘗試這一點,看看多大的值最適合您。

.scene {
	width: 260px;
	height: 400px;
	margin: 30px;
	float: left;
	perspective: 1000px;
}
複製代碼

相似.scene類,咱們還須要在.movie類類上設置明確的寬度和高度。 這將有助於每張海報在轉換時看起來都是正確的。 接下來,咱們將transform-style設置爲preserve-3d,以便咱們能夠在3D空間中轉換元素。 最後,咱們將沿Z軸將其平移-130像素。 這將使海報有更多的空間來移動。

.movie {
	width: 260px;
	height: 400px;
	transform-style: preserve-3d;
	transform: translateZ(-130px);
	transition: transform 350ms;
}
複製代碼

這是轉換開始的地方。咱們給.movie類添加一個transition。 設置時間爲350毫秒,但若是你想要一個更戲劇性的效果,能夠設置較小的值。

而後當鼠標懸停在.movie類時將開始轉換。 這將沿Y軸旋轉3D海報,而後沿Z軸將其移向屏幕。 您能夠將海報旋轉整整90度,但我更喜歡稍微偏移以保持3D效果。

.movie:hover {
	transform: rotateY(-78deg) translateZ(20px);
}
複製代碼

敏銳的程序員會注意到,雖然咱們已經平移了每一個li,但咱們實際上從未實際旋轉任何會產生幾何圖形並構建對象的元素。 咱們如今建立每一個3D海報。 每一個.poster和.info都須要絕對定位,不然它們會互相推開。 咱們不但願這樣,由於咱們將使用變換來定位它們。 接下來,咱們須要在兩個類上設置顯式維度,以便雙方中的每個都徹底相同。

.movie .poster, 
.movie .info {
  position: absolute;
  width: 260px;
  height: 400px;
  background-color: #fff;
  backface-visibility: hidden;
}

複製代碼

隨着咱們海報的幾何形狀準備就緒,咱們能夠將它們變換到位。 .poster只需沿Z軸移動130px(由於記住,咱們將.movie移回了這個數量)。 背景大小已設置爲cover,以便在咱們應用海報背景時,它們將填充幾何體。 不管如何它們都會正確,由於它們的尺寸正確,因此這實際上只是一種預防措施。

.info須要平移與.poster相同的數量,但也須要旋轉。 咱們想要造成一個方框,因此咱們將它旋轉90度。 我在轉換後添加了一些樣式,但這主要是出於審美緣由。

.movie .poster  {
  transform: translateZ(130px);
  background-size: cover;
  background-repeat: no-repeat;
}

.movie .info {
  transform: rotateY(90deg) translateZ(130px);
  border: 1px solid #B8B5B5;
  font-size: 0.75em;
}
複製代碼

咱們將使用僞元素::after建立另外一個盒子陰影:

.movie::after {
  content: '';
  width: 260px;
  height: 260px;
  position: absolute;
  bottom: 0;
  box-shadow: 0 30px 50px rgba(0,0,0,0.3);
  transform-origin: 100% 100%;
  transform: rotateX(90deg) translateY(130px);
  transition: box-shadow 350ms;
}

.movie:hover::after {
  box-shadow: 20px -5px 50px rgba(0,0,0,0.3);
}

複製代碼

在CSS中,咱們繼續設置.info類中包含的子元素的樣式。 這些都與此演示無關,由於它主要只是格式化一些文本和圖像。 真正的魔法發生在之後。

.info header {
  color: #FFF;
  padding: 7px 10px;
  font-weight: bold;
  height: 195px;
  background-size: contain;
  background-repeat: no-repeat;
  text-shadow: 0px 1px 1px rgba(0,0,0,1);
}

.info header h1 {
  margin: 0 0 2px;
  font-size: 1.4em;
}

.info header .rating {
  border: 1px solid #FFF;
  padding: 0px 3px;
}

.info p {
  padding: 1.2em 1.4em;
  margin: 2px 0 0;
  font-weight: 700;
  color: #666;
  line-height: 1.4em;
  border-top: 10px solid #555;
}
複製代碼

這是咱們使用box-shadow屬性建立僞照明的地方。 對於.poster類,咱們添加一個內陰影,其X和Y偏移爲0px。 模糊半徑將設置爲40px,陰影設置爲rgba(255,255,255,0)(白色「陰影」設置爲100%透明度)。 請記住,有一個過渡應用於.movie的全部子項,因此若是咱們爲陰影設置一個起始狀態,咱們就可使用:hover對其進行動畫處理。

若是咱們將鼠標懸停在.movie上,它將重置.poster的box-shadow值,並經過轉換爲它們設置動畫。 在這個新狀態下,海報的X偏移爲300px,不透明度爲0.8。 這將有效地將盒子陰影移動到海報頂部,沿着邊緣有一些模糊。 透明度將有助於使海報圖像凝聚陰影,這將使海報看起來像有光澤的。

.movie .poster,
.movie .info,
.movie .info header {
  transition: box-shadow 350ms;
}

.movie .poster {
  box-shadow: inset 0px 0px 40px rgba(255,255,255,0);
}

.movie:hover .poster {
  box-shadow: inset 300px 0px 40px rgba(255,255,255,0.8);
}
複製代碼

就像海報同樣,咱們也但願在盒子的另外一側塗上陰影。 對於.info面板,咱們但願當元素向前旋轉時暗陰影消失,而後當紙張紋理縮回到每一個3D海報之間的間隙時再從新出現。 在咱們的頁面上,左側有光澤的海報,右側有陰影,看起來會像有一束光從左側照在頁面上。

.movie .info, 
.movie .info header {
  box-shadow: inset -300px 0px 40px rgba(0,0,0,0.5);
}

.movie:hover .info, 
.movie:hover .info header {
  box-shadow: inset 0px 0px 40px rgba(0,0,0,0);
}
複製代碼

最後,咱們須要將海報圖像和靜態圖像添加到每部電影中。 我使用:nth-child僞類完成了這個,但一樣,這可能會在動態網站的其餘地方完成。

.scene:nth-child(1) .movie .poster {
  background-image: url(../img/poster01.jpg);
}

.scene:nth-child(2) .poster {
  background-image: url(../img/poster02.jpg);
}

.scene:nth-child(3) .poster {
  background-image: url(../img/poster03.jpg);
}

.scene:nth-child(1) .info header {
  background-image: url(../img/still01.jpg);
}

.scene:nth-child(2) .info header {
  background-image: url(../img/still02.jpg);
}

.scene:nth-child(3) .info header {
  background-image: url(../img/still03.jpg);
}
複製代碼

您會注意到咱們在演示中使用了Modernizr來檢測對3D變換的支持,併爲不支持它的瀏覽器提供簡單的回退版本。

正如我在介紹中所建議的那樣,這種技術能夠應用於簡單的幾何體。 有人可能想知道爲何我沒有使用漸變來在海報圖像上建立一個更受控制的陰影。 在本文誕生的時候,轉換不能應用於漸變,因此雖然這可能適用於靜態幾何,但一旦元素設置了動畫效果,幻象就會被打破。

若是您對此技術有任何問題,意見或改進,我很樂意在評論中聽到它們!

相關文章
相關標籤/搜索