# Day 3:Playing with CSS Variables and JS [竹白記事本](https://chupainotebook.blogspot.com/),Javascript 30,紀錄。 ###### tags: `Javascript 30` ## 實現效果 使用 JavaScript 搭配原生 CSS 變數,製作出一個即時濾鏡效果工具。 可調整模糊、邊框色、內距大小。 - [原始碼](https://github.com/chupai/JS30/tree/master/source_code/Day03) - [原始狀態](https://chupai.github.io/JS30/source_code/Day03/index-START.html) - [範例效果](https://chupai.github.io/JS30/source_code/Day03/index-FINISHED.html) ## 重點 1. CSS Variables 2. 標題的 JS 顏色也要變化 3. 定義好得 `data-sizing` 用來判斷單位 ## 基礎語法 ### CSS - [CSS Variables](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Using_CSS_custom_properties) - `filter:blur()` ### DOM - [`dataset`](https://developer.mozilla.org/zh-TW/docs/Web/API/HTMLElement/dataset) - [`setProperty()`](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration/setProperty) - [`documentElement`](https://developer.mozilla.org/zh-TW/docs/Web/API/Document/documentElement) ## 說明 ### 1. CSS 必須先宣告全域的 CSS 變數,並套用到對應的頁面元素中(圖片、標題)。 ### 2. CSS Variables 支援度 `style` 所繼承的 `CSSStyleDeclaration` 介面,不支援 CSS Variables 的樣式屬性,所以必須使用 `setProperty()` 來設定樣式屬性。 ## 實作 ### 1. 步驟 #### Step 1 新增 CSS 變數 ```css :root { --base: #ffc600; --spacing: 10px; --blur: 10px; } img { padding: var(--spacing); background: var(--base); filter: blur(var(--blur)); } .hl { color: var(--base); } ```` `:root` 等同 `html` 選取器。 將資料變數放在 CSS 的優缺點: - 減少 JS 放資料的負擔 - 只修改一處 CSS 變數,所有套用此變數的樣式都會一起變動 - 寫程式時需要到 CSS 查看變數與修改 #### Step 2 對所有 `input` 標籤 註冊監聽事 ```javascript const input = const inputs = document.querySelectorAll('.controls input'); ``` 注意,`querySelectorAll` 出來的是 [`NodeList`](https://developer.mozilla.org/zh-TW/docs/Web/API/NodeList) 類陣列,不是陣列,陣列部分的功能它沒有。在 [Day 1](/ryWdlSIWH) 中有提到過。 ```javascript inputs.forEach(function(key) { key.addEventListener('change', changeHandler); }); ``` 為每個 `input` 標籤註冊監聽事件,當 `change` 事件發生,執行 `changeHandler` 函式。 由於 [`change`](https://developer.mozilla.org/zh-CN/docs/Web/Events/change) 事件並不即時,滑鼠放開才會執行,所以還需要再加入 [`mousemove`](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/mousemove_event) 事件,使拉動滑桿時,也能更新效果。 ```javascript inputs.forEach(function(key) { key.addEventListener('change', changeHandler); key.addEventListener('mousemove', changeHandler); }); ``` #### Step 3 建立 `changeHandler` 函式 不使用 CSS 變數的作法: ```javascript function changeHandler() { const img = document.querySelector('img'); const hl = document.querySelector('.hl'); switch (this.name) { case 'spacing': img.style.padding = this.value + 'px'; break; case 'blur': img.style.filter = `blur(${this.value}px)`; break; case 'base': img.style.backgroundColor = this.value; hl.style.color = this.value; break; } } ``` 這樣的缺點是,當有兩處以上需要變動,就要手動增加。 依照題目使用 CSS 變數作法: ```javascript document.querySelector('html') document.querySelector('root') document.documentElement ``` 這三個是一樣的,依個人喜好選擇。 ```javascript function changeHandler() { const unit = this.dataset.sizing || ''; document.documentElement.style.setProperty( `--${this.name}`, this.value + unit ); } ``` 原始碼 HTML 有提供 `data-sizing` 屬性,是用來判斷要不要加上單位,因此這邊用 `dataset` 取得。 由於 `--變數` 是較新的 CSS 屬性 `style` 不論是 `.` 或 `[]` 都不支援,因此這裡用 `setProperty` 來加上 CSS 屬性。 這邊的 `this` 指向觸發 `changeHandler()` 的元素,因此可以獲取該元素的 `data-sizing`、`name`、`value` 值。 #### Step End ```javascript (function() { const inputs = document.querySelectorAll('.controls input'); function changeHandler() { const unit = this.dataset.sizing || ''; document.documentElement.style.setProperty( `--${this.name}`, this.value + unit ); } inputs.forEach(function(key) { key.addEventListener('change', changeHandler); key.addEventListener('mousemove', changeHandler); }); })(); ``` ### 2. 進節 #### 改用事件委派 與 Day1 相同,改用事件委派可以減少監聽器。 ```javascript const inputs = document.querySelector('.controls'); function changeHandler(e) { if (e.target.nodeName !== 'INPUT') { return; } const unit = e.target.dataset.sizing || ''; document.documentElement.style.setProperty( `--${e.target.name}`, e.target.value + unit ); } inputs.addEventListener('change', changeHandler); inputs.addEventListener('mousemove', changeHandler); ``` ### 3. 實作連結 - [初版](https://chupai.github.io/JS30/source_code/Day03/index1.html) - [使用事件委派](https://chupai.github.io/JS30/source_code/Day03/index.html)
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.