let selectedPalette = []; let animationsEnabled = true; fetch('colors.json') .then(response => response.json()) .then(data => { const colorFamiliesContainer = document.getElementById('color-families'); data.forEach(family => { const familyDiv = document.createElement('div'); familyDiv.classList.add('color-family'); familyDiv.innerHTML = `

${family.family}

`; const swatchContainer = document.createElement('div'); swatchContainer.classList.add('swatch-container'); family.colors.forEach(color => { const swatchWrapper = document.createElement('div'); swatchWrapper.classList.add('swatch-wrapper'); const swatch = document.createElement('div'); swatch.classList.add('color-swatch'); swatch.dataset.color = color.hex; const backgroundDiv = document.createElement('div'); backgroundDiv.classList.add('color-background'); if (color.image) { backgroundDiv.style.backgroundImage = `url(${color.image})`; } else { backgroundDiv.style.backgroundColor = color.hex; } if (color.metallic && color.chromeType) { backgroundDiv.classList.add('metallic', `chrome-${color.chromeType}`); } if (isLightColor(color.hex)) { backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)'; } swatch.appendChild(backgroundDiv); const shineImg = document.createElement('img'); shineImg.classList.add('color-shine'); shineImg.src = "shine.svg"; shineImg.alt = ""; swatch.appendChild(shineImg); const colorName = document.createElement('span'); colorName.classList.add('color-name'); colorName.textContent = color.name; swatch.addEventListener('click', () => { const isSelected = selectedPalette.some(c => c.hex === color.hex); if (isSelected) { selectedPalette = selectedPalette.filter(c => c.hex !== color.hex); } else { selectedPalette.push(color); } backgroundDiv.classList.add('pop'); backgroundDiv.addEventListener('animationend', () => { backgroundDiv.classList.remove('pop'); }, { once: true }); renderSelectedPalette(); updateSwatchHighlights(); }); swatchWrapper.appendChild(swatch); swatchWrapper.appendChild(colorName); swatchContainer.appendChild(swatchWrapper); }); familyDiv.appendChild(swatchContainer); colorFamiliesContainer.appendChild(familyDiv); }); renderSelectedPalette(); updateSwatchHighlights(); }) .catch(error => console.error('Error loading colors:', error)); function renderSelectedPalette() { const paletteColorsContainer = document.getElementById('palette-colors'); paletteColorsContainer.innerHTML = ''; selectedPalette.forEach(color => { const swatchWrapper = document.createElement('div'); swatchWrapper.classList.add('swatch-wrapper'); // --- Balloon and String Container --- const floatGroup = document.createElement('div'); floatGroup.classList.add('balloon-float-group'); if (animationsEnabled) { floatGroup.classList.add('balloon-float'); floatGroup.style.animationDuration = `${(Math.random() * 3 + 3).toFixed(2)}s`; floatGroup.style.animationDelay = `${(Math.random() * 2).toFixed(2)}s`; } else { floatGroup.classList.remove('balloon-float'); floatGroup.style.animation = 'none'; } // --- Balloon --- const swatch = document.createElement('div'); swatch.classList.add('color-swatch'); swatch.dataset.color = color.hex; const backgroundDiv = document.createElement('div'); backgroundDiv.classList.add('color-background', 'chosen'); if (color.image) { backgroundDiv.style.backgroundImage = `url(${color.image})`; } else { backgroundDiv.style.backgroundColor = color.hex; } if (isLightColor(color.hex)) { backgroundDiv.style.border = '1px solid rgba(0, 0, 0, 0.2)'; } if (color.metallic && color.chromeType) { backgroundDiv.classList.add('metallic', `chrome-${color.chromeType}`); } swatch.appendChild(backgroundDiv); const shineImg = document.createElement('img'); shineImg.classList.add('color-shine'); shineImg.src = "shine.svg"; shineImg.alt = ""; swatch.appendChild(shineImg); // --- SVG String --- const svgNS = "http://www.w3.org/2000/svg"; const stringSVG = document.createElementNS(svgNS, "svg"); stringSVG.setAttribute("class", "balloon-string-svg"); stringSVG.setAttribute("width", "20"); stringSVG.setAttribute("height", "60"); stringSVG.setAttribute("viewBox", "0 0 20 60"); const path = document.createElementNS(svgNS, "path"); path.setAttribute("d", "M10 0 C8 10, 12 20, 10 30 C8 40, 12 50, 10 60"); path.setAttribute("stroke", "#444"); path.setAttribute("stroke-width", "2"); path.setAttribute("fill", "none"); stringSVG.appendChild(path); // --- Assemble Group --- floatGroup.appendChild(swatch); floatGroup.appendChild(stringSVG); swatchWrapper.appendChild(floatGroup); // --- Name --- const colorName = document.createElement('span'); colorName.classList.add('color-name', 'highlighted-name'); colorName.textContent = color.name; swatchWrapper.appendChild(colorName); // --- Click to remove --- swatch.addEventListener('click', () => { selectedPalette = selectedPalette.filter(c => c.hex !== color.hex); renderSelectedPalette(); updateSwatchHighlights(); }); paletteColorsContainer.appendChild(swatchWrapper); }); } function updateSwatchHighlights() { const allSwatches = document.querySelectorAll('#color-families .color-swatch'); allSwatches.forEach(swatch => { const color = swatch.dataset.color; const background = swatch.querySelector('.color-background'); const nameEl = swatch.parentElement.querySelector('.color-name'); const isSelected = selectedPalette.some(c => c.hex === color); if (isSelected) { background.classList.add('chosen'); nameEl.classList.add('highlighted-name'); } else { background.classList.remove('chosen'); nameEl.classList.remove('highlighted-name'); } }); } 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', () => { selectedPalette = []; renderSelectedPalette(); updateSwatchHighlights(); }); document.getElementById('toggle-animation').addEventListener('click', () => { animationsEnabled = !animationsEnabled; renderSelectedPalette(); }); document.getElementById('shuffle-palette').addEventListener('click', () => { selectedPalette = shuffleArray(selectedPalette); renderSelectedPalette(); updateSwatchHighlights(); }); function shuffleArray(array) { 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; }