iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 3
0

首先先來看看 html

<h2>Update CSS Variables with <span class='hl'>JS</span></h2>

<div class="controls">
  <label for="spacing">Spacing:</label>
  <input id="spacing" type="range" name="spacing" min="10" max="200" value="10" data-sizing="px">

  <label for="blur">Blur:</label>
  <input id="blur" type="range" name="blur" min="0" max="25" value="10" data-sizing="px">

  <label for="base">Base Color</label>
  <input id="base" type="color" name="base" value="#ffc600">
</div>

在這些<input>中都存著每種濾鏡的變數名稱namevalue

css variable
相較於 scss 的變數 $spacing: 10px;$blur: 10px;$base #ffc600;, css 變數更自由

  • scss 所設定的變數,在編譯成 css 時就已經將真實的值代替變數了,所以使用者無法透過瀏覽器更改變數,一次改變多個屬性值
  • css 變數則可讓 js 擷取、動態修改並套用到使用該變數的屬性值,即使用者可以透過更改瀏覽器變數,一次改變多個屬性值

可以將 css 變數寫在:root內,以兩個 dash 宣告變數

:root{
  --spacing: 10px;
  --blur: 10px;
  --base: #ffc600;
}

接下來是利用var + 變數名稱來使用變數

img {
    padding: var(--spacing);
    background: var(--base);
    filter: blur(var(--blur));
}
.hl {
    color: var(--base);
}

由上述 code 可以知道:

  • --spacing控制img元素的padding
  • --base控制img元素的background和.hl的color
  • blur控制img元素的模糊程度

其中css filter 濾鏡 - MDN可以到這裡玩玩看

都設置完成後,進入 JS

const inputs = document.querySelectorAll('.controls input');
function handlerUpdate() {
    //改變濾鏡效果
}
inputs.forEach(value => value.addEventListener('change', handlerUpdate));

利用querySelectorAll選取.controls下所有的input元素
並用forEach()對其內的每一個 input 元素監聽'change'、事件,一旦事件發生,執行handlerUpdate事件。改變濾鏡效果

function handlerUpdate() {
    const dataSizing = this.dataset.sizing || '';
    document.documentElement.style.setProperty(`--${this.name}`, this.value + dataSizing);
}

這裡的this是指綁定事件的元素,因此會分別會得到<input id="spacing"><input id="blur"><input id="base">
由於我們將長度單位放在data-sizing,所以我們需要使用dataset.(data-後的名稱),但是 color 並不需要長度單位
所以需要使用||''(或空值),讓id="base"那個 input 後面在組字串的時候不會變成#ffc600 + undefined

最後使用document.documentElement取得根元素,用setProperty來修改樣式

可以成功修改濾鏡效果了,但是還不是很完美,只有在鬆開滑鼠的時候才會知道變成什麼顏色。我們希望在拉動滑鼠時就可以預先知道濾鏡效果,由於只有change事件的話,就只有存取值被改變的時候才會執行handlerUpdate函式,所以加入mousemove事件可以讓在拉動 handler 的時候,也能即時看到效果變化

inputs.forEach(value => value.addEventListener('mousemove', handlerUpdate));

跑起來的流程是
<input id="spacing">的 handler 被拉動了,拉動的過程中因為有監聽mousemove事件,會不斷的觸發handlerUpdate函式,一直修改:root內的--spacing變數。

Demo
完整程式碼

參考資料
css filter - MDN


上一篇
JS 30 - 02 - JS and CSS Clock
下一篇
JS 30 - 04 - Array Cardio Part I
系列文
寫JS30天30
0
Arel
iT邦新手 5 級 ‧ 2018-10-18 18:40:17

我覺得筆者去年的鐵人文前五篇很精彩,今年還會有嗎!?

可以考慮把Arel寫進去!

0
TomasLin
iT邦新手 5 級 ‧ 2018-10-18 18:44:56

我記得去年我跪著看筆者的前五篇,今年還會有嗎!?

不會!

0
Chris
iT邦新手 5 級 ‧ 2018-10-20 23:07:49

插播一篇龍門客棧如何?

龍門客棧的掌櫃去走標了

我要留言

立即登入留言