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

赤木晴子發表於2019-02-23

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

線上預覽 下載原始碼

當使用 3D 轉換來對元素進行格式化的時候,您可能會注意到它們沒有任何陰影並且看起來非常平坦。 在現實生活中,物體會阻擋光線併產生陰影。 物體表面可能是啞光,反光,或者介於兩者之間。所以,我們可以做得更好。

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

HTML結構

我們的頁面將有幾個不同的部分。 首先,我們需要一個簡單的父元素來居中頁面上的所有內容。 接下來,我們將建立一個包含所有3D海報的無序列表。 我們給ul新增類“stage”,給每個li新增類“scene”。 在我們的CSS中,ul將充當所有li元素的容器,每個li元素會設定perspective屬性用於構成透檢視。

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

複製程式碼

對於每個li,我們需要新增相當多的子元素。 這將包含我們的電影海報以及每部電影的所有相關介紹。 在一個更強大的電影庫中,這可以使用一些後端程式碼動態完成。 出於本示例的目的,我們將保持簡單。

<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部分。

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

CSS樣式

請注意,示例CSS不包含任何瀏覽器字首,但您可以在下載的檔案中找到它們。

首先,讓我們做一些基本的操作。 我們需要將我們的父元素居中,然後刪除預設的列表樣式。

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

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

接下來,我們將給.scene類設定明確的寬度和高度(與我們的海報相同)。 如果您想在高解析度顯示器上有更好的視覺效果,那麼您可以使用兩倍大的影象。

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

最後,我們將新增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變換的支援,併為不支援它的瀏覽器提供簡單的回退版本。

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

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

相關文章