2048 update
This commit is contained in:
parent
b08d1b5ce7
commit
cd9955bfa8
237
2048.css
237
2048.css
@ -1274,3 +1274,240 @@ h1 {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==========================
|
||||||
|
ADVANCED SOUND CONTROL
|
||||||
|
========================== */
|
||||||
|
.sound-control-container {
|
||||||
|
position: fixed;
|
||||||
|
top: clamp(10px, 2vh, 20px);
|
||||||
|
left: clamp(10px, 2vw, 20px);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main Sound Button */
|
||||||
|
.btn-sound-main {
|
||||||
|
width: clamp(40px, 6.5vw, 52px);
|
||||||
|
height: clamp(40px, 6.5vw, 52px);
|
||||||
|
padding: 0;
|
||||||
|
background: rgba(30, 0, 50, 0.9);
|
||||||
|
backdrop-filter: blur(15px);
|
||||||
|
border: 2px solid rgba(0, 217, 255, 0.5);
|
||||||
|
border-radius: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow:
|
||||||
|
0 5px 20px rgba(0, 0, 0, 0.4),
|
||||||
|
0 0 25px rgba(0, 217, 255, 0.25),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sound-main svg {
|
||||||
|
width: clamp(20px, 3.5vw, 26px);
|
||||||
|
height: clamp(20px, 3.5vw, 26px);
|
||||||
|
color: rgba(0, 234, 255, 0.95);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sound-main:hover {
|
||||||
|
background: rgba(0, 234, 255, 0.18);
|
||||||
|
border-color: rgba(0, 234, 255, 0.85);
|
||||||
|
box-shadow:
|
||||||
|
0 7px 28px rgba(0, 0, 0, 0.5),
|
||||||
|
0 0 40px rgba(0, 234, 255, 0.4),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.15);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sound-main:hover svg {
|
||||||
|
color: rgba(0, 234, 255, 1);
|
||||||
|
transform: scale(1.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sound-main:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Muted State - Red */
|
||||||
|
.btn-sound-main.all-muted {
|
||||||
|
background: rgba(60, 0, 10, 0.9) !important;
|
||||||
|
border-color: rgba(255, 60, 60, 0.7) !important;
|
||||||
|
box-shadow:
|
||||||
|
0 5px 20px rgba(0, 0, 0, 0.4),
|
||||||
|
0 0 25px rgba(255, 60, 60, 0.3),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sound-main.all-muted svg {
|
||||||
|
color: rgba(255, 80, 80, 0.95) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sound-main.all-muted:hover {
|
||||||
|
background: rgba(255, 60, 60, 0.2) !important;
|
||||||
|
border-color: rgba(255, 80, 80, 0.9) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Volume Panel */
|
||||||
|
.volume-panel {
|
||||||
|
position: absolute;
|
||||||
|
top: clamp(46px, 8vh, 60px);
|
||||||
|
left: 0;
|
||||||
|
background: linear-gradient(145deg, rgba(20, 0, 40, 0.98), rgba(30, 0, 50, 0.98));
|
||||||
|
backdrop-filter: blur(25px);
|
||||||
|
border: 2px solid rgba(0, 217, 255, 0.4);
|
||||||
|
border-radius: 18px;
|
||||||
|
padding: 20px 18px;
|
||||||
|
min-width: clamp(240px, 30vw, 280px);
|
||||||
|
box-shadow:
|
||||||
|
0 20px 60px rgba(0, 0, 0, 0.7),
|
||||||
|
0 0 50px rgba(0, 217, 255, 0.3),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
animation: slideDown 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideDown {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-15px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Volume Item */
|
||||||
|
.volume-item {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-icon {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
color: rgba(0, 234, 255, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-label {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-value {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(0, 234, 255, 0.9);
|
||||||
|
min-width: 40px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Volume Slider */
|
||||||
|
.volume-slider {
|
||||||
|
width: 100%;
|
||||||
|
height: 6px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider::-webkit-slider-track {
|
||||||
|
height: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background: linear-gradient(135deg, #00eaff 0%, #0099ff 100%);
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow:
|
||||||
|
0 2px 10px rgba(0, 234, 255, 0.5),
|
||||||
|
0 0 20px rgba(0, 234, 255, 0.3);
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider::-webkit-slider-thumb:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
box-shadow:
|
||||||
|
0 4px 15px rgba(0, 234, 255, 0.7),
|
||||||
|
0 0 30px rgba(0, 234, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider::-moz-range-track {
|
||||||
|
height: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider::-moz-range-thumb {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background: linear-gradient(135deg, #00eaff 0%, #0099ff 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow:
|
||||||
|
0 2px 10px rgba(0, 234, 255, 0.5),
|
||||||
|
0 0 20px rgba(0, 234, 255, 0.3);
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider::-moz-range-thumb:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Slider Fill Effect */
|
||||||
|
.volume-slider {
|
||||||
|
background: linear-gradient(to right,
|
||||||
|
rgba(0, 234, 255, 0.3) 0%,
|
||||||
|
rgba(0, 234, 255, 0.3) var(--value, 0%),
|
||||||
|
rgba(255, 255, 255, 0.1) var(--value, 0%),
|
||||||
|
rgba(255, 255, 255, 0.1) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile Responsive */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.volume-panel {
|
||||||
|
min-width: clamp(220px, 50vw, 260px);
|
||||||
|
padding: 16px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-item {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-label {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-value {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
84
2048.html
84
2048.html
@ -16,42 +16,72 @@
|
|||||||
<div class="cursor-light" aria-hidden="true"></div>
|
<div class="cursor-light" aria-hidden="true"></div>
|
||||||
|
|
||||||
<!-- SOUND CONTROLS - KIRI ATAS -->
|
<!-- SOUND CONTROLS - KIRI ATAS -->
|
||||||
<div class="sound-controls">
|
<!-- SOUND CONTROL - KIRI ATAS -->
|
||||||
<!-- BG Music Toggle -->
|
<div class="sound-control-container">
|
||||||
<button class="icon-btn btn-sound" id="btn-sound-bg" data-sound="bg" title="Toggle Background Music">
|
<!-- Main Sound Button -->
|
||||||
<svg class="sound-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
<button class="icon-btn btn-sound-main" id="btn-sound-main" title="Sound Settings">
|
||||||
<path d="M9 18V5l12-2v13M9 18c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3zm12-2c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z"/>
|
<!-- Icon Full Sound (all ON) -->
|
||||||
|
<svg class="sound-full" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||||||
|
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
|
||||||
|
<path d="M15.54 8.46a5 5 0 0 1 0 7.07M19.07 4.93a10 10 0 0 1 0 14.14"/>
|
||||||
</svg>
|
</svg>
|
||||||
<svg class="mute-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="display: none;">
|
<!-- Icon Medium Sound (some muted) -->
|
||||||
<line x1="2" y1="2" x2="22" y2="22"/>
|
<svg class="sound-medium" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="display: none;">
|
||||||
<path d="M9 18V5l12-2v13M9 18c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3zm12-2c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z"/>
|
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
|
||||||
|
<path d="M15.54 8.46a5 5 0 0 1 0 7.07"/>
|
||||||
|
</svg>
|
||||||
|
<!-- Icon Low Sound (mostly muted) -->
|
||||||
|
<svg class="sound-low" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="display: none;">
|
||||||
|
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
|
||||||
|
</svg>
|
||||||
|
<!-- Icon Muted (all OFF) -->
|
||||||
|
<svg class="sound-muted" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="display: none;">
|
||||||
|
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
|
||||||
|
<line x1="23" y1="9" x2="17" y2="15"/>
|
||||||
|
<line x1="17" y1="9" x2="23" y2="15"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Pop SFX Toggle -->
|
<!-- Volume Sliders Panel (Hidden by default) -->
|
||||||
<button class="icon-btn btn-sound" id="btn-sound-pop" data-sound="pop" title="Toggle Pop Sound">
|
<div class="volume-panel" id="volume-panel" style="display: none;">
|
||||||
<svg class="sound-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
<!-- Music Volume -->
|
||||||
|
<div class="volume-item">
|
||||||
|
<div class="volume-header">
|
||||||
|
<svg class="volume-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M9 18V5l12-2v13M9 18c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3zm12-2c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z"/>
|
||||||
|
</svg>
|
||||||
|
<span class="volume-label">Music</span>
|
||||||
|
<span class="volume-value" id="vol-music-display">25%</span>
|
||||||
|
</div>
|
||||||
|
<input type="range" class="volume-slider" id="vol-music" min="0" max="100" value="25">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pop SFX Volume -->
|
||||||
|
<div class="volume-item">
|
||||||
|
<div class="volume-header">
|
||||||
|
<svg class="volume-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
<circle cx="12" cy="12" r="10"/>
|
<circle cx="12" cy="12" r="10"/>
|
||||||
<path d="M8 12h8M12 8v8"/>
|
<path d="M8 12h8M12 8v8"/>
|
||||||
</svg>
|
</svg>
|
||||||
<svg class="mute-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
|
<span class="volume-label">Pop SFX</span>
|
||||||
<line x1="2" y1="2" x2="22" y2="22"/>
|
<span class="volume-value" id="vol-pop-display">90%</span>
|
||||||
<circle cx="12" cy="12" r="10"/>
|
</div>
|
||||||
</svg>
|
<input type="range" class="volume-slider" id="vol-pop" min="0" max="100" value="90">
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Merge SFX Toggle -->
|
|
||||||
<button class="icon-btn btn-sound" id="btn-sound-merge" data-sound="merge" title="Toggle Merge Sound">
|
|
||||||
<svg class="sound-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
|
||||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
|
||||||
</svg>
|
|
||||||
<svg class="mute-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" style="display: none;">
|
|
||||||
<line x1="2" y1="2" x2="22" y2="22"/>
|
|
||||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Merge SFX Volume -->
|
||||||
|
<div class="volume-item">
|
||||||
|
<div class="volume-header">
|
||||||
|
<svg class="volume-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
||||||
|
</svg>
|
||||||
|
<span class="volume-label">Merge SFX</span>
|
||||||
|
<span class="volume-value" id="vol-merge-display">100%</span>
|
||||||
|
</div>
|
||||||
|
<input type="range" class="volume-slider" id="vol-merge" min="0" max="100" value="100">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- Top Right Controls -->
|
<!-- Top Right Controls -->
|
||||||
<div class="top-controls">
|
<div class="top-controls">
|
||||||
<button class="icon-btn btn-tutorial" id="btn-tutorial" title="How to Play">
|
<button class="icon-btn btn-tutorial" id="btn-tutorial" title="How to Play">
|
||||||
|
|||||||
165
2048.js
165
2048.js
@ -608,38 +608,165 @@ function hideGameOver() {
|
|||||||
/* =============================================
|
/* =============================================
|
||||||
SOUND CONTROLS
|
SOUND CONTROLS
|
||||||
============================================= */
|
============================================= */
|
||||||
function toggleSound(soundType) {
|
/* =============================================
|
||||||
soundState[soundType] = !soundState[soundType];
|
ADVANCED VOLUME CONTROL SYSTEM
|
||||||
localStorage.setItem('sound_' + soundType, soundState[soundType]);
|
============================================= */
|
||||||
updateAudioVolumes();
|
|
||||||
|
|
||||||
const button = document.getElementById('btn-sound-' + soundType);
|
// Volume State (0-100 for each sound)
|
||||||
if (button) {
|
let volumeState = {
|
||||||
updateSoundButtonState(button, soundState[soundType]);
|
music: parseInt(localStorage.getItem('vol_music')) || 25,
|
||||||
|
pop: parseInt(localStorage.getItem('vol_pop')) || 90,
|
||||||
|
merge: parseInt(localStorage.getItem('vol_merge')) || 100
|
||||||
|
};
|
||||||
|
|
||||||
|
// Apply volumes on load
|
||||||
|
function initVolumeControl() {
|
||||||
|
// Set audio volumes
|
||||||
|
audio.bg.volume = volumeState.music / 100;
|
||||||
|
audio.pop.volume = volumeState.pop / 100;
|
||||||
|
audio.merge.volume = volumeState.merge / 100;
|
||||||
|
|
||||||
|
// Update sliders
|
||||||
|
const musicSlider = document.getElementById('vol-music');
|
||||||
|
const popSlider = document.getElementById('vol-pop');
|
||||||
|
const mergeSlider = document.getElementById('vol-merge');
|
||||||
|
|
||||||
|
if (musicSlider) {
|
||||||
|
musicSlider.value = volumeState.music;
|
||||||
|
updateSliderFill(musicSlider, volumeState.music);
|
||||||
|
document.getElementById('vol-music-display').textContent = volumeState.music + '%';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soundType === 'bg') {
|
if (popSlider) {
|
||||||
if (soundState.bg) {
|
popSlider.value = volumeState.pop;
|
||||||
|
updateSliderFill(popSlider, volumeState.pop);
|
||||||
|
document.getElementById('vol-pop-display').textContent = volumeState.pop + '%';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mergeSlider) {
|
||||||
|
mergeSlider.value = volumeState.merge;
|
||||||
|
updateSliderFill(mergeSlider, volumeState.merge);
|
||||||
|
document.getElementById('vol-merge-display').textContent = volumeState.merge + '%';
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMainSoundIcon();
|
||||||
|
|
||||||
|
// Event listeners for sliders
|
||||||
|
if (musicSlider) {
|
||||||
|
musicSlider.addEventListener('input', (e) => {
|
||||||
|
const val = parseInt(e.target.value);
|
||||||
|
volumeState.music = val;
|
||||||
|
audio.bg.volume = val / 100;
|
||||||
|
localStorage.setItem('vol_music', val);
|
||||||
|
document.getElementById('vol-music-display').textContent = val + '%';
|
||||||
|
updateSliderFill(e.target, val);
|
||||||
|
updateMainSoundIcon();
|
||||||
|
|
||||||
|
// Auto-play BG music if volume > 0
|
||||||
|
if (val > 0 && audio.bg.paused) {
|
||||||
tryPlayBg();
|
tryPlayBg();
|
||||||
} else {
|
} else if (val === 0) {
|
||||||
audio.bg.pause();
|
audio.bg.pause();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (popSlider) {
|
||||||
|
popSlider.addEventListener('input', (e) => {
|
||||||
|
const val = parseInt(e.target.value);
|
||||||
|
volumeState.pop = val;
|
||||||
|
audio.pop.volume = val / 100;
|
||||||
|
localStorage.setItem('vol_pop', val);
|
||||||
|
document.getElementById('vol-pop-display').textContent = val + '%';
|
||||||
|
updateSliderFill(e.target, val);
|
||||||
|
updateMainSoundIcon();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mergeSlider) {
|
||||||
|
mergeSlider.addEventListener('input', (e) => {
|
||||||
|
const val = parseInt(e.target.value);
|
||||||
|
volumeState.merge = val;
|
||||||
|
audio.merge.volume = val / 100;
|
||||||
|
localStorage.setItem('vol_merge', val);
|
||||||
|
document.getElementById('vol-merge-display').textContent = val + '%';
|
||||||
|
updateSliderFill(e.target, val);
|
||||||
|
updateMainSoundIcon();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle panel visibility
|
||||||
|
const btnSoundMain = document.getElementById('btn-sound-main');
|
||||||
|
const volumePanel = document.getElementById('volume-panel');
|
||||||
|
|
||||||
|
if (btnSoundMain && volumePanel) {
|
||||||
|
btnSoundMain.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const isVisible = volumePanel.style.display === 'block';
|
||||||
|
volumePanel.style.display = isVisible ? 'none' : 'block';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close panel when clicking outside
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!volumePanel.contains(e.target) && !btnSoundMain.contains(e.target)) {
|
||||||
|
volumePanel.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent panel click from closing
|
||||||
|
volumePanel.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSoundButtonState(button, isEnabled) {
|
// Update slider fill effect
|
||||||
if (!button) return;
|
function updateSliderFill(slider, value) {
|
||||||
|
slider.style.setProperty('--value', value + '%');
|
||||||
|
}
|
||||||
|
|
||||||
if (isEnabled) {
|
// Update main sound icon based on volumes
|
||||||
button.classList.remove('muted');
|
function updateMainSoundIcon() {
|
||||||
button.querySelector('.sound-icon').style.display = 'block';
|
const btnMain = document.getElementById('btn-sound-main');
|
||||||
button.querySelector('.mute-icon').style.display = 'none';
|
if (!btnMain) return;
|
||||||
|
|
||||||
|
const iconFull = btnMain.querySelector('.sound-full');
|
||||||
|
const iconMedium = btnMain.querySelector('.sound-medium');
|
||||||
|
const iconLow = btnMain.querySelector('.sound-low');
|
||||||
|
const iconMuted = btnMain.querySelector('.sound-muted');
|
||||||
|
|
||||||
|
// Calculate total volume average
|
||||||
|
const totalVolume = volumeState.music + volumeState.pop + volumeState.merge;
|
||||||
|
const avgVolume = totalVolume / 3;
|
||||||
|
|
||||||
|
// Hide all icons first
|
||||||
|
iconFull.style.display = 'none';
|
||||||
|
iconMedium.style.display = 'none';
|
||||||
|
iconLow.style.display = 'none';
|
||||||
|
iconMuted.style.display = 'none';
|
||||||
|
|
||||||
|
// Show appropriate icon based on average
|
||||||
|
if (totalVolume === 0) {
|
||||||
|
iconMuted.style.display = 'block';
|
||||||
|
btnMain.classList.add('all-muted');
|
||||||
} else {
|
} else {
|
||||||
button.classList.add('muted');
|
btnMain.classList.remove('all-muted');
|
||||||
button.querySelector('.sound-icon').style.display = 'none';
|
|
||||||
button.querySelector('.mute-icon').style.display = 'block';
|
if (avgVolume >= 60) {
|
||||||
|
iconFull.style.display = 'block';
|
||||||
|
} else if (avgVolume >= 30) {
|
||||||
|
iconMedium.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
iconLow.style.display = 'block';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize on DOM load (add this to your existing DOMContentLoaded)
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
// ... existing code ...
|
||||||
|
initVolumeControl(); // ADD THIS LINE
|
||||||
|
});
|
||||||
|
|
||||||
/* =============================================
|
/* =============================================
|
||||||
COMBO EFFECTS
|
COMBO EFFECTS
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user