今天來優化 Day24 做的色碼挑戰器,主要增加的功能如下:
因為要多顯示一個色碼表示法,將排版做了些微調整,改成下圖的樣子
這次學習的主要一個重點是複製功能,在瀏覽器中主要有三個方法可以實作複製功能,之後的實作會先採用第一種方法
Document.execCommand
document.execCommand('copy')
執行複製p
元素的方式const get = (text) => document.querySelector(text);
const p = get('p');
p.addEventListener('click', function() {
// 產生 range 物件
const range = document.createRange();
// 選取p節點作為range物件的內容
range.selectNode(p);
// 產生 selection 物件
const selection = window.getSelection();
// 清除選取範圍
selection.removeAllRanges();
// 將選取到內容放入selection物件中
selection.addRange(range);
// 執行複製
document.execCommand('copy');
// 清除
selection.removeAllRanges();
})
Clipboard API
navigator.clipboard
Clipboard Event
認識有哪些方法可以對瀏覽器中的元素進行複製後,就開始來練習吧~
<!-- 顯示顏色的區域 -->
<section class="display">
<!--總共有三個與下面同樣結構的div -->
<div class="hex">
<div class="colorpad"></div>
<p class="colorCode">#808080</p>
</div>
<!--略 -->
</section>
<!-- 可以滑動slider的區域 -->
<section class="slider">
<!--總共有四個與下面同樣結構的div:代表R/G/B/A的slider-->
<div class="alpha-group">
<span>A</span>
<input type="range" min="0" max="1" step="0.01" value="0.5" class="alpha">
<span class="range">0.5</span>
</div>
<!--略 -->
</section>
由於要增加 RGBA 的顯示,我將原本的displayValue
函式拆解成兩個函式:
displayDigit
: 負責 slider 中 R/G/B/A 個別數值顯示displayColorCode
: 負責不同色碼的顯示這裡會拆出來也是在更改的過程中,發現當我在添加 RGBA 的顯示時,即便不是拖曳透明度的 slider,數值也會跟著做變化,見識到不必要的耦合現象!!!
其他的邏輯部分和 Day24 的實作沒有太大的區別,所以以下直接看程式碼
// 轉換數值
function rgbToHex(R,G,B) {
const hexDigit = [R, G, B].map( item => {
return Number(item).toString(16).padStart(2, '0')
}).join('');
return '#'+ hexDigit;
}
// 顯示 slider 個別數值
function displayDigits(e) {
const currentValue = e.target.value;
const alphaValue = currentValue;
e.target.nextElementSibling.innerHTML = currentValue;
}
// 顯示顏色的不同表示法
function displayColorCode() {
const hexValue = (rgbToHex(red.value, green.value, blue.value)).toUpperCase();
const hexIndicator = get('.hex').children[1];
const rgbIndicator = get('.rgb').children[1];
const rgbaIndicator = get('.rgba').children[1];
hexIndicator.innerHTML = hexValue;
rgbIndicator.innerHTML = `RGB(${red.value},${green.value},${blue.value})`;
rgbaIndicator.innerHTML = `RGBA(${red.value},${green.value},${blue.value},${alpha.value})`;
}
//改變圓形圖的顏色
function changeColor() {
const hexColorPad = get('.hex').children[0];
const rgbColorPad = get('.rgb').children[0];
const rgbaColorPad = get('.rgba').children[0];
hexColorPad.style.backgroundColor = `rgb(${red.value},${green.value},${blue.value})`;
rgbColorPad.style.backgroundColor = `rgb(${red.value},${green.value},${blue.value})`;
rgbaColorPad.style.backgroundColor = `rgba(${red.value},${green.value},${blue.value}, ${alpha.value})`;
}
//對 slider綁定事件監聽器
rangeSliders.forEach(rangeSlider => {
//監聽並改變RGB個別代碼
rangeSlider.addEventListener('mousemove', displayDigits);
//監聽並改變所有色碼表示法
rangeSlider.addEventListener('mousemove', displayColorCode);
//監聽並改變背景顏色
rangeSlider.addEventListener('mousemove', changeColor);
})
copy函式
changeDisplay函式
//做複製的功能
const buttons = getAll('.colorCode');
function copy() {
const range = document.createRange();
range.selectNode(this);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
selection.removeAllRanges();
}
// 改變顏色和文字內容
function changeDisplay(e){
e.target.style.backgroundColor = `rgb(247,157,128)`;
e.target.innerHTML = `複製好色碼囉~`;
reset(e);
}
// 兩秒後會回復到先前的狀態
function reset(e){
setTimeout(()=> {
e.target.style.backgroundColor = `rgb(78,199,207)`;
displayColorCode();
}, 2000)
}
//對按鈕綁定事件監聽
buttons.forEach(button => {
button.addEventListener('click', copy);
button.addEventListener('click', changeDisplay);
});
完成~~~codepen連結
一開始只是為了回應饅頭大大的一句話,想不到因而學習到瀏覽器的複製功該如何實作,也在增加功能的過程中再次體會到拆函式的重要性,不好好將函式拆好的下場就是改了 A 動了B,不斷有出其不意的驚喜(令人崩潰的那種XD)
透過觀察線上的色碼轉換器所包含的功能,想想這些功能是怎麼實作出來的,再逐步找相應語法嘗試的過程真的很有趣~
謝謝神隊友的修改建議和提問~~
參考資料:
RGBA and Hex Color Converter
剪貼簿複製操作
那些被忽略但很好用的 Web API / Clipboard