Created
November 1, 2024 00:13
-
-
Save ntorga/16ba8f1c162206e0896234426fb35be1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function hexToRgbTransformer(originalHex) { | |
const redChannel = parseInt(originalHex.slice(1, 3), 16); | |
const greenChannel = parseInt(originalHex.slice(3, 5), 16); | |
const blueChannel = parseInt(originalHex.slice(5, 7), 16); | |
return { red: redChannel, green: greenChannel, blue: blueChannel }; | |
}; | |
function rgbChannelToHex(colorChannel) { | |
const positiveChannelValue = Math.max(0, colorChannel); | |
const normalizedChannelValue = Math.min(positiveChannelValue, 255); | |
const hexRepresentation = normalizedChannelValue.toString(16); | |
return hexRepresentation.padStart(2, '0'); | |
}; | |
function rgbToHexTransformer(red, green, blue) { | |
const redChannelHex = rgbChannelToHex(red); | |
const greenChannelHex = rgbChannelToHex(green); | |
const blueChannelHex = rgbChannelToHex(blue); | |
return "#" + redChannelHex + greenChannelHex + blueChannelHex; | |
}; | |
function shadeFactory(channelValue, maxChannelValue, approximationFactor) { | |
return Math.round( | |
channelValue + (maxChannelValue - channelValue) * approximationFactor | |
); | |
}; | |
function createColorScale(baseColorHex) { | |
if (!baseColorHex.startsWith('#')) { | |
baseColorHex = '#' + baseColorHex; | |
} | |
if (baseColorHex.length !== 7) { | |
throw new Error('InvalidHexColorFormat'); | |
} | |
const baseColorRgb = hexToRgbTransformer(baseColorHex); | |
const scaleShadeFactors = { | |
50: 0.95, | |
100: 0.85, | |
200: 0.75, | |
300: 0.55, | |
400: 0.30, | |
500: 0, | |
600: 0.15, | |
700: 0.30, | |
800: 0.45, | |
900: 0.60, | |
950: 0.75 | |
}; | |
const colorScale = { | |
500: baseColorHex | |
}; | |
const blackChannelValue = 0; | |
const whiteChannelValue = 255; | |
for (const [shadeId, shadeFactor] of Object.entries(scaleShadeFactors)) { | |
if (shadeId === '500') { | |
continue; | |
} | |
const isLighterShade = parseInt(shadeId) < 500; | |
const maxChannelValue = isLighterShade ? whiteChannelValue : blackChannelValue; | |
const redChannel = shadeFactory(baseColorRgb.red, maxChannelValue, shadeFactor); | |
const greenChannel = shadeFactory(baseColorRgb.green, maxChannelValue, shadeFactor); | |
const blueChannel = shadeFactory(baseColorRgb.blue, maxChannelValue, shadeFactor); | |
colorScale[shadeId] = rgbToHexTransformer(redChannel, greenChannel, blueChannel); | |
} | |
return colorScale; | |
}; | |
// Test with a few colors: | |
const testColors = ['#978b84', '#d75c77', '#438e96']; | |
testColors.forEach(baseColor => { | |
console.log(`\nGenerated scale for ${baseColor}:`); | |
const colorScale = createColorScale(baseColor); | |
Object.entries(colorScale).forEach(([shade, color]) => { | |
console.log(`${shade}: ${color}`); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment