標籤:

使用CSS技術實現Netflix Logo動畫效果

原文鏈接:Netflix Logo In CSS

本文已獲的原作翻譯授權,轉自譯文時請附上原文鏈接以及譯文鏈接,未經允許不得隨意轉載譯文

這篇博客是 Gregor Adams 講他如何用 CSS 重現 Netflix 商標效果。Gregor 是 CSS 方面冉冉升起的新星。能在這裡分析他的案例也是非常榮幸的。

我嘗試使用 Netflix(譯者註:一家在線影片租賃提供商)時,立即就把我吸引住了。我觀看了一些不得不在它處才能觀看的節目。每一集電視劇或者電影都以 Netflix 動畫作為開始。

(譯者註:知乎貌似不支持gif,請大家移步原網址查看動畫效果)

在觀看了幾集電視劇之後,我想到可以用 CSS 來實現 Netflix 的 logo 動畫,於是我看了幾部作品之後,就用 CodePen 來重現這個 logo。

第一個概念

因為我想要嘗試某些技術,導致我的第一種實現方式有些累贅。

例如:我想使用純 CSS 技術來實現它,並且我也想當我點擊按鈕的時候,這個動畫再執行一次,所以我要使用一些不可思議技巧。幸運的是當我寫 CSS 代碼的時候,總會有一些小技巧會在我的腦海里湧現。

我們來談論一下實際的動畫。

我錄下這個動畫並且在 Quicktime 中循環播放,這樣可以詳細檢查。我傾向於這麼做,能讓我停在某些特定幀弄清楚到底發生了什麼。

這個商標:

  1. 以一個白屏幕開始。
  2. 彈出白色的 3D 字母。
  3. 投射陰影。

  4. 消失。

  5. 把字體顏色變成紅色。

這就是我需要重現的動畫步驟。但是這裡有另外一些關於這個 logo 的東西需要解決:字母在商標中心是傾斜的。

大家一直問我如何做到這些。都是從積累中獲取地 :)

我做過許多 3D 案例,所以這對我來說不是很難。

使字母變傾斜

以這個詞 「Netflix」 的一些基本標記開始。

<div class="logo">n <span>N</span>n <span>E</span>n <span>T</span>n <span>F</span>n <span>L</span>n <span>I</span>n <span>X</span>n</div>n

我用類 logo 做了一個包裹,並且用 span 標籤包裹每一個字母。

然後我在Y軸上旋轉這個字母並且在 X 軸上縮放這個字母以保持它的原始寬度。重要的部分是在 class="logo" 包裝上設置一個 perspective ,並且定義它的 perspective-origin 。

// 基礎的字母樣式 nspan {n font-size: 8em;n font-family: impact;n display: block;n}n// 開啟三維效果 n.logo {n perspective: 1000px;n perspective-origin: 50% 0;n}n// 給字母變換 n.logo span {n transform-origin: 0 0;n transform: scaleX(80) rotateY(89.5deg);n}n

這裡還有一些其它的方式來實現這些技巧,例如使用一個不同 perspective(比如500px),旋轉角度(比如9deg)和縮放(比如0.5),但是這些值能最大滿足我的需求。

下面是在 CodePen 實現的小例子:(譯者註:原文章展示 demo 是通過頁面中嵌入 iframe 實現嵌入 CodePen ,但是知乎文章沒有嵌入 iframe 的方法,所以採用 CodePen 鏈接來展示,並且把原 demo 的 jade 和 scss 寫法轉換成 html 和 css 方便沒有使用過兩種技術的讀者閱讀)

  • 使用 jade 和 scss 完成的 demo

  • 轉換成 html 和 css 完成的 demo

實際效果

接下來我要對所有的字母應用這個樣式,中間的字母不要變化。右邊的字母朝著相反的方向傾斜,並且字母高度發生變化。

為了實現這些需要增加一些新邏輯:我使用 Sass 的標準語法來實現。

scss代碼

