最近,我誤打誤撞的遇到一個有趣的問題。我想要隨機的去設定animation-duration的值。 這是一個非隨機的例子:
這是我用CSS寫的一個動畫:
@keyframes flicker { 0% { opacity: 1; } 100% { opacity: 0; } } #red { animation: flicker 2s ease alternate infinite; }
目前工作良好. 但是這裡沒有隨機化,動畫執行時間固定為2s。
我想要的動畫是執行時間是2s以內的隨機數。我想要的效果是這樣的:
.element { animation: flicker $randomNumber alternate infinite; }
這裡的$randomNumber是一個透過特定函數產生的隨機數。
CSS預處理器如Sass提供了這樣的一個函數:
$randomNumber: random(5); .thing { animation-duration: $randomNumber + s; }
這可能是以你想要的,但卻不是我想要的,預處理器生成隨機數過程中有一個明顯的缺陷:
Sass中,随机数生成过程就像是从一个故事中选择名字的过程,它仅仅在写完之后随机取出,然后它就不再变化了。 — jake albaugh (@jake_albaugh) 2016年12月29日
換句話說,一旦CSS預處理器執行完畢,隨機化的過程就結束了,生成得到隨機數也就永遠的固定為一個值(也即直到CSS預處理器再次運行的時候才會重新生成。
在深表遺憾的同時,我也意識到這是一個使用CSS變數(CSS的自有屬性)的完美的機會!雖然,使用它來產生隨機數字並不是一件容易的事,但是,它們仍然可以幫助我們。
如果你不熟悉它們,那麼也別擔心。事實上CSS變數是它自帶的功能, 並且不同於你已經熟悉的CSS預處理器比如SASS和LESS的那種變數。參考Chris在這裡列舉的許多好處:
●你可是使用它們而不需要使用預處理。
●它們是級聯的。你可以在任何一個選擇器裡邊設定這個變數的值或是覆蓋目前的變數指。
●當它們的值改變(例如媒體查詢或者其它的狀態變化), 瀏覽器將會重新渲染.
●你可以訪問它們並且可以使用JavaScript操縱它們.
最後一點對於我們來說是重要的。我們在JavaScript中產生隨機數,再把產生的值設定到CSS變數上。
設定一個CSS自訂屬性, 並且給它一個預設值(萬一JavaScript在寫值的時候由於一些原因失敗的時候這是很有用的):
/* 设置默认的动画执行时间 */ :root { --animation-time: 2s; }
現在我們可以這樣在CSS中使用這個變數:
#red { animation: flicker var(--animation-time) ease alternate infinite; }
話不多說, 我們立即開始。 儘管這個看起來像之前的一個SVG動畫, 但這一個是使用CSS變數寫的. 你可以改變變數的值去測試它的工作方式。且即時預覽效果。
現在我們使用JavaScript來存取和操作這個變數:
var time = Math.random();
在這裡我們可以找到使用SVG建立的紅色的圓圈並且使用setProperty改變--animation-time 的值。
var red = document.querySelector('#red'); red.style.setProperty('--animation-time', time +'s');
看這裡!一個隨機數已經被設定到了SVG動畫元素上了:
看這個Robin Rendle (@robinrendle)寫在CodePen上的例子CSS隨機數#3。
這比起之前的有了很大的進步因為它的值是JavaScript運行時產生的隨機數,它每一次都在變化。 這成功實現了我們想要的效果, 但做到這一點我們還有些困難: 在運行時定期的animation-duration一個隨機數.
幸運地是,我們現在可以用JavaScript了,我們可以根據我們想要的更新自訂變數的值。這是一個我們每秒更新animation-duration的值的例子:
var red = document.querySelector('#red'); function setProperty(duration) { red.style.setProperty('--animation-time', duration +'s'); } function changeAnimationTime() { var animationDuration = Math.random(); setProperty(animationDuration); } setInterval(changeAnimationTime, 1000);
這正是我想要的: 看這個Robin Rendle (@robinrendle)寫在CodePen上的例子CSS隨機數#4。
不過得記住一點,CSS變數(自訂屬性)的支持性仍然不是太好,因此使用時要當心。 我們可以實現一個像這樣的漸進增強的動畫:
#red { animation: flicker .5s ease alternate infinite; animation: flicker var(--animation-time) ease alternate infinite;}
如果CSS變量沒有得到支持我們也能看到部分的動畫, 雖然它並不是我心目中的完美的樣子.
值得慶幸的是, CSS變數並不是我們產生animation-duration隨機值的唯一途徑。我們可以使用JavaScript操作DOM直接設值到style上:var red = document.querySelector('#red'); red.style.animationDuration = Math.floor(Math.random() * 5 + 1) + "s";
我們甚至可以等待動畫完成之前,設定一個新的時間,如果我們想要這樣的效果的話:
var red = document.querySelector('#red'); function setRandomAnimationDuration() { red.style.animationDuration = Math.floor(Math.random() * 10 + 1) + "s"; } red.addEventListener("animationiteration", setRandomAnimationDuration);
@element '#animation' { .element { animation-duration: eval('rand')s; }}
var rand = Math.random();EQCSS.apply();