Use modal color picker for classic palette
This commit is contained in:
parent
540acedcab
commit
f546662143
107
classic.js
107
classic.js
@ -588,23 +588,30 @@ function distinctPaletteSlots(palette) {
|
|||||||
const isArch = (model.patternName || '').toLowerCase().includes('arch');
|
const isArch = (model.patternName || '').toLowerCase().includes('arch');
|
||||||
let slideX = 80;
|
let slideX = 80;
|
||||||
let slideY = 0;
|
let slideY = 0;
|
||||||
|
const idx = typeof cell.balloonIndexInCluster === 'number' ? cell.balloonIndexInCluster : 0;
|
||||||
|
const spread = idx - 1.5;
|
||||||
if (isArch) {
|
if (isArch) {
|
||||||
// Radial slide outward; preserve layout.
|
// Radial slide outward; preserve layout.
|
||||||
const dist = Math.hypot(c.x, c.y) || 1;
|
const dist = Math.hypot(c.x, c.y) || 1;
|
||||||
const offset = 80;
|
const offset = 80;
|
||||||
slideX = (c.x / dist) * offset;
|
const nx = c.x / dist, ny = c.y / dist;
|
||||||
slideY = (c.y / dist) * offset;
|
slideX = nx * offset;
|
||||||
|
slideY = ny * offset;
|
||||||
|
// Slight tangent spread (~5px) to separate balloons without reshaping the quad.
|
||||||
|
const txDirX = -ny;
|
||||||
|
const txDirY = nx;
|
||||||
|
const fan = spread * 10;
|
||||||
|
slideX += txDirX * fan;
|
||||||
|
slideY += txDirY * fan;
|
||||||
}
|
}
|
||||||
let tx = c.x + slideX;
|
let tx = c.x + slideX;
|
||||||
let ty = c.y + slideY;
|
let ty = c.y + slideY;
|
||||||
// Keep shape intact; only fan columns slightly.
|
// Keep shape intact; only fan columns slightly.
|
||||||
const idx = typeof cell.balloonIndexInCluster === 'number' ? cell.balloonIndexInCluster : 0;
|
|
||||||
const spread = idx - 1.5;
|
|
||||||
if (isArch) {
|
if (isArch) {
|
||||||
// no fan/scale for arches; preserve layout
|
// no fan/scale for arches; preserve layout
|
||||||
} else {
|
} else {
|
||||||
tx += spread * 4;
|
tx += spread * 12;
|
||||||
ty += spread * 2;
|
ty += spread * 10;
|
||||||
}
|
}
|
||||||
const fanScale = 1;
|
const fanScale = 1;
|
||||||
// Nudge the top pair down slightly in columns so they remain easily clickable.
|
// Nudge the top pair down slightly in columns so they remain easily clickable.
|
||||||
@ -1016,7 +1023,7 @@ function distinctPaletteSlots(palette) {
|
|||||||
btn.className = 'slot-btn tab-btn';
|
btn.className = 'slot-btn tab-btn';
|
||||||
btn.dataset.slot = String(i);
|
btn.dataset.slot = String(i);
|
||||||
btn.textContent = `#${i}`;
|
btn.textContent = `#${i}`;
|
||||||
btn.addEventListener('click', () => { activeTarget = String(i); updateUI(); });
|
btn.addEventListener('click', () => { activeTarget = String(i); updateUI(); openPalettePicker(); });
|
||||||
slotsContainer.appendChild(btn);
|
slotsContainer.appendChild(btn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1115,53 +1122,55 @@ function distinctPaletteSlots(palette) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const allPaletteColors = flattenPalette(); swatchGrid.innerHTML = '';
|
const allPaletteColors = flattenPalette();
|
||||||
(window.PALETTE || []).forEach(group => {
|
swatchGrid.innerHTML = '';
|
||||||
const title = document.createElement('div'); title.className = 'family-title'; title.textContent = group.family; swatchGrid.appendChild(title);
|
swatchGrid.style.display = 'none'; // hide inline list; use modal picker instead
|
||||||
const row = document.createElement('div'); row.className = 'swatch-row';
|
|
||||||
(group.colors || []).forEach(colorItem => {
|
|
||||||
const sw = document.createElement('button'); sw.type = 'button'; sw.className = 'swatch'; sw.title = colorItem.name;
|
|
||||||
sw.setAttribute('aria-label', colorItem.name);
|
|
||||||
sw.dataset.hex = normHex(colorItem.hex);
|
|
||||||
if (colorItem.image) sw.dataset.image = colorItem.image;
|
|
||||||
|
|
||||||
sw.style.backgroundImage = colorItem.image ? `url("${colorItem.image}")` : 'none';
|
const openPalettePicker = () => {
|
||||||
sw.style.backgroundColor = colorItem.hex;
|
if (typeof window.openColorPicker !== 'function') return;
|
||||||
sw.style.backgroundSize = '500%';
|
const items = allPaletteColors.map(c => ({
|
||||||
sw.style.backgroundPosition = 'center';
|
label: c.name || c.hex,
|
||||||
|
hex: c.hex,
|
||||||
|
meta: c,
|
||||||
|
metaText: c.family || ''
|
||||||
|
}));
|
||||||
|
const currentType = document.querySelector('.topper-type-btn[aria-pressed="true"]')?.dataset.type || 'round';
|
||||||
|
const subtitle = isManual()
|
||||||
|
? 'Apply to active paint'
|
||||||
|
: (activeTarget === 'T' ? 'Set topper color' : `Set slot #${activeTarget}`);
|
||||||
|
window.openColorPicker({
|
||||||
|
title: 'Choose a color',
|
||||||
|
subtitle,
|
||||||
|
items,
|
||||||
|
onSelect: (item) => {
|
||||||
|
const meta = item.meta || {};
|
||||||
|
const selectedColor = { hex: meta.hex || item.hex, image: meta.image || null };
|
||||||
|
if (activeTarget === 'T') {
|
||||||
|
if (currentType.startsWith('num-')) {
|
||||||
|
setNumberTintColor(selectedColor.hex);
|
||||||
|
setNumberTintOpacity(1);
|
||||||
|
if (numberTintSlider) numberTintSlider.value = 1;
|
||||||
|
} else {
|
||||||
|
setTopperColor(selectedColor);
|
||||||
|
}
|
||||||
|
} else if (isManual()) {
|
||||||
|
manualActiveColorGlobal = window.shared?.setActiveColor?.(selectedColor) || selectedColor;
|
||||||
|
} else {
|
||||||
|
const index = parseInt(activeTarget, 10) - 1;
|
||||||
|
if (index >= 0 && index < MAX_SLOTS) { classicColors[index] = selectedColor; setClassicColors(classicColors); }
|
||||||
|
}
|
||||||
|
updateUI(); onColorChange();
|
||||||
|
if (window.updateExportButtonVisibility) window.updateExportButtonVisibility();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
sw.addEventListener('click', () => {
|
topperSwatch.addEventListener('click', () => { activeTarget = 'T'; updateUI(); openPalettePicker(); });
|
||||||
const selectedColor = { hex: colorItem.hex, image: colorItem.image };
|
|
||||||
const currentType = document.querySelector('.topper-type-btn[aria-pressed="true"]')?.dataset.type || 'round';
|
|
||||||
if (activeTarget === 'T') {
|
|
||||||
if (currentType.startsWith('num-')) {
|
|
||||||
setNumberTintColor(selectedColor.hex);
|
|
||||||
setNumberTintOpacity(1);
|
|
||||||
if (numberTintSlider) numberTintSlider.value = 1;
|
|
||||||
} else {
|
|
||||||
setTopperColor(selectedColor);
|
|
||||||
}
|
|
||||||
} else if (isManual()) {
|
|
||||||
manualActiveColorGlobal = window.shared?.setActiveColor?.(selectedColor) || selectedColor;
|
|
||||||
} else {
|
|
||||||
const index = parseInt(activeTarget, 10) - 1;
|
|
||||||
if (index >= 0 && index < MAX_SLOTS) { classicColors[index] = selectedColor; setClassicColors(classicColors); }
|
|
||||||
}
|
|
||||||
updateUI(); onColorChange();
|
|
||||||
if (window.updateExportButtonVisibility) window.updateExportButtonVisibility();
|
|
||||||
});
|
|
||||||
row.appendChild(sw);
|
|
||||||
});
|
|
||||||
swatchGrid.appendChild(row);
|
|
||||||
});
|
|
||||||
topperSwatch.addEventListener('click', () => { activeTarget = 'T'; updateUI(); });
|
|
||||||
activeChip?.addEventListener('click', () => {
|
activeChip?.addEventListener('click', () => {
|
||||||
if (openManualPicker()) return;
|
openPalettePicker();
|
||||||
try { swatchGrid?.scrollIntoView({ behavior: 'smooth', block: 'center' }); } catch {}
|
|
||||||
});
|
});
|
||||||
floatingChip?.addEventListener('click', () => {
|
floatingChip?.addEventListener('click', () => {
|
||||||
if (openManualPicker()) return;
|
openPalettePicker();
|
||||||
try { swatchGrid?.scrollIntoView({ behavior: 'smooth', block: 'center' }); } catch {}
|
|
||||||
});
|
});
|
||||||
randomizeBtn?.addEventListener('click', () => {
|
randomizeBtn?.addEventListener('click', () => {
|
||||||
const pool = allPaletteColors.slice(); const picks = [];
|
const pool = allPaletteColors.slice(); const picks = [];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user