Skip to content

Instantly share code, notes, and snippets.

Created March 14, 2018 20:28
Show Gist options
  • Save anonymous/36bf8ad003379d1eb39ca23fcd975846 to your computer and use it in GitHub Desktop.
Save anonymous/36bf8ad003379d1eb39ca23fcd975846 to your computer and use it in GitHub Desktop.
<div class="controls">
<a href="#add-color">+ Add New Color</a>
<a href="#random-hue">Random Hue</a>
<input type="range" name="hue-adjustment" value="0" min="0" max="359" />
</div>
<div class="colors-wrapper">
<div class="colors">
<div class="color-wrapper">
<div class="color" style="background-color: #000; "><span class="hue-value"></span></div>
<input type="text" />
</div>
<div class="color-wrapper ">
<div class="color" style="background-color: #000; "><span class="hue-value"></span></div>
<input type="text" />
</div>
</div>
<div class="new-colors">
<div class="color-wrapper">
<div class="color " style="background-color: #000; "><span class="hue-value"></span></div>
<input type="text " />
</div>
<div class="color-wrapper">
<div class="color" style="background-color: #000; "><span class="hue-value"></span></div>
<input type="text" />
</div>
</div>
</div>
function createNewPalette() {
let hueVal = parseInt(document.querySelector('input[name="hue-adjustment"]').value, 10),
origColors = document.querySelectorAll('.colors .color'),
newColors = document.querySelectorAll('.new-colors .color'),
anchor = tinycolor(origColors[0].style.backgroundColor).toHsl(),
anchorHue = anchor.h;
//set the anchor colors hue to the value of our new anchor hue.
anchor.h = hueVal;
newColors[0].style.backgroundColor = tinycolor.fromRatio(anchor).toHexString();
newColors[0].parentNode.querySelector('input').value = tinycolor.fromRatio(anchor).toHexString();
for (let i = 1; i < origColors.length; i++) {
let cEle = origColors[i],
nEle = newColors[i],
c = tinycolor(cEle.style.backgroundColor).toHsl(),
n = tinycolor(nEle.style.backgroundColor).toHsl(),
//calculate the hue distance between the previous color and the current color
dist = Math.round(c.h - anchorHue);
//set our new color hue to our previous new color hue + distance we only adjust the hue now because reasons. Really limits the overall number of colors.
c.h = hueVal + dist;
if (c.h < 0)
c.h += 360;
else if (c.h > 360)
c.h -= 360;
//update our dom colors
nEle.style.backgroundColor = tinycolor.fromRatio(c).toHexString();
nEle.parentNode.querySelector('input').value = tinycolor.fromRatio(c).toHexString();
}
updateHueValues();
}
function contrastText(color) {
let rgb = color.toRgb();
return Math.round((rgb.r * 299) + (rgb.g * 587) + (rgb.b * 114) / 1000) > 125 ? color.darken(30) : color.lighten(25);
}
function updateHueValues() {
let origColors = document.querySelectorAll('.colors .color'),
newColors = document.querySelectorAll('.new-colors .color');
for(let i=0; i < origColors.length; i++) {
let oColor = tinycolor(origColors[i].style.backgroundColor),
nColor = tinycolor(newColors[i].style.backgroundColor),
oVal = Math.round(oColor.toHsl().h),
nVal = Math.round(nColor.toHsl().h);
oColor = contrastText(oColor);
nColor = contrastText(nColor);
origColors[i].style.color = oColor.toHexString();
newColors[i].style.color = nColor.toHexString();
origColors[i].querySelector('.hue-value').innerText = oVal;
newColors[i].querySelector('.hue-value').innerText = nVal;
}
}
function addHandlers() {
let link = document.querySelector('a[href="#add-color"]'),
randomLink = document.querySelector('a[href="#random-hue"]'),
hue = document.querySelector('input[name="hue-adjustment"]');
randomLink.addEventListener('click', (e) => {
let newHue = Math.floor(Math.random() * 360);
document.querySelector('input[name="hue-adjustment"]').value = newHue;
createNewPalette();
});
link.addEventListener('click', (e) => {
let newColor = document.createElement('div'),
count = document.querySelectorAll('.colors .color-wrapper').length,
color = getRandomColor();
newColor.innerHTML = '<div class="color"><span class="hue-value"></span></div><input type="text" />';
newColor.querySelector('.color').style.backgroundColor = color;
newColor.querySelector('input').value = color;
newColor.classList.add('color-wrapper');
newColor.setAttribute('data-pos', count);
document.querySelector('.colors').appendChild(newColor);
document.querySelector('.new-colors').appendChild(newColor.cloneNode(true));
newColor.querySelector('input').addEventListener('input', changeColor);
createNewPalette();
e.preventDefault();
return false;
});
hue.addEventListener('input', createNewPalette);
}
function setInitialColors() {
let origColors = document.querySelectorAll('.colors .color-wrapper'),
newColors = document.querySelectorAll('.new-colors .color-wrapper');
for (let i = 0; i < origColors.length; i++) {
let c = origColors[i],
n = newColors[i],
color = getRandomColor();
c.querySelector('.color').style.backgroundColor = color;
c.querySelector('input').value = color;
c.setAttribute('data-pos', i);
n.querySelector('input').setAttribute('readonly', 'readonly');
n.querySelector('.color').style.backgroundColor = color;
n.querySelector('input').value = color;
n.setAttribute('data-pos', i);
c.querySelector('input').addEventListener('input', changeColor);
}
createNewPalette();
}
function changeColor() {
let newColor = tinycolor(this.value);
if (newColor.isValid()) {
let color = this.parentNode.querySelector('.color');
color.style.backgroundColor = newColor.toHexString();
createNewPalette();
}
}
function getRandomColor() {
let r = Math.floor(Math.random() * 255),
g = Math.floor(Math.random() * 255),
b = Math.floor(Math.random() * 255);
return tinycolor(`rgb(${r}, ${g}, ${b}`).toHexString();
}
function init() {
addHandlers();
setInitialColors();
}
init();
* {
box-sizing: border-box;
}
.colors {
border-right: 1px solid #ccc;
}
.colors,
.new-colors {
display: flex;
flex: 1;
flex-wrap: wrap;
}
.colors-wrapper {
display: flex;
width: 100%;
}
.color-wrapper {
position: relative;
width: 50%;
padding: 15px;
}
.color-wrapper {
.color {
position: relative;
margin: 0 auto 10px;
width: 100%;
&:after {
display: block;
padding-top: 100%;
content: '';
}
.hue-value {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
input {
display: block;
width: 100%;
border: 1px solid #ccc;
border-radius: 20px;
outline: 0;
padding: 4px;
text-align: center;
text-transform: uppercase;
}
}
@media screen and (min-width: 500px) {
.color-wrapper {
width: 33.3333%;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment