[POST] Codrops Collective Cover CSS version note
前些天抽空參考 Codrops Collective 的封面做了個 CSS 動畫版的 https://codepen.io/Rplus/pen/YMBmOK 要看錄的示範影片請到 Twitter
Codrops 原圖:

因為最近寫 code 都沒在錄影 而且這玩意算數學也稍微花了一些時間 錄起來應該會像停格一樣吧 XD
下面回憶/記錄一下自己的製作思路:
1 基板
看到圖形時
就大概有個概念弄個一堆點點
然後配上不同的 scale 數值,讓它們有不同的尺寸
主要的思考是在於需不需要使用 CSS Grid
因為其實主要圖案的排版也不難
Grid 似乎有些大材小用的感覺
原本是想直接用 inline-block 做
後來想想,算了,得需要 gap,那就用 Grid 吧…
因為參數都在 pug 那邊就用 CSS variables 傳到上層了 所以 grid columns 也就直接吃參數了
另外說一下自己的(~~偷懶~~)命名習慣 這類沒什麼語意的基礎單元, 我是滿喜歡用
.o來當 class name 的 兩個 o.oo代表小組件,常見的是線形, 而這邊因為沒有單軸向的單元 所以.oo就代表兩軸向的平面 三個 o 的.ooo就單純懶得想上層命名,嗯,就是這樣 XD
而稍後用到的
--oi是指該單元(.o)的index-ooi=>.oo的index很懶~ 但我覺得這樣還算直觀好記 XDD
2 單元點
因為對這類點的規則悟性不夠
並不像 Ana Tudor 一樣可以很迅速地推出參數與方程 XDD
所以最一開始我是做觀察
方法就是把 index, col index, row index 全部列上去
然後再慢慢去想該怎麼搭配組合出我想要的大小變化

就寫個 pseudo-element 塞一些 index 來看 看著上面這圖,再看看圖源 先找出規律性
2-1 單元點的尺寸
整體一起看會有點難想 那就一排排往下看;或先看邊界條件:看頭尾
第一排看起來是依照 col index 逐一遞增 1
最後一排剛好相反,依 col index 遞減
PS: 要看之前,得記得先定義
絕對大小不然看第二排就大概忘記第一排的大小了 XD 這邊我是把第一排當作基準,最小的當 0 ,最大的當 15 (一排 16 顆)
看完頭尾兩列,再來看同樣是邊界的兩欄
第一欄也是很直觀地,依 row index 遞增 1;最末欄相反
不在邊線、中間的點點,看起來似乎不是單純整數的關係
雖然單看左上角,似乎有點像 x = y 的線性關係
但看 中央部份 跟 右上、左下的尺寸就明顯不同
所以應該沒那麼簡單~
接下來就是要算聯立方程了 嘿嘿嘿~ 正好我線性代數重修了三次
教授,抱歉,我全忘光了呢~ XDDD
線代不會沒關係~ 幸好我還記得國中的二元方程怎麼列 XD
若有人看不下去的,歡迎回覆救援~ XDD
這些點點的大小若化作座標點 每列連成線的話,大概就會長得像這圖:

