<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
</head>
<body>
<style>
:root {
color-scheme: light dark;
font-family: Menlo, monospace;
}
body {
margin: 0;
}
main {
width: -webkit-fit-content;
margin: 0 auto;
padding: 1em;
text-align: center;
}
main > canvas {
margin: 1em;
border: 1px solid grey;
}
main > div {
padding: 1em;
}
main > div > * {
margin: 0.2em;
}
select + div {
display: flex;
justify-content: center;
align-items: center;
}
label {
display: flex;
align-items: center;
}
label + label {
-webkit-margin-start: 1em;
}
label > input {
font-family: inherit;
}
main > input {
width: 100%;
margin-top: 2em;
font-family: inherit;
font-size: 1em;
text-align: center;
border: none;
outline: none;
-webkit-appearance: none;
}
:matches(.rgb, .hsl, .rgba, .hsla) input {
text-align: right;
}
</style>
<script>
let mainElement = document.body.appendChild(document.createElement("main"));
mainElement.appendChild(document.createElement("h1")).textContent = "Remove Alpha";
let canvas = mainElement.appendChild(document.createElement("canvas"));
canvas.width = 200;
canvas.height = 200;
let context = canvas.getContext("2d");
let backgroundColor = null;
let foregroundColor = null;
function recalculate() {
context.fillStyle = backgroundColor;
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = foregroundColor;
context.fillRect(0, 0, canvas.width, canvas.height);
let [r, g, b, a] = context.getImageData(canvas.width / 2, canvas.height / 2, 1, 1).data;
console.assert(a === 255);
resultInputElement.value = `rgb(${r}, ${g}, ${b})`;
}
function createInput(label, type, min, max, step, /* handleInput */) {
let handleInput = arguments[arguments.length - 1];
let labelElement = document.createElement("label");
labelElement.appendChild(document.createTextNode(label));
labelElement.className = label.toLowerCase();
let inputElement = labelElement.appendChild(document.createElement("input"));
inputElement.type = type;
if (inputElement.type === "number") {
inputElement.min = min;
inputElement.max = max;
inputElement.step = step;
}
inputElement.addEventListener("input", handleInput);
return {labelElement, inputElement};
}
function getInputKey(input) {
let key = "";
for (let node = input.inputElement; node && node !== mainElement; node = node.parentNode) {
if (node.className)
key = node.className + (key ? "-" + key : "");
}
return key;
}
function resetInput(input, value) {
let key = getInputKey(input);
if (key in window.localStorage)
value = window.localStorage.getItem(key);
input.inputElement.value = input.inputElement.placeholder = value;
}
function parseInput(input) {
let value = input.inputElement.value.trim();
if (input.inputElement.type === "number") {
value = parseFloat(value);
if (isNaN(value))
value = parseFloat(input.inputElement.placeholder);
}
if (!value)
value = input.inputElement.placeholder;
window.localStorage.setItem(getInputKey(input), value);
return value;
}
/* ====================== */
/* ===== Background ===== */
/* ====================== */
let backgroundContainer = mainElement.appendChild(document.createElement("div"));
backgroundContainer.className = "background";
backgroundContainer.appendChild(document.createElement("div")).textContent = "Background";
let backgroundFormatSelectElement = backgroundContainer.appendChild(document.createElement("select"));
backgroundFormatSelectElement.appendChild(document.createElement("option")).textContent = "HSL";
backgroundFormatSelectElement.appendChild(document.createElement("option")).textContent = "RGB";
backgroundFormatSelectElement.appendChild(document.createElement("option")).textContent = "HEX";
let backgroundInputsContainer = backgroundContainer.appendChild(document.createElement("div"));
function handleBackgroundHSLInput(event) {
let h = parseInput(backgroundInputH);
let s = parseInput(backgroundInputS);
let l = parseInput(backgroundInputL);
backgroundColor = `hsl(${h}, ${s}%, ${l}%)`;
recalculate();
}
let backgroundInputH = createInput("H", "number", 0, 100, 1, handleBackgroundHSLInput);
let backgroundInputS = createInput("S", "number", 0, 100, 1, handleBackgroundHSLInput);
let backgroundInputL = createInput("L", "number", 0, 100, 1, handleBackgroundHSLInput);
function handleBackgroundRGBInput(event) {
let r = parseInput(backgroundInputR);
let g = parseInput(backgroundInputG);
let b = parseInput(backgroundInputB);
backgroundColor = `rgb(${r}, ${g}, ${b})`;
recalculate();
}
let backgroundInputR = createInput("R", "number", 0, 255, 1, handleBackgroundRGBInput);
let backgroundInputG = createInput("G", "number", 0, 255, 1, handleBackgroundRGBInput);
let backgroundInputB = createInput("B", "number", 0, 255, 1, handleBackgroundRGBInput);
function handleBackgroundHEXInput(event) {
let hex = parseInput(backgroundInputHEX);
backgroundColor = `#${hex}`;
recalculate();
}
let backgroundInputHEX = createInput("#", "text", handleBackgroundHEXInput);
function handleBackgroundFormatInput(event) {
backgroundInputsContainer.textContent = "";
backgroundInputsContainer.className = backgroundFormatSelectElement.value.toLowerCase();
switch (backgroundFormatSelectElement.value) {
case "HSL":
backgroundInputsContainer.append(backgroundInputH.labelElement, backgroundInputS.labelElement, "%", backgroundInputL.labelElement, "%");
resetInput(backgroundInputH, 0);
resetInput(backgroundInputS, 0);
resetInput(backgroundInputL, 100);
handleBackgroundHSLInput();
break;
case "RGB":
backgroundInputsContainer.append(backgroundInputR.labelElement, backgroundInputG.labelElement, backgroundInputB.labelElement);
resetInput(backgroundInputR, 255);
resetInput(backgroundInputG, 255);
resetInput(backgroundInputB, 255);
handleBackgroundRGBInput();
break;
case "HEX":
backgroundInputsContainer.append(backgroundInputHEX.labelElement);
resetInput(backgroundInputHEX, "FFFFFF");
handleBackgroundHEXInput();
break;
}
}
backgroundFormatSelectElement.addEventListener("change", handleBackgroundFormatInput);
/* ====================== */
/* ===== Foreground ===== */
/* ====================== */
let foregroundContainer = mainElement.appendChild(document.createElement("div"));
foregroundContainer.className = "foreground";
foregroundContainer.appendChild(document.createElement("div")).textContent = "Foreground";
let foregroundFormatSelectElement = foregroundContainer.appendChild(document.createElement("select"));
foregroundFormatSelectElement.appendChild(document.createElement("option")).textContent = "HSLA";
foregroundFormatSelectElement.appendChild(document.createElement("option")).textContent = "RGBA";
foregroundFormatSelectElement.appendChild(document.createElement("option")).textContent = "HEXAlpha";
let foregroundInputsContainer = foregroundContainer.appendChild(document.createElement("div"));
function handleForegroundHSLAInput(event) {
let h = parseInput(foregroundInputH);
let s = parseInput(foregroundInputS);
let l = parseInput(foregroundInputL);
let a = parseInput(foregroundInputA_HSLA);
foregroundColor = `hsla(${h}, ${s}%, ${l}%, ${a})`;
recalculate();
}
let foregroundInputH = createInput("H", "number", 0, 100, 1, handleForegroundHSLAInput);
let foregroundInputS = createInput("S", "number", 0, 100, 1, handleForegroundHSLAInput);
let foregroundInputL = createInput("L", "number", 0, 100, 1, handleForegroundHSLAInput);
let foregroundInputA_HSLA = createInput("A", "number", 0, 1, 0.01, handleForegroundHSLAInput);
function handleForegroundRGBAInput(event) {
let r = parseInput(foregroundInputR);
let g = parseInput(foregroundInputG);
let b = parseInput(foregroundInputB);
let a = parseInput(foregroundInputA_RGBA);
foregroundColor = `rgba(${r}, ${g}, ${b}, ${a})`;
recalculate();
}
let foregroundInputR = createInput("R", "number", 0, 255, 1, handleForegroundRGBAInput);
let foregroundInputG = createInput("G", "number", 0, 255, 1, handleForegroundRGBAInput);
let foregroundInputB = createInput("B", "number", 0, 255, 1, handleForegroundRGBAInput);
let foregroundInputA_RGBA = createInput("A", "number", 0, 1, 0.01, handleForegroundRGBAInput);
function handleForegroundHEXAlphaInput(event) {
let hexalpha = parseInput(foregroundInputHEXAlpha);
foregroundColor = `#${hexalpha}`;
recalculate();
}
let foregroundInputHEXAlpha = createInput("#", "text", handleForegroundHEXAlphaInput);
function handleForegroundFormatInput(event) {
foregroundInputsContainer.textContent = "";
foregroundInputsContainer.className = foregroundFormatSelectElement.value.toLowerCase();
switch (foregroundFormatSelectElement.value) {
case "HSLA":
foregroundInputsContainer.append(foregroundInputH.labelElement, foregroundInputS.labelElement, "%", foregroundInputL.labelElement, "%", foregroundInputA_HSLA.labelElement);
resetInput(foregroundInputH, 0);
resetInput(foregroundInputS, 100);
resetInput(foregroundInputL, 50);
resetInput(foregroundInputA_HSLA, 0.5);
handleForegroundHSLAInput();
break;
case "RGBA":
foregroundInputsContainer.append(foregroundInputR.labelElement, foregroundInputG.labelElement, foregroundInputB.labelElement, foregroundInputA_RGBA.labelElement);
resetInput(foregroundInputR, 255);
resetInput(foregroundInputG, 0);
resetInput(foregroundInputB, 0);
resetInput(foregroundInputA_RGBA, 0.5);
handleForegroundRGBAInput();
break;
case "HEXAlpha":
foregroundInputsContainer.append(foregroundInputHEXAlpha.labelElement);
resetInput(foregroundInputHEXAlpha, "FF00007F");
handleForegroundHEXAlphaInput();
break;
}
}
foregroundFormatSelectElement.addEventListener("change", handleForegroundFormatInput);
/* ================== */
/* ===== Result ===== */
/* ================== */
let resultInputElement = mainElement.appendChild(document.createElement("input"));
resultInputElement.spellcheck = false;
resultInputElement.addEventListener("mousedown", (event) => {
event.preventDefault();
resultInputElement.select();
document.execCommand("copy");
});
resultInputElement.addEventListener("input", (event) => {
event.preventDefault();
});
resultInputElement.addEventListener("paste", (event) => {
event.preventDefault();
});
handleBackgroundFormatInput();
handleForegroundFormatInput();
recalculate();
</script>
</body>
</html>