added chrome and balloon strings. updated colors

This commit is contained in:
chris 2025-06-29 23:57:17 -04:00
parent ac2e0b75b2
commit 126f7b05f1
13 changed files with 256 additions and 57 deletions

View File

@ -114,14 +114,72 @@
{ {
"family": "Chrome Colors", "family": "Chrome Colors",
"colors": [ "colors": [
{ "name": "Chrome Gold", "hex": "#39FF14", "metallic": true, "chromeType": "gold" }, {
{ "name": "Chrome Silver", "hex": "#a8a9a4", "metallic": true, "chromeType": "silver" }, "name": "Chrome Gold",
{ "name": "Chrome Rose Gold", "hex": "#FFBF00", "metallic": true, "chromeType": "rosegold" }, "hex": "#a18b67",
{ "name": "Chrome Champagne", "hex": "#FF1DCE", "metallic": true, "chromeType": "champagne" }, "metallic": true,
{ "name": "Chrome Blue", "hex": "#2d576f", "metallic": true, "chromeType": "blue" }, "chromeType": "gold",
{ "name": "Chrome Purple", "hex": "#DFFF00", "metallic": true, "chromeType": "purple" }, "image": "images/chrome-gold.png"
{ "name": "Chrome Green", "hex": "#457066", "metallic": true, "chromeType": "green" } },
{
"name": "Chrome Champagne",
"hex": "#FF1DCE",
"metallic": true,
"chromeType": "champagne",
"image": "images/chrome-champagne.png"
},
{
"name": "Chrome Silver",
"hex": "#a8a9a4",
"metallic": true,
"chromeType": "silver",
"image": "images/chrome-silver.png"
},
{
"name": "Chrome Rose Gold",
"hex": "#FFBF00",
"metallic": true,
"chromeType": "rosegold",
"image": "images/chrome-rosegold.png"
},
{
"name": "Chrome Pink",
"hex": "#FFBF00",
"metallic": true,
"chromeType": "rosegold",
"image": "images/chrome-pink.png"
},
{
"name": "Chrome Truffel",
"hex": "#FF1DCE",
"metallic": true,
"chromeType": "champagne",
"image": "images/chrome-truffel.png"
},
{
"name": "Chrome Blue",
"hex": "#2d576f",
"metallic": true,
"chromeType": "blue",
"image": "images/chrome-blue.png"
},
{
"name": "Chrome Purple",
"hex": "#DFFF00",
"metallic": true,
"chromeType": "purple",
"image": "images/chrome-purple.png"
},
{
"name": "Chrome Green",
"hex": "#457066",
"metallic": true,
"chromeType": "green",
"image": "images/chrome-green.png"
}
] ]
} }
] ]

BIN
images/chrome-blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
images/chrome-champagne.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
images/chrome-gold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
images/chrome-green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
images/chrome-pink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
images/chrome-purple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
images/chrome-rosegold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
images/chrome-silver.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
images/chrome-truffel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -15,6 +15,14 @@
</header> </header>
<div id="selected-palette"> <div id="selected-palette">
<h2>Your Palette</h2> <h2>Your Palette</h2>
<div id="palette-controls">
<label class="switch">
<input type="checkbox" id="toggle-animation" checked>
<span class="slider"></span>
</label>
<button id="shuffle-palette" title="Shuffle Palette">🔀</button>
</div>
<div id="palette-colors"></div> <div id="palette-colors"></div>
<button id="clear-palette">Clear Palette</button> <button id="clear-palette">Clear Palette</button>
</div> </div>

112
script.js
View File

@ -23,23 +23,26 @@ fetch('colors.json')
const backgroundDiv = document.createElement('div'); const backgroundDiv = document.createElement('div');
backgroundDiv.classList.add('color-background'); backgroundDiv.classList.add('color-background');
if (color.image) {
backgroundDiv.style.backgroundImage = `url(${color.image})`;
backgroundDiv.style.backgroundSize = 'cover';
backgroundDiv.style.backgroundPosition = 'center';
} else {
backgroundDiv.style.backgroundColor = color.hex; backgroundDiv.style.backgroundColor = color.hex;
}
if (color.metallic && color.chromeType) { if (color.metallic && color.chromeType) {
backgroundDiv.classList.add('metallic', `chrome-${color.chromeType}`); backgroundDiv.classList.add('metallic', `chrome-${color.chromeType}`);
} }
const metallicNames = ["Gold", "Silver", "Rose Gold", "Hot Magenta"];
if (metallicNames.includes(color.name)) {
backgroundDiv.classList.add('metallic');
}
if (isLightColor(color.hex)) { if (isLightColor(color.hex)) {
backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)'; backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)';
} }
swatch.appendChild(backgroundDiv); swatch.appendChild(backgroundDiv);
const shineImg = document.createElement('img'); const shineImg = document.createElement('img');
shineImg.classList.add('color-shine'); shineImg.classList.add('color-shine');
shineImg.src = "shine.svg"; shineImg.src = "shine.svg";
@ -49,14 +52,13 @@ fetch('colors.json')
const colorName = document.createElement('span'); const colorName = document.createElement('span');
colorName.classList.add('color-name'); colorName.classList.add('color-name');
colorName.textContent = color.name; colorName.textContent = color.name;
colorName.title = color.name;
swatch.addEventListener('click', () => { swatch.addEventListener('click', () => {
const isSelected = selectedPalette.some(c => c.hex === color.hex); const isSelected = selectedPalette.some(c => c.hex === color.hex);
if (isSelected) { if (isSelected) {
selectedPalette = selectedPalette.filter(c => c.hex !== color.hex); selectedPalette = selectedPalette.filter(c => c.hex !== color.hex);
} else { } else {
selectedPalette.push({ name: color.name, hex: color.hex, metallic: color.metallic, chromeType: color.chromeType }); selectedPalette.push(color);
} }
backgroundDiv.classList.add('pop'); backgroundDiv.classList.add('pop');
@ -82,10 +84,8 @@ fetch('colors.json')
}) })
.catch(error => console.error('Error loading colors:', error)); .catch(error => console.error('Error loading colors:', error));
function renderSelectedPalette() { function renderSelectedPalette() {
const paletteColorsContainer = document.getElementById('palette-colors'); const paletteColorsContainer = document.getElementById('palette-colors');
const previousHeight = paletteColorsContainer.offsetHeight;
paletteColorsContainer.innerHTML = ''; paletteColorsContainer.innerHTML = '';
selectedPalette.forEach(color => { selectedPalette.forEach(color => {
@ -96,20 +96,21 @@ function renderSelectedPalette() {
swatch.classList.add('color-swatch', 'balloon-float'); swatch.classList.add('color-swatch', 'balloon-float');
swatch.dataset.color = color.hex; swatch.dataset.color = color.hex;
// Randomize animation const duration = (Math.random() * 3 + 3).toFixed(2) + 's';
const duration = (Math.random() * 3 + 3).toFixed(2) + 's'; // 3s6s
const delay = (Math.random() * 2).toFixed(2) + 's'; const delay = (Math.random() * 2).toFixed(2) + 's';
swatch.style.animationDuration = duration; swatch.style.animationDuration = duration;
swatch.style.animationDelay = delay; swatch.style.animationDelay = delay;
// Optional random float rotation direction
const rotate = Math.random() > 0.5 ? 'rotate(-3deg)' : 'rotate(3deg)';
swatch.style.transform = rotate;
const backgroundDiv = document.createElement('div'); const backgroundDiv = document.createElement('div');
backgroundDiv.classList.add('color-background'); backgroundDiv.classList.add('color-background', 'chosen');
if (color.image) {
backgroundDiv.style.backgroundImage = `url(${color.image})`;
backgroundDiv.style.backgroundSize = 'cover';
backgroundDiv.style.backgroundPosition = 'center';
} else {
backgroundDiv.style.backgroundColor = color.hex; backgroundDiv.style.backgroundColor = color.hex;
}
if (isLightColor(color.hex)) { if (isLightColor(color.hex)) {
backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)'; backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)';
@ -119,9 +120,25 @@ function renderSelectedPalette() {
backgroundDiv.classList.add('metallic', `chrome-${color.chromeType}`); backgroundDiv.classList.add('metallic', `chrome-${color.chromeType}`);
} }
backgroundDiv.classList.add('chosen');
swatch.appendChild(backgroundDiv); swatch.appendChild(backgroundDiv);
const svgString = `
<svg class="balloon-string" viewBox="0 0 10 100" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
<path d="M5 0 Q3 20 5 40 Q7 60 5 80 Q3 90 5 100" stroke="#333" fill="none" stroke-width="1" />
</svg>
`;
if (animationsEnabled) {
swatch.classList.add('balloon-float');
const duration = (Math.random() * 3 + 3).toFixed(2) + 's';
const delay = (Math.random() * 2).toFixed(2) + 's';
swatch.style.animationDuration = duration;
swatch.style.animationDelay = delay;
} else {
swatch.classList.remove('balloon-float');
swatch.style.animation = 'none';
}
swatch.insertAdjacentHTML('beforeend', svgString);
const shineImg = document.createElement('img'); const shineImg = document.createElement('img');
shineImg.classList.add('color-shine'); shineImg.classList.add('color-shine');
shineImg.src = "shine.svg"; shineImg.src = "shine.svg";
@ -142,14 +159,8 @@ function renderSelectedPalette() {
swatchWrapper.appendChild(colorName); swatchWrapper.appendChild(colorName);
paletteColorsContainer.appendChild(swatchWrapper); paletteColorsContainer.appendChild(swatchWrapper);
}); });
const newHeight = paletteColorsContainer.scrollHeight;
paletteColorsContainer.style.maxHeight = previousHeight + 'px';
void paletteColorsContainer.offsetWidth;
paletteColorsContainer.style.maxHeight = newHeight + 'px';
} }
function updateSwatchHighlights() { function updateSwatchHighlights() {
const allSwatches = document.querySelectorAll('#color-families .color-swatch'); const allSwatches = document.querySelectorAll('#color-families .color-swatch');
@ -169,23 +180,54 @@ function updateSwatchHighlights() {
}); });
} }
function isLightColor(hex) {
const rgb = hex.replace('#', '').match(/.{1,2}/g).map(x => parseInt(x, 16));
const brightness = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;
return brightness > 220;
}
document.getElementById('clear-palette').addEventListener('click', () => { document.getElementById('clear-palette').addEventListener('click', () => {
selectedPalette = []; selectedPalette = [];
renderSelectedPalette(); renderSelectedPalette();
updateSwatchHighlights(); updateSwatchHighlights();
}); });
window.addEventListener('scroll', () => {
const palette = document.getElementById('selected-palette');
if (window.scrollY > 0) { // Toggle balloon animation globally
palette.classList.add('stuck'); document.getElementById('toggle-animation').addEventListener('click', () => {
} else { animationsEnabled = !animationsEnabled;
palette.classList.remove('stuck'); renderSelectedPalette(); // re-render with or without animation
}
}); });
function isLightColor(hex) { // Shuffle selected palette
const rgb = hex.replace('#', '').match(/.{1,2}/g).map(x => parseInt(x, 16)); document.getElementById('shuffle-palette').addEventListener('click', () => {
const brightness = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; selectedPalette = shuffleArray(selectedPalette);
return brightness > 220; renderSelectedPalette();
updateSwatchHighlights();
});
function shuffleArray(array) {
// FisherYates Shuffle
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
} }
return array;
}
let animationsEnabled = true;
// Handle toggle switch
document.getElementById('toggle-animation').addEventListener('change', (e) => {
animationsEnabled = e.target.checked;
renderSelectedPalette();
});
// Shuffle button
document.getElementById('shuffle-palette').addEventListener('click', () => {
selectedPalette = shuffleArray(selectedPalette);
renderSelectedPalette();
updateSwatchHighlights();
});

111
style.css
View File

@ -262,6 +262,8 @@ background-image: url("https://www.transparenttextures.com/patterns/asfalt-light
/* overflow: hidden; /*Hide overflow text if necessary */ /* overflow: hidden; /*Hide overflow text if necessary */
text-overflow: ellipsis; /* Add ... when text is too long */ text-overflow: ellipsis; /* Add ... when text is too long */
max-width: 90%; max-width: 90%;
background-color: #e8e8e8;
z-index: 1;
} }
#palette-colors .color-swatch { #palette-colors .color-swatch {
@ -332,13 +334,13 @@ background-image: url("https://www.transparenttextures.com/patterns/asfalt-light
.metallic { .metallic {
position: relative; position: relative;
border: 1px solid rgba(255, 255, 255, 0.3); border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: inset 1px 1px 4px rgba(255, 255, 255, 0.6), /* box-shadow: inset 1px 1px 4px rgba(255, 255, 255, 0.6),
0 2px 4px rgba(0, 0, 0, 0.3); 0 2px 4px rgba(0, 0, 0, 0.3); */
overflow: hidden; overflow: hidden;
} }
/* Highlight overlay */ /* Highlight overlay */
.metallic::after { .metallic1::after {
content: ''; content: '';
position: absolute; position: absolute;
top: 15%; top: 15%;
@ -353,7 +355,7 @@ background-image: url("https://www.transparenttextures.com/patterns/asfalt-light
/* Specific chrome variants */ /* Specific chrome variants */
.chrome-gold { .chrome-gold {
background: linear-gradient(145deg, #fefcea, #f1da36, #b29600, #fefcea); background: linear-gradient(145deg, #fefcea, #b69978, #a18b67, #806748);
} }
.chrome-silver { .chrome-silver {
@ -382,17 +384,106 @@ background-image: url("https://www.transparenttextures.com/patterns/asfalt-light
@keyframes balloonFloat { @keyframes balloonFloat {
0%, 100% { transform: translateY(0) rotate(-3deg); } 0%, 100% { transform: translateY(0) rotate(-4deg); }
50% { transform: translateY(-20px) rotate(3deg); } 50% { transform: translateY(-25px) rotate(4deg); }
} }
.balloon-float { .balloon-float {
animation-name: balloonFloat; animation-name: balloonFloat;
animation-timing-function: ease-in-out; animation-timing-function: 4s ease-in-out;
animation-iteration-count: infinite; animation-iteration-count: infinite;
transform-origin: bottom center; transform-origin: bottom center;
position: relative; position: relative;
} }
.color-background {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.balloon-string {
width: 6px;
height: 45px;
position: absolute;
bottom: -45px;
left: 50%;
transform: translateX(-50%);
animation: stringWiggle 2s ease-in-out infinite;
}
@keyframes stringWiggle {
0%, 100% {
transform: translateX(-50%) rotate(0deg);
}
25% {
transform: translateX(-50%) rotate(1.5deg);
}
50% {
transform: translateX(-50%) rotate(-1.5deg);
}
75% {
transform: translateX(-50%) rotate(1deg);
}
}
#palette-controls {
position: absolute;
top: 10px;
right: 10px;
display: flex;
align-items: center;
gap: 10px;
z-index: 200;
}
/* Toggle Switch Styling */
.switch {
position: relative;
display: inline-block;
width: 40px;
height: 20px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0; left: 0;
right: 0; bottom: 0;
background-color: #ccc;
transition: 0.4s;
border-radius: 20px;
}
.slider:before {
position: absolute;
content: "";
height: 14px;
width: 14px;
left: 3px;
bottom: 3px;
background-color: white;
transition: 0.4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: #4caf50;
}
input:checked + .slider:before {
transform: translateX(20px);
}
/* Shuffle Button */
#shuffle-palette {
font-size: 16px;
padding: 4px 8px;
border: none;
background: #f0f0f0;
border-radius: 6px;
cursor: pointer;
}