volumebar
This commit is contained in:
parent
42a8c8122b
commit
e6beacd005
3 changed files with 188 additions and 0 deletions
21
index.html
21
index.html
|
|
@ -299,6 +299,27 @@
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="fullscreen-volume-container">
|
||||||
|
<button id="fs-volume-btn" class="fs-volume-btn" title="Mute">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
|
||||||
|
<path d="M15.54 8.46a5 5 0 0 1 0 7.07"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div id="fs-volume-bar" class="fs-volume-bar">
|
||||||
|
<div id="fs-volume-fill" class="fs-volume-fill"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
83
js/ui.js
83
js/ui.js
|
|
@ -5,6 +5,8 @@ import {
|
||||||
SVG_DOWNLOAD,
|
SVG_DOWNLOAD,
|
||||||
SVG_MENU,
|
SVG_MENU,
|
||||||
SVG_HEART,
|
SVG_HEART,
|
||||||
|
SVG_VOLUME,
|
||||||
|
SVG_MUTE,
|
||||||
formatTime,
|
formatTime,
|
||||||
createPlaceholder,
|
createPlaceholder,
|
||||||
trackDataStore,
|
trackDataStore,
|
||||||
|
|
@ -900,6 +902,87 @@ export class UIRenderer {
|
||||||
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/><path d="M11 10h1v4"/></svg>';
|
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/><path d="M11 10h1v4"/></svg>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fullscreen volume controls
|
||||||
|
const fsVolumeBtn = document.getElementById('fs-volume-btn');
|
||||||
|
const fsVolumeBar = document.getElementById('fs-volume-bar');
|
||||||
|
const fsVolumeFill = document.getElementById('fs-volume-fill');
|
||||||
|
|
||||||
|
if (fsVolumeBtn && fsVolumeBar && fsVolumeFill) {
|
||||||
|
const updateFsVolumeUI = () => {
|
||||||
|
const { muted } = audioPlayer;
|
||||||
|
const volume = this.player.userVolume;
|
||||||
|
fsVolumeBtn.innerHTML = muted || volume === 0 ? SVG_MUTE : SVG_VOLUME;
|
||||||
|
fsVolumeBtn.classList.toggle('muted', muted || volume === 0);
|
||||||
|
const effectiveVolume = muted ? 0 : volume * 100;
|
||||||
|
fsVolumeFill.style.setProperty('--fs-volume-level', `${effectiveVolume}%`);
|
||||||
|
fsVolumeFill.style.width = `${effectiveVolume}%`;
|
||||||
|
};
|
||||||
|
|
||||||
|
fsVolumeBtn.onclick = () => {
|
||||||
|
audioPlayer.muted = !audioPlayer.muted;
|
||||||
|
localStorage.setItem('muted', audioPlayer.muted);
|
||||||
|
updateFsVolumeUI();
|
||||||
|
};
|
||||||
|
|
||||||
|
const setFsVolume = (e) => {
|
||||||
|
const rect = fsVolumeBar.getBoundingClientRect();
|
||||||
|
const position = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
||||||
|
const newVolume = position;
|
||||||
|
this.player.setVolume(newVolume);
|
||||||
|
if (audioPlayer.muted && newVolume > 0) {
|
||||||
|
audioPlayer.muted = false;
|
||||||
|
localStorage.setItem('muted', false);
|
||||||
|
}
|
||||||
|
updateFsVolumeUI();
|
||||||
|
};
|
||||||
|
|
||||||
|
let isAdjustingFsVolume = false;
|
||||||
|
|
||||||
|
fsVolumeBar.addEventListener('mousedown', (e) => {
|
||||||
|
isAdjustingFsVolume = true;
|
||||||
|
setFsVolume(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
fsVolumeBar.addEventListener(
|
||||||
|
'touchstart',
|
||||||
|
(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
isAdjustingFsVolume = true;
|
||||||
|
const touch = e.touches[0];
|
||||||
|
setFsVolume({ clientX: touch.clientX });
|
||||||
|
},
|
||||||
|
{ passive: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', (e) => {
|
||||||
|
if (isAdjustingFsVolume) {
|
||||||
|
setFsVolume(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
'touchmove',
|
||||||
|
(e) => {
|
||||||
|
if (isAdjustingFsVolume) {
|
||||||
|
const touch = e.touches[0];
|
||||||
|
setFsVolume({ clientX: touch.clientX });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ passive: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
document.addEventListener('mouseup', () => {
|
||||||
|
isAdjustingFsVolume = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('touchend', () => {
|
||||||
|
isAdjustingFsVolume = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.addEventListener('volumechange', updateFsVolumeUI);
|
||||||
|
updateFsVolumeUI();
|
||||||
|
}
|
||||||
|
|
||||||
const update = () => {
|
const update = () => {
|
||||||
if (document.getElementById('fullscreen-cover-overlay').style.display === 'none') return;
|
if (document.getElementById('fullscreen-cover-overlay').style.display === 'none') return;
|
||||||
|
|
||||||
|
|
|
||||||
84
styles.css
84
styles.css
|
|
@ -2230,6 +2230,90 @@ input:checked + .slider::before {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fullscreen-volume-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: var(--foreground);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-btn:hover {
|
||||||
|
background: rgb(255, 255, 255, 0.1);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-btn.muted {
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-bar {
|
||||||
|
width: 150px;
|
||||||
|
height: 6px;
|
||||||
|
background-color: rgb(255, 255, 255, 0.2);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
transition: height 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-bar:hover {
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-fill {
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--foreground);
|
||||||
|
border-radius: 3px;
|
||||||
|
width: var(--fs-volume-level, 70%);
|
||||||
|
transition: width 0.1s ease;
|
||||||
|
position: relative;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-bar:hover .fs-volume-fill {
|
||||||
|
background-color: var(--highlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-bar:hover .fs-volume-fill::after,
|
||||||
|
.fs-volume-bar:active .fs-volume-fill::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
right: -6px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background-color: var(--highlight);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 2px 4px rgb(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.fullscreen-volume-container {
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-volume-bar {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.fullscreen-actions {
|
.fullscreen-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue