161 lines
5.4 KiB
JavaScript
161 lines
5.4 KiB
JavaScript
const modeToggle = document.getElementById('modeToggle');
|
|
const modeLabel = document.getElementById('modeLabel');
|
|
const workItems = document.querySelectorAll('.work-item');
|
|
const workIndex = document.getElementById('workIndex');
|
|
const workTitle = document.getElementById('workTitle');
|
|
const workCopy = document.getElementById('workCopy');
|
|
const stageCard = document.querySelector('.stage-card');
|
|
const revealBlocks = document.querySelectorAll('.reveal');
|
|
const toneChips = document.querySelectorAll('.tone-chip');
|
|
const swatches = document.querySelectorAll('.swatch');
|
|
const noteItems = document.querySelectorAll('.note-item');
|
|
const densityRange = document.getElementById('densityRange');
|
|
const densityValue = document.getElementById('densityValue');
|
|
const previewCard = document.getElementById('previewCard');
|
|
const previewTone = document.getElementById('previewTone');
|
|
const previewDensity = document.getElementById('previewDensity');
|
|
const previewTitle = document.getElementById('previewTitle');
|
|
const previewText = document.getElementById('previewText');
|
|
const previewAccentLabel = document.getElementById('previewAccentLabel');
|
|
const previewNote = document.getElementById('previewNote');
|
|
const storedMode = window.localStorage.getItem('spectra-mode');
|
|
|
|
if (storedMode === 'light') {
|
|
document.body.classList.add('light-mode');
|
|
}
|
|
|
|
const toneMap = {
|
|
quiet: {
|
|
label: 'Quiet tone',
|
|
title: 'A layout that leaves more breathing room.',
|
|
text: '较安静的版式语气会减少冲突感,让留白、边框与小字说明承担更多秩序工作。',
|
|
},
|
|
balanced: {
|
|
label: 'Balanced tone',
|
|
title: 'A layout that knows where to stop.',
|
|
text: '平衡模式维持标题、说明与边框之间的中段张力,更适合作为正式落地页的默认状态。',
|
|
},
|
|
dramatic: {
|
|
label: 'Dramatic tone',
|
|
title: 'A layout with sharper contrast and pacing.',
|
|
text: '更强对比的语气不会增加花哨效果,而是把标题权重、信息落差和段落收束做得更明显。',
|
|
},
|
|
};
|
|
|
|
const densityMap = {
|
|
'1': 'Airy',
|
|
'2': 'Balanced',
|
|
'3': 'Dense',
|
|
};
|
|
|
|
const accentNames = {
|
|
'#7f2f2f': 'Accent / Oxblood',
|
|
'#3f5a73': 'Accent / Slate Blue',
|
|
'#6c6250': 'Accent / Warm Taupe',
|
|
};
|
|
|
|
function applyMode() {
|
|
const isLight = document.body.classList.contains('light-mode');
|
|
modeToggle.textContent = isLight ? 'Dark Mode' : 'Light Mode';
|
|
modeLabel.textContent = isLight ? 'Editorial Light' : 'Editorial Dark';
|
|
window.localStorage.setItem('spectra-mode', isLight ? 'light' : 'dark');
|
|
}
|
|
|
|
function updateWorkStage(item) {
|
|
workItems.forEach((button) => {
|
|
button.classList.remove('is-active');
|
|
button.setAttribute('aria-selected', 'false');
|
|
});
|
|
|
|
item.classList.add('is-active');
|
|
item.setAttribute('aria-selected', 'true');
|
|
|
|
stageCard?.classList.remove('is-refreshing');
|
|
requestAnimationFrame(() => {
|
|
stageCard?.classList.add('is-refreshing');
|
|
window.setTimeout(() => {
|
|
stageCard?.classList.remove('is-refreshing');
|
|
}, 340);
|
|
});
|
|
|
|
workIndex.textContent = item.dataset.index || '';
|
|
workTitle.textContent = item.dataset.title || '';
|
|
workCopy.textContent = item.dataset.copy || '';
|
|
}
|
|
|
|
function updatePreviewTone(tone) {
|
|
toneChips.forEach((chip) => chip.classList.toggle('is-active', chip.dataset.tone === tone));
|
|
previewCard.dataset.tone = tone;
|
|
previewTone.textContent = toneMap[tone].label;
|
|
previewTitle.textContent = toneMap[tone].title;
|
|
previewText.textContent = toneMap[tone].text;
|
|
}
|
|
|
|
function updatePreviewDensity(level) {
|
|
previewCard.dataset.density = level;
|
|
previewCard.style.padding = level === '1' ? '20px' : level === '3' ? '30px' : '24px';
|
|
densityValue.textContent = densityMap[level];
|
|
previewDensity.textContent = `Density 0${level}`;
|
|
}
|
|
|
|
function updatePreviewAccent(accent) {
|
|
swatches.forEach((swatch) => swatch.classList.toggle('is-active', swatch.dataset.accent === accent));
|
|
document.documentElement.style.setProperty('--accent', accent);
|
|
document.documentElement.style.setProperty('--accent-soft', `${accent}22`);
|
|
previewAccentLabel.textContent = accentNames[accent] || 'Accent / Custom';
|
|
}
|
|
|
|
function updatePreviewNote(note) {
|
|
noteItems.forEach((item) => item.classList.toggle('is-active', item.dataset.note === note));
|
|
previewNote.textContent = note;
|
|
}
|
|
|
|
modeToggle?.addEventListener('click', () => {
|
|
document.body.classList.toggle('light-mode');
|
|
applyMode();
|
|
});
|
|
|
|
workItems.forEach((item) => {
|
|
item.addEventListener('click', () => updateWorkStage(item));
|
|
});
|
|
|
|
toneChips.forEach((chip) => {
|
|
chip.addEventListener('click', () => updatePreviewTone(chip.dataset.tone || 'balanced'));
|
|
});
|
|
|
|
swatches.forEach((swatch) => {
|
|
swatch.addEventListener('click', () => updatePreviewAccent(swatch.dataset.accent || '#7f2f2f'));
|
|
});
|
|
|
|
noteItems.forEach((item) => {
|
|
item.addEventListener('click', () => updatePreviewNote(item.dataset.note || ''));
|
|
});
|
|
|
|
densityRange?.addEventListener('input', (event) => {
|
|
updatePreviewDensity(event.target.value);
|
|
});
|
|
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('is-visible');
|
|
observer.unobserve(entry.target);
|
|
}
|
|
});
|
|
},
|
|
{ threshold: 0.18 },
|
|
);
|
|
|
|
revealBlocks.forEach((block) => observer.observe(block));
|
|
|
|
if (workItems[0]) {
|
|
updateWorkStage(workItems[0]);
|
|
}
|
|
|
|
updatePreviewTone('balanced');
|
|
updatePreviewDensity(densityRange?.value || '2');
|
|
updatePreviewAccent('#7f2f2f');
|
|
updatePreviewNote('封面对齐决定第一印象。');
|
|
applyMode();
|