|
| 1 | +function hexToRgb(hex) { |
| 2 | + let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); |
| 3 | + return result |
| 4 | + ? { |
| 5 | + r: parseInt(result[1], 16), |
| 6 | + g: parseInt(result[2], 16), |
| 7 | + b: parseInt(result[3], 16), |
| 8 | + } |
| 9 | + : null; |
| 10 | +} |
| 11 | + |
| 12 | +function rgbToHex(r, g, b) { |
| 13 | + return ( |
| 14 | + "#" + |
| 15 | + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase() |
| 16 | + ); |
| 17 | +} |
| 18 | + |
| 19 | +function interpolateColor(startRgb, endRgb, factor) { |
| 20 | + return { |
| 21 | + r: Math.round(startRgb.r + factor * (endRgb.r - startRgb.r)), |
| 22 | + g: Math.round(startRgb.g + factor * (endRgb.g - startRgb.g)), |
| 23 | + b: Math.round(startRgb.b + factor * (endRgb.b - startRgb.b)), |
| 24 | + }; |
| 25 | +} |
| 26 | + |
| 27 | +// Function to generate the gradient |
| 28 | +function generateGradient(startHex, endHex, steps, middleHex = null) { |
| 29 | + const startRgb = hexToRgb(startHex); |
| 30 | + const endRgb = hexToRgb(endHex); |
| 31 | + const gradient = []; |
| 32 | + |
| 33 | + if (middleHex) { |
| 34 | + const middleRgb = hexToRgb(middleHex); |
| 35 | + const halfSteps = Math.floor(steps / 2); |
| 36 | + |
| 37 | + for (let i = 0; i < halfSteps; i++) { |
| 38 | + const factor = i / (halfSteps - 1); |
| 39 | + const color = interpolateColor(startRgb, middleRgb, factor); |
| 40 | + gradient.push(shortenHex(rgbToHex(color[0], color[1], color[2]))); |
| 41 | + } |
| 42 | + |
| 43 | + for (let i = 0; i < steps - halfSteps; i++) { |
| 44 | + const factor = i / (steps - halfSteps - 1); |
| 45 | + const color = interpolateColor(middleRgb, endRgb, factor); |
| 46 | + gradient.push(shortenHex(rgbToHex(color[0], color[1], color[2]))); |
| 47 | + } |
| 48 | + } else { |
| 49 | + for (let i = 0; i < steps; i++) { |
| 50 | + const factor = i / (steps - 1); |
| 51 | + const color = interpolateColor(startRgb, endRgb, factor); |
| 52 | + gradient.push(shortenHex(rgbToHex(color[0], color[1], color[2]))); |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + return gradient; |
| 57 | +} |
| 58 | + |
| 59 | +function shortenHex(hex) { |
| 60 | + // convert 6-digit hex color to 3-digit |
| 61 | + /* |
| 62 | + R = round(0xRR/0xFF*0xF) |
| 63 | + G = round(0xGG/0xFF*0xF) |
| 64 | + B = round(0xBB/0xFF*0xF) |
| 65 | + */ |
| 66 | + const r = Math.round((parseInt(hex.slice(1, 3), 16) / 255) * 15).toString(16); |
| 67 | + const g = Math.round((parseInt(hex.slice(3, 5), 16) / 255) * 15).toString(16); |
| 68 | + const b = Math.round((parseInt(hex.slice(5, 7), 16) / 255) * 15).toString(16); |
| 69 | + return `#${r}${g}${b}`.toUpperCase(); |
| 70 | +} |
| 71 | + |
| 72 | +const username = document.getElementById("username"); |
| 73 | +const startInput = document.getElementById("startColor"); |
| 74 | +const middleInput = document.getElementById("middleColor"); |
| 75 | +const endInput = document.getElementById("endColor"); |
| 76 | +const result = document.querySelector(".result"); |
| 77 | +const tmResult = document.querySelector("#tmResult"); |
| 78 | +const copy = document.querySelector("#copy"); |
| 79 | +const middleColorCheckbox = document.querySelector("#middleColorCheckbox"); |
| 80 | +function generateUsername() { |
| 81 | + const startColor = startInput.value; |
| 82 | + const middleColor = middleColorCheckbox.checked ? middleInput.value : null; |
| 83 | + const endColor = endInput.value; |
| 84 | + const name = username.value; |
| 85 | + console.log( |
| 86 | + `startColor: ${startColor}, middleColor: ${middleColor}, endColor: ${endColor}, name: ${name}` |
| 87 | + ); |
| 88 | + const minNameLength = middleColorCheckbox.checked ? 4 : 2; |
| 89 | + if (!startColor || !endColor || !name || name.length < minNameLength) return; |
| 90 | + const gradient = generateGradient( |
| 91 | + startColor, |
| 92 | + endColor, |
| 93 | + name.length, |
| 94 | + middleColor |
| 95 | + ); |
| 96 | + console.log(gradient); |
| 97 | + result.innerHTML = ""; |
| 98 | + tmResult.value = ""; |
| 99 | + for (let i = 0; i < name.length; i++) { |
| 100 | + result.innerHTML += `<span style="color: ${gradient[i]}; font-weight: bolder">${name[i]}</span>`; |
| 101 | + // the raw result, looks like this : $FF0[letter]$F0F[letter] |
| 102 | + tmResult.value += `$${gradient[i].slice(1)}${name[i]}`; |
| 103 | + } |
| 104 | +} |
| 105 | +username.addEventListener("input", generateUsername); |
| 106 | +startInput.addEventListener("input", generateUsername); |
| 107 | +middleInput.addEventListener("input", () => { |
| 108 | + middleColorCheckbox.checked = true; |
| 109 | + generateUsername(); |
| 110 | +}); |
| 111 | +endInput.addEventListener("input", generateUsername); |
| 112 | +middleColorCheckbox.addEventListener("change", generateUsername); |
| 113 | + |
| 114 | +copy.addEventListener("click", function () { |
| 115 | + navigator.clipboard.writeText(tmResult.value); |
| 116 | +}); |
0 commit comments