以下為原始檔
https://github.com/87JoJo/Playing-with-CSS-Variables-and-JS-
成果如下圖
以前我們都是直接在JS控制屬性,而這次我們利用資料(歸納在css中),
也就是在CSS設置變數的方法來改變畫面,缺點會比較難找變數名稱。
分別為滑動桿,與色彩選取器
<label for="spacing">Spacing:</label>
<!-- type="range" 滑動桿 -->
<input id="spacing" type="range" name="spacing" min="10" max="200" value="10" data- sizing="px" />
<label for="base">Base Color</label>
<!-- type="color" 顏色選取器 -->
<input id="base" type="color" name="base"
為偽類選取器
,設置樣式為變數,前面需要加上--
,我們將變數設置在html裡
,然後img及hl在利用var獲取其設置好的屬性值
,當我們:root內的屬性值改變
,img及hl的畫面也會跟著改變。
/* :root等同於html */
:root {
--base: #ffc600;
--spacing: 10px;
--blur: 10px;
}
img {
/* 讀取位於html層設置的變數屬性 */
padding: var(--spacing);
background: var(--base);
filter: blur(var(--blur));
}
.hl {
color: var(--base);
}
先利用querySelectorAll獲取所有Input
// querySelectorAll獲取為半殘的array(like-array),有foreach、length、key,但無map
const inputs = document.querySelectorAll('.controls input');
// console.log(inputs); NodeList(3)
在遍歷每個Input做監聽事件的處理,利用change事件來做監聽,當input有所變動就會觸發,但change為修改完,最後才會觸發,為了連續觸發屬性值(10px,11px,12px...),所以要額外加上mousemove的事件,來做即時的監聽。
// 每次拿一個input,並賦予事件
inputs.forEach(input => {
// 當改變的時候觸發changeHandler
// change事件為最後觸發
input.addEventListener('change', changeHandler);
// 如果要連續觸發須加上mousemove
input.addEventListener('mousemove', changeHandler);
});
再來就處理觸發事件後的函數changeHandler,我們所要的是觸發事件後,更改對應的樣式。
這種寫法,繁雜麻煩,當要一次改變多個樣式,還需再加上一行代碼
function changeHandler() {
console.log(this.name, this.value); 可獲取當前改變的樣式及值
switch (this.name) {
case 'spacing':
document.querySelector('img').style.padding = this.value + 'px';
break;
case 'blur':
document.querySelector(
'img'
).style.filter = `blur(${this.value}px)`;
break;
case 'base':
document.querySelector('img').style.background = this.value;
// 改變標題的字母(js)
document.querySelector('.hl').style.color = this.value;
break;
}
資料放在root,要獲取的話,這三種寫法都相同document.querySelector('html')=document.querySelector(':root')=document.documentElement
[屬性名稱]較傳統方法,來設置屬性,但由於變數名有--,故無法使用中括號
而後的三目運算符,為如果屬性名為base就加上'',如果不為(blur,spacing)就加上px
document.documentElement.style['--' + this.name]= this.value + (this.name === 'base' ? '' : 'px');
獲取放在html層的資料變數,並利用setProperty修改其屬性值
document.querySelector('html').style.setProperty('--' + this.name,this.value + (this.name === 'base' ? '' : 'px'));
<input id="blur" type="range" name="blur" min="0" max="25" value="10" data-sizing="px" />
<input id="spacing" type="range" name="spacing" min="10" max="200" value="10" data-sizing="px" />
<input id="base" type="color" name="base" value="#ffc600" />
以dataset判斷代替三目運算符,dataset指的也就是讀取所有你在DOM上data開頭的屬性,如果有sizing的屬性就用它,如果沒有就給予空,而在我們的DOM元素,有sizing的只有blur,spacing。
// 設置一個變數,如果data為sizing的屬性就使用他的屬性值,否則為空
const unit = this.dataset.sizing || '';
document.querySelector('html').style.setProperty('--' + this.name, this.value + unit);
// document.querySelector('html').style.setProperty('--' + this.name,this.value + (this.dataset.sizing || ''));
console.log(this.dataset); // DOMStringMap {sizing: "px"}
console.log(this.dataset.sizing); // 當控制spacing,blur出現px而改變顏色會出現undefined```