先看第一列的線性函數(紅色那條)
左下座標 (0, 0) => { col:0, size:0 }
右上座標 (15, 15) => { col:15, size: 15 }
代入二元來解 a, b ax + b = y
row1: (0, 0), (15, 15)
0a + b = 0
15a + b = 15
=> a = 1, b = 0
=> row1: 1x + 0 = y
=> row1: 15x/15 + 0 = y
row2: (0, 1), (15, 14)
0a + b = 1
15a + b = 14
=> b = 1, a = 13 / 15
=> 13x/15 + 1 = y
…
row16: (0, 15) (15, 0)
0a + b = 15
15a + b = 0
=> b = 15, a = -1
=> row15: -1x + 15 = y
=> row15: -15x/15 + 15 = y
歸納出
y = x * (15 - 2 * row-index) / 15 + row-index
將 x, y 用參數代入
y : size
x : col-index(ci)
row-index(ri)
=> size = ci * (15 - ri * 2) / 15 + ri
15 = col count - 1 = col gap count
嗯~ 好吧 我刻完那張一堆線的圖 再打完上面那堆解聯立 我也不曉得到底有用到了什麼數學原理 數學能力大概只剩下:直觀感覺不出來的話,那就算了吧 XDD
不管如何~ 總算得到了圓點尺寸了呢~
而用在 CSS 裡的話,最好再處理一次數值
免得 CSS 裡還要寫一堆 normalization 算式
在 pug 裡有另外寫了一支 shiftNumber() 來處理數值轉換
裡頭也就只是簡單的線代
反正就是 x0-y0 線段上的 n 點映射到 x1-y1 線段後的座標點
當然這邊只用了單維,所以當作伸縮平移也就可以了~
這段主要是輸出 CSS 要的數值範圍與格式
因為 CSS 那邊不太需要過多的小數點
算個大概就好,反正最小刻度也不能低於 1px,
一般狀況下精度不用太在意
很好,圓點大小就到這邊哩~
2-2 圓點對齊
原圖的對齊方式還挺奇妙的 我原本比為只是很普通地對齊正中心 結果細看之下,哇~ 這麼坑呀… 垂直對齊都是一致的正中心,很好 水平對齊方式真的奇葩:左邊的靠左、右邊的靠右…
我看了就碎念為什麼不弄成一樣的對齊方式…
不過後來想了一想, 覺得這設計還是有它的道理在 忘了是人眼是水平向的緣故、還是地平線的關係 人眼對於水平線的對齊會較為敏感 所以如果水平的對齊不一致的話,就會很突兀 垂直向就大概是設計師個人品味了吧(?
這邊就還滿簡單的
依據 col index,然後比例平移到 [0, 1] 之間即可
之後到 CSS 裡設定 transform-origin
2-3 圓點顏色
這邊看圖片
顏色分佈大概是右上到左下漸變
算式就比較簡單: col-index 與 row-index 的差值
因為套色會用算式來處理
所以記得讓差值正規化到 [1, -1] 區間
而在計算這種漸變色
通常會用 HSL 表式法來定義色彩
作法也挺簡單
就挑個支援 HSL 的取色器(或直接用 Chrome devtool 取色也可
得到的兩組 HSL,兩值取均值再加差值的一半
而這兩組 HSL 中的 S & L 數值差不多
所以就直接寫死了
反正我辨色力不佳~ XDD
如果設計師比較在意的話再一併調整也沒問題 :P
顏色、大小 都妥妥了~
3 動畫
上面做完後已經跟原版一樣了 但海報跟網頁有所不同, 網頁可以有更多互動嘛~
辛苦兜這麼久 當然不能只滿足於復現啦 一定得加點自己的料進去才行 XDD
原本是想弄成個上一個一樣
加些 transition 就好
但總覺得讓它們可以自己動起來好像會比較好玩
所以就加了 animation 進去
delay 時間就用 size 處理一下,
某方面來說,我們算出的 size 就是該點的 變化參數
要記得 animation 想先觸發動畫的話,delay 要設定成負數~
加好了之後,嗯~ 棒棒的
3-1 互動性
動態的有人喜歡,但也有些人喜歡靜態 能動能靜,兩種都能滿足的話不是更棒嗎~
在以往的 codepen 裡,
有些 CSS animation 我都是習慣讓滑鼠 :hover 過去後再啟動動畫
開發的時候也習慣先上一個 play-state: paused
一直動,很暈的…
所以在這邊用了 CSS variables + variables fallback
animation-play-state: var(--animation-play-state, paused)
預設就先停止
滑過親代層時再啟動動畫,享受眼花撩亂
:hover { --animation-play-state: running }
但其中有個問題是 若滑鼠移入再移出,畫面就不再是初始狀態 會跟原本的圖源長得不一樣
這邊有用到另一個 CSS 小技巧來重設動畫
&:active { --animation-name: gg }
點擊時指派另外的動畫名稱(不一定要真實存在) 點擊狀態不再時,動畫就會回到初始狀態了
本來只是想記錄一下算數學那段 XDD 不過寫就寫了 就順便記錄一些有用到的小東西 :P
註:CSS custom property 使用習慣的變化
近來用的 CSS custom property(CSS variabls) 寫作習慣是有些些的不太一樣
以前會喜歡讓 HTML 完全乾淨,只有 class name
然後在 SCSS 裡下些迴圈生些 nth-of-type() 之類的選擇器
再配與相應的 index 或是 計算用參數
而最近有些作品,我會選擇直接將參數以 inline style 的方式刻在 DOM 上 像這例我就直接將 CSS 要用到的三個參數先算完再擺進 style 裡
前者用法的好處是,樣式就真的歸樣式處理 不會因為 DOM 因為 JS 新塞新的元件進去就 gg 沒套用到
但缺點就是 SCSS/CSS 會變得比較醜
比如說,這次的例子裡,pug 裡那些算式其實也可以放在 SCSS 裡處理
都只是一些四則運算而已,
在 CSS 裡單純用 --ci, --ri 加減乘除也是完全能處理過來的
但就真的是變得醜醜的 XD
SCSS + calc + var() 的醜不是說說而已 XDD
另個原因是我覺得參數這類東西在 DOM 出來時就確立了 基本上不太會異動 這樣的情況我會比較喜歡直接在 pug 裡算完 然後在 CSS 裡寫比較明確與易懂的算式 CSS 算式寫太長,維護時讀起來有時會有點晃神 XDD
大概就這樣~
支持的話可以到 codepen 點個 ♥️ 或是 follow ~