- Published on
踏入自媒體的 30 天 - Day 11
- Authors
-
-
- Name
- Jyhwoei Yang (Tom)
- @tomz12321
- Sr. Front End Developer at Pimwa Corp. (Australia) / Deliostech (USA)
-
Day #11
前言
30 days 的開始 踏入自媒體的 30 天❗️- 我有個朋友在做自媒體
Image
Here we go :
默默小語
最近開始用 JS 刷題, 但是同時建立基礎知識也是很重要的。
正文開始
今天要來演示 5 mins 快速地做一個 Chrome Extension 的微專案。
以下會用到的工具只會有
- 網頁前端三劍客 HTML / CSS / JavaScript
- 一個 IDE,我自己是用 VS Code
- 一個 Browser (e.g. Chrome)
- Terminal 終端機 (macOS bashshell)
首先我們先照著下面的專案架構
建立一組 網頁前端三劍客。
- index.html
- index.js
- style.css
使用 mac 內建的 bashshell 快速做法
#!/bin/bash
mkdir simple-color-picker
cd simple-color-picker/
touch index.html
touch index.js
touch style.css
拷貝,然後存成 create-simple-app.sh
之後執行
$ chmod 777 ./create-simple-app.sh
再執行
$ ./create-simple-app.sh
做完以後,你就會得到一個以下的專案結構
Project Structure
/simple-color-picker
├── index.html
├── index.js
└── style.css
剩下的就是打開 IDE 照著打
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Chrome Color Picker Extension | Tomzyang</title>
</head>
<body>
<div class="container">
<div class="picker">
<button id="picker-btn">Pick Color</button>
<button id="export-btn">Export Colors</button>
</div>
<div class="colors-list hide">
<header>
<p class="title">Picked Colors</p>
<span id="clear-btn">Clear All</span>
</header>
<ul class="all-colors"></ul>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
或著就直接複製 code 貼上。
- index.js
const pickerBtn = document.querySelector("#picker-btn");
const clearBtn = document.querySelector("#clear-btn");
const colorList = document.querySelector(".all-colors");
const exportBtn = document.querySelector("#export-btn");
// Retrieving picked colors from localstorage or initializing an empty array
let pickedColors = JSON.parse(localStorage.getItem("colors-list")) || [];
// Variable to keep track of the current color popup
let currentPopup = null;
// Function to copy text to the clipboard
const copyToClipboard = async (text, element) => {
try {
await navigator.clipboard.writeText(text);
element.innerText = "Copied!";
// Resseting element text after 1 second
setTimeout(() => {
element.innerText = text;
}, 1000);
} catch (error) {
alert("Filed to copy text!");
}
};
// Function to export colors as text file
const exportColors = () => {
const colorText = pickedColors.join("\n");
const blob = new Blob([colorText], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "Colors.txt";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
};
// Function to create the color popup
const createColorPopup = (color) => {
const popup = document.createElement("div");
popup.classList.add("color-popup");
popup.innerHTML = `
<div class="color-popup-content">
<span class="close-popup">x</span>
<div class="color-info">
<div class="color-preview" style="background: ${color};"></div>
<div class="color-details">
<div class="color-value">
<span class="label">Hex:</span>
<span class="value hex" data-color="${color}">${color}</span>
</div>
<div class="color-value">
<span class="label">RGB:</span>
<span class="value rgb" data-color="${color}">${hexToRgb(color)}</span>
</div>
</div>
</div>
</div>
`;
// Close button inside the popup
const closePopup = popup.querySelector(".close-popup");
closePopup.addEventListener('click', () => {
document.body.removeChild(popup);
currentPopup = null;
});
// Event listeners to copy color values to clipboard
const colorValues = popup.querySelectorAll(".value");
colorValues.forEach((value) => {
value.addEventListener('click', (e) => {
const text = e.currentTarget.innerText;
copyToClipboard(text, e.currentTarget);
});
});
return popup;
};
// Function to display the picked colors
const showColors = () => {
colorList.innerHTML = pickedColors.map((color) =>
`
<li class="color">
<span class="rect" style="background: ${color}; border: 1px solid ${color === "#ffffff" ? "#ccc" : color}"></span>
<span class="value hex" data-color="${color}">${color}</span>
</li>
`
).join("");
const colorElements = document.querySelectorAll(".color");
colorElements.forEach((li) => {
const colorHex = li.querySelector(".value.hex");
colorHex.addEventListener('click', (e) => {
const color = e.currentTarget.dataset.color;
if (currentPopup) {
document.body.removeChild(currentPopup);
}
const popup = createColorPopup(color);
document.body.appendChild(popup);
currentPopup = popup;
});
});
const pickedColorsContainer = document.querySelector(".colors-list");
pickedColorsContainer.classList.toggle("hide", pickedColors.length === 0);
};
// Function to convert a hex color code to rgb format
const hexToRgb = (hex) => {
const bigint = parseInt(hex.slice(1), 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return `rgb(${r}, ${g}, ${b})`;
};
// Function to activate the eye dropper color picker
const activateEyeDropper = async () => {
document.body.style.display = "none";
try {
// Opening the eye dropper and retrieving the selected color
const { sRGBHex } = await new EyeDropper().open();
if (!pickedColors.includes(sRGBHex)) {
pickedColors.push(sRGBHex);
localStorage.setItem("colors-list", JSON.stringify(pickedColors));
}
showColors();
} catch (error) {
alert("Filed to copy the color code!");
} finally {
document.body.style.display = "block";
}
};
// Function to clear all picked colors
const clearAllColors = () => {
pickedColors = [];
localStorage.removeItem("colors-list");
showColors();
};
// Event listeners for buttons
clearBtn.addEventListener('click', clearAllColors);
pickerBtn.addEventListener('click', activateEyeDropper);
exportBtn.addEventListener('click', exportColors);
// Displaying picked colors on document load
showColors();
- style.css
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
.container{
background-color: #fff;
width: 350px;
}
.container :where(.picker, header, .all-colors){
display: flex;
align-items: center;
border-radius: 0 0 35px 35px;
}
.container .picker{
padding: 35px 0;
background-color: #c8e6c9;
justify-content: center;
}
.picker #picker-btn{
margin-right: 8px;
}
.picker #picker-btn, .picker #export-btn{
border: none;
outline: none;
color: #fff;
font-size: 1rem;
cursor: pointer;
padding: 6px 12px;
background-color: #43a047;
border-radius: 5px;
transition: all 0.3s ease;
}
.picker #picker-btn:hover, .picker #export-btn:hover{
background-color: #2e7d32;
}
.colors-list{
margin: 10px 15px;
}
.colors-list header{
justify-content: space-between;
}
header .title{
font-size: 1rem;
}
header #clear-btn{
cursor: pointer;
font-size: 0.9rem;
color: #43a047;
}
header #clear-btn:hover{
color: #2e7d32;
}
.colors-list.hide{
display: none;
}
.colors-list .all-colors{
flex-wrap: wrap;
list-style: none;
margin: 10px 0 0;
}
.all-colors .color{
display: flex;
cursor: pointer;
margin-bottom: 10px;
width: calc(100% / 3);
}
.all-colors .rect{
height: 22px;
width: 22px;
display: block;
margin-right: 3px;
border-radius: 3px;
}
.all-colors .color span{
font-size: 0.86rem;
font-weight: 500;
text-transform: uppercase;
}
.color-popup{
position: fixed;
top: 52px;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
z-index: 9999;
}
.color-popup-content{
padding: 20px;
}
.color-info{
display: flex;
align-items: center;
}
.color-preview{
width: 50px;
height: 50px;
border-radius: 5px;
margin-right: 10px;
}
.color-details{
flex-grow: 1;
}
.color-value{
display: flex;
align-items: center;
margin-bottom: 5px;
}
.label{
font-weight: bold;
margin-right: 5px;
}
.value{
cursor: pointer;
}
span.close-popup{
font-size: 14px;
cursor: pointer;
float: right;
}
然後你會需要一個 manifest.json
{
"manifest_version": 3,
"name": "Color Picker",
"description": "Simple Color Picker Extension that we created. Pick any color on web page, Picked Colors history, Copy RGB and Hex or Clear them with a single click.",
"version": "1.0",
"action": {
"default_popup": "index.html"
},
"icons": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
我們需要新增一個,/icons
資料夾,放 icons
-
來這邊下載我們會用到的 icons - (載點)
-
接下來的步驟比較複雜,會用到 Chrome 的 Developer Mode
Chrome 開啟一個分頁。在網址列輸入:
chrome://extensions/
跟上了
-
右上角開啟 Developer Mode
-
開啟以後,在左上角找到
Load unpacked
按鈕 -
選擇你的專案資料夾擺放位置
-
開啟 Extensions 並釘選你剛剛新加入的 Extension - Color Picker
-
如果以上都完成了:
最終成果,我們會得到一個 Color Picker 的 Extension。 有了這個小工具,我們就可以在任意網頁上找任意格點的顏色代碼了。
複習一下我們以上學習了什麼:
- Terminal 用法
- bashshell 寫 script
- 了解網頁三劍客之間的關係
- 了解怎麼在 local 端,開發一個 Chrome Extension
以上 5 mins 內快速完成一個 Color Picker。
如果大家對這個主題有興趣的話,
找時間,我們可以再來 Speed Run 一輪,下次手刻一台計算機
(XD)。
完整 Github Repo - (傳送門)
參考資料
對啊我是一個宅宅工程師,
找人一起 code 是我的日常。
🔻支持打賞🔻
Welcome to my github - [https://github.com/tomz12321]
喜歡的話,隨便找個專案給顆星。