.logo {n perspective: 1000px;n perspective-origin: 50% 0;n font-size: 8em;n display: inline-flex;nn span {n font-family: impact;n display: block;nn $letters: 7;n @for $i from 1 through $letters {n $offset: $i - ceil($letters / 2);n $trans: if($offset > 0, -89.5deg, 89.5deg);nn &:nth-child(#{$i}) {n // trans/de-form the lettersn transform-origin: 50% + 50%/$offset 200%;n font-size: if($offset == 0,n 0.85em,n 0.9em + 0.015*pow(abs($offset),2));n transform:n if($offset == 0, scale(1, 1), scale(95.9 - abs($offset) * 10, 1))n if($offset == 0, translatey(0%), rotatey($trans));n }n }n }n}n

為了方便不懂 scss 同學理解,這是我編譯後的 css 代碼

.logo {n perspective: 1000px;n perspective-origin: 50% 0;n font-size: 8em;n display: inline-flex;n}n.logo span {n font-family: impact;n display: block;n}n.logo span:nth-child(1) {n transform-origin: 33.33333333% 200%;n font-size: 1.035em;n transform: scale(65.9, 1) rotatey(89.5deg);n}n.logo span:nth-child(2) {n transform-origin: 25% 200%;n font-size: 0.96em;n transform: scale(75.9, 1) rotatey(89.5deg);n}n.logo span:nth-child(3) {n transform-origin: 0% 200%;n font-size: 0.915em;n transform: scale(85.9, 1) rotatey(89.5deg);n}n.logo span:nth-child(4) {n transform-origin: Infinity% 200%;n font-size: 0.85em;n transform: scale(1, 1) translatey(0%);n}n.logo span:nth-child(5) {n transform-origin: 100% 200%;n font-size: 0.915em;n transform: scale(85.9, 1) rotatey(-89.5deg);n}n.logo span:nth-child(6) {n transform-origin: 75% 200%;n font-size: 0.96em;n transform: scale(75.9, 1) rotatey(-89.5deg);n}n.logo span:nth-child(7) {n transform-origin: 66.66666667% 200%;n font-size: 1.035em;n transform: scale(65.9, 1) rotatey(-89.5deg);n}n

下面是在 CodePen 實現的小例子:(譯者註:原文章展示 demo 是通過頁面中嵌入 iframe 實現嵌入 CodePen ,但是知乎文章沒有嵌入 iframe 的方法,所以採用 CodePen 鏈接來展示,並且把原 demo 的 jade 和 scss 寫法轉換成 html 和 css 方便沒有使用過兩種技術的讀者閱讀)

  • 使用 jade 和 scss 完成的 demo

  • 轉換成 html 和 css 的 demo

實際效果

一個用於陰影的函數

寫一個實現 3d 效果和陰影的函數。我把視頻停在某一幀,並仔細查看細節。

正如你所看到的,當這個陰影到達右下角,3d 效果的消失點在中間。現在知道我們函數需要做什麼了。

我們將會在 keyframes 中調用這個函數,所以我們希望他能處理一些值,例如:

  • color

  • x

  • y
  • blur

  • mix

我們還需要一個參數來定義陰影的深度或者 3d 效果。

下面就是用來處理這些需求的函數:

/// 在特定方向創創建三維陰影n/// @author Gregor Adamsn/// @param {Number} $depth - 陰影長度n/// @param {Unit} $color - 陰影顏色n/// @param {Unit} $x - 在x軸上到下一個陰影的距離n/// @param {Unit} $y - 在y軸上到下一個陰影的距離n/// @param {Unit} $blur - text-shadow的模糊距離n/// @param {Color|false} $mix - 添加一個可選的顏色來混合n/// @return {List} - 返回text-shadow列表n@function d3($depth, $color, $x: 1px, $y: 1px, $blur: 0, $mix: false) {n $shadow: ();n @for $i from 1 through $depth {n // append to the existing shadown @if type-of($mix) != color {n $shadow: append($shadow, round($i * $x) round($i * $y) $blur $color, comma);nn } @else {n $shadow: append($shadow, round($i * $x) round($i * $y) $blur mix($mix, $color, 0.3%*$i), comma);n }n }n @return $shadow;n}n

這個函數對於 Sass 菜鳥或者只使用基本語言特性的開發者和設計師來說可能有點難理解,所以讓我來詳細解釋一下。

我以一個 $shadow 的變數開始, list 是一個空的列表。

$shadow: ();n

我是從1開始循環到 $depth 。在 Sass 中會使迭代器迭代到 through 這個值。

  • from 0 to 5 = 0, 1, 2, 3, 4

  • from 0 through 5 = 0, 1, 2, 3, 4, 5

每一次迭代我都添加一個 text-shadow 到這個列表。所以最後這個列表看起來就是下面這個樣子:

$shadow: (0 1px 0 red, 1px 2px 0 red, 2px 3px 0 red, ...);n

使用的時候就像下面這樣:

text-shadow: d3(5, red, [$x], [$y], [$blur], [$mix]);n

$x,$y,$blur 和 $mix 都是可選的參數。我已經提到我將會在 keyframes 中調用這個函數,所以我需要可選擇性地改變他們。 $mix 允許添加第二個顏色,實現這個陰影從一種顏色淡出成另外一種顏色。

下面是在 CodePen 實現的小例子:(譯者註:原文章展示 demo 是通過頁面中嵌入 iframe 實現嵌入 CodePen ,但是知乎文章沒有嵌入 iframe 的方法,所以採用 CodePen 鏈接來展示,並且把原 demo 的 jade 和 scss 寫法轉換成 html 和 css 方便沒有使用過兩種技術的讀者閱讀)

  • 使用 jade 和 scss 完成的 demo

  • 轉成成 html 和 css 的 demo

實際效果

組裝在一起

因為我已經創造了許多我需要的部分,現在可以建立動畫了。

1.組裝在一起

我使用兩個上面已經定義的變數 $offset 和 $trans ,動畫有三個階段,我需要仔細地決定何時到達某幀。

@keyframes pop-out {n 0% {n transform:n if($offset == 0, scale(1, 1), scale(95.9 - abs($offset) * 10, 1))n if($offset == 0, translatey(0%), rotatey($trans));n text-shadow:n d3(15, rgba($c_3d, 0), 0, 0),n d3(50, rgba($c_shadow, 0), 0, 0);n }n 50% {n transform:n if($offset == 0, scale(1.2, 1.2), scale(126.2 - abs($offset) * 10, 1.2))n if($offset == 0, translatey(-16%), rotatey($trans));n text-shadow:n d3(15, $c_3d, if($offset == 0, 0, -0.25px * $offset), 1px),n d3(50, $c_shadow, 1px, 3px, 3px, $c_shadow-mix);n }n 100% {n transform:n if($offset == 0, scale(1.1, 1.1), scale(116.2 - abs($offset) * 10, 1.1))n if($offset == 0, translatey(-12%), rotatey($trans));n text-shadow:n d3(15, $c_3d, if($offset == 0, 0, -0.25px * $offset), 1px),n d3(50, $c_shadow, 1px, 3px, 3px, $c_shadow-mix);n }n}n

2.淡出(動畫結尾)

同樣的步驟實現淡出的效果。

@keyframes fade-back {n 0% {n transform:n if($offset == 0, scale(1.1, 1.1), scale(116.2 - abs($offset) * 10, 1.1))n if($offset == 0, translatey(-12%), rotatey($trans));n text-shadow:n d3(15, $c_3d, if($offset == 0, 0, -0.25px * $offset), 1px),n d3(50, $c_shadow, 1px, 3px, 3px, $c_shadow-mix);n }n 20% {n transform:n if($offset == 0, scale(1.05, 1.05), scale(105.9 - abs($offset) * 10, 1.05))n if($offset == 0, translatey(-7%), rotatey($trans));n text-shadow:n d3(15, rgba($c_3d, 0), 0, 0),n d3(50, rgba($c_shadow, 0), 0, 0);n }n 100% {n transform:n if($offset == 0, scale(1, 1), scale(95.9 - abs($offset) * 10, 1))n if($offset == 0, translatey(0%), rotatey($trans));n text-shadow:n d3(15, rgba($c_3d, 0), 0, 0),n d3(50, rgba($c_shadow, 0), 0, 0);n }n}n

3.改變字體顏色

還需要提供一個動畫改變字體顏色。

@keyframes change-color {n 0% {n color: $c_bg;n }n 100% {n color: $c_fg;n }n}n

4.觸發這個動畫

現在我們可以像下面這樣把動畫連接在一起。

animation-name: pop-out, fade-back, change-color;nanimation-duration: 4s, 2s, 0.1s;nanimation-delay: 0s, 2s, 3.2sn

上面的代碼只是一個近似的實現,每個字母有不同的動畫延遲和間隔,可以點擊這裡查看最終的實現效果。

最後注意一下,我使用了一些不可思議的技巧來實現在純 CSS 中再次觸發動畫,我將會在接下來的文章中解釋。

寫案例的時候並不是十分滿意,因為寫文章的時候我又想到了其它幾個提高效果的方法。

為了寫這篇文章我重新寫了整個 Sass 代碼,但是我仍然覺得我能提升一些。這就是我不間斷做案例的主要原因。讓我變得更加聰明,和在一些以前沒有涉足過的方向有新的突破。

我幾乎沒有在實際的項目中用到這樣的技術,但是我經常使用函數來提升效果。不論如何希望你喜歡這篇文章。

Gregor Adams 是一位來自 Hamburg 的前端開發者,他對 CSS 和 Sass 有極大的熱情。從他的 CodePen 中可以看出他強大的 CSS 技術。

歡迎關注

  • 新浪微博:前端外刊評論

  • 博客:前端外刊評論
  • 個人博客

  • 如果有疏漏的地方歡迎批評指正:vista5004@gmail.com

推薦閱讀:

使用 CSS 來做素數的判定與篩選
You Don't Know CSS(二)
CSS 設計理念
移動端實現內滾動的4種方案
外邊距摺疊-磨人的小妖精

TAG:前端开发 | CSS |