better ui for new selectors on player
This commit is contained in:
@@ -495,6 +495,10 @@ const AnimePlayer = (function() {
|
||||
els.video.appendChild(track);
|
||||
});
|
||||
}
|
||||
const ICONS = {
|
||||
settings: `<svg viewBox="0 0 24 24"><path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/></svg>`,
|
||||
audio: `<svg viewBox="0 0 24 24"><path d="M12,2C6.48,2,2,6.48,2,12v6c0,2.21,1.79,4,4,4h1c1.1,0,2-0.9,2-2v-5c0-1.1-0.9-2-2-2H3v-1c0-4.97,4.03-9,9-9s9,4.03,9,9v1 h-4c-1.1,0-2,0.9-2,2v5c0,1.1,0.9,2,2,2h1c2.21,0,4-1.79,4-4v-6C22,6.48,17.52,2,12,2z"/></svg>`
|
||||
};
|
||||
|
||||
function createQualitySelector(hls) {
|
||||
const levels = hls.levels;
|
||||
@@ -502,37 +506,64 @@ const AnimePlayer = (function() {
|
||||
|
||||
const plyrEl = els.video.closest('.plyr');
|
||||
const controls = plyrEl.querySelector('.plyr__controls');
|
||||
if (!controls) return;
|
||||
|
||||
if (controls.querySelector('#quality-select')) return;
|
||||
if (!controls || controls.querySelector('#quality-control-wrapper')) return;
|
||||
|
||||
// 1. Crear el Wrapper
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'plyr__control';
|
||||
wrapper.className = 'plyr__controls__item plyr__custom-select-wrapper';
|
||||
wrapper.id = 'quality-control-wrapper';
|
||||
|
||||
// 2. Crear el Botón Visual (Fake)
|
||||
const btn = document.createElement('div');
|
||||
btn.className = 'plyr__custom-control-btn';
|
||||
// Icono + Texto Inicial
|
||||
btn.innerHTML = `${ICONS.settings} <span class="label-text">Auto</span>`;
|
||||
|
||||
// 3. Crear el Select Real (Invisible)
|
||||
const select = document.createElement('select');
|
||||
select.id = 'quality-select';
|
||||
select.className = 'plyr__sr-only-select'; // Clase auxiliar si quieres depurar, sino usa el CSS wrapper
|
||||
|
||||
// AUTO
|
||||
const auto = document.createElement('option');
|
||||
auto.value = -1;
|
||||
auto.textContent = 'Auto';
|
||||
select.appendChild(auto);
|
||||
// Opción AUTO
|
||||
const autoOpt = document.createElement('option');
|
||||
autoOpt.value = -1;
|
||||
autoOpt.textContent = 'Auto';
|
||||
select.appendChild(autoOpt);
|
||||
|
||||
// Opciones de Niveles
|
||||
levels.forEach((l, i) => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = i;
|
||||
opt.textContent = `${l.height}p`;
|
||||
opt.textContent = `${l.height}p`; // Texto que sale en el dropdown nativo
|
||||
select.appendChild(opt);
|
||||
});
|
||||
|
||||
// Sincronizar estado inicial
|
||||
select.value = hls.currentLevel;
|
||||
updateLabel(select.value);
|
||||
|
||||
// Evento Change
|
||||
select.onchange = () => {
|
||||
hls.currentLevel = Number(select.value);
|
||||
updateLabel(select.value);
|
||||
};
|
||||
|
||||
function updateLabel(val) {
|
||||
const index = Number(val);
|
||||
let text = 'Auto';
|
||||
if (index !== -1 && levels[index]) {
|
||||
// Solo el número + p (ej: 720p)
|
||||
text = `${levels[index].height}p`;
|
||||
}
|
||||
btn.innerHTML = `<span class="label-text">${text}</span>`;
|
||||
}
|
||||
|
||||
wrapper.appendChild(select);
|
||||
controls.insertBefore(wrapper, controls.children[4]);
|
||||
wrapper.appendChild(btn);
|
||||
|
||||
// Insertar en controles Plyr (antes del botón de pantalla completa o ajustes)
|
||||
// Insertamos antes del 5º elemento (usualmente settings o fullscreen)
|
||||
const insertIndex = controls.children.length > 4 ? 4 : controls.children.length - 1;
|
||||
controls.insertBefore(wrapper, controls.children[insertIndex]);
|
||||
}
|
||||
|
||||
function createAudioSelector(hls) {
|
||||
@@ -540,15 +571,20 @@ const AnimePlayer = (function() {
|
||||
|
||||
const plyrEl = els.video.closest('.plyr');
|
||||
const controls = plyrEl.querySelector('.plyr__controls');
|
||||
if (!controls) return;
|
||||
|
||||
if (controls.querySelector('#audio-select')) return;
|
||||
if (!controls || controls.querySelector('#audio-control-wrapper')) return;
|
||||
|
||||
// 1. Wrapper
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'plyr__control';
|
||||
wrapper.className = 'plyr__controls__item plyr__custom-select-wrapper';
|
||||
wrapper.id = 'audio-control-wrapper';
|
||||
|
||||
// 2. Botón Visual
|
||||
const btn = document.createElement('div');
|
||||
btn.className = 'plyr__custom-control-btn';
|
||||
btn.innerHTML = `<span class="label-text">Audio 1</span>`;
|
||||
|
||||
// 3. Select Invisible
|
||||
const select = document.createElement('select');
|
||||
select.id = 'audio-select';
|
||||
|
||||
hls.audioTracks.forEach((t, i) => {
|
||||
const opt = document.createElement('option');
|
||||
@@ -558,13 +594,37 @@ const AnimePlayer = (function() {
|
||||
});
|
||||
|
||||
select.value = hls.audioTrack;
|
||||
updateLabel(select.value);
|
||||
|
||||
select.onchange = () => {
|
||||
hls.audioTrack = Number(select.value);
|
||||
updateLabel(select.value);
|
||||
};
|
||||
|
||||
function updateLabel(val) {
|
||||
const index = Number(val);
|
||||
const track = hls.audioTracks[index];
|
||||
|
||||
// Priorizamos el idioma (lang), luego el nombre
|
||||
let rawText = track.lang || track.name || `A${index + 1}`;
|
||||
|
||||
// Tomamos solo las 2 primeras letras y las pasamos a Mayúsculas
|
||||
let shortText = rawText.substring(0, 2).toUpperCase();
|
||||
|
||||
btn.querySelector('.label-text').innerText = shortText;
|
||||
}
|
||||
|
||||
wrapper.appendChild(select);
|
||||
controls.insertBefore(wrapper, controls.children[4]); // antes del volumen
|
||||
wrapper.appendChild(btn);
|
||||
|
||||
// Insertar antes del selector de calidad si existe, o en la posición 4
|
||||
const qualityWrapper = controls.querySelector('#quality-control-wrapper');
|
||||
if(qualityWrapper) {
|
||||
controls.insertBefore(wrapper, qualityWrapper);
|
||||
} else {
|
||||
const insertIndex = controls.children.length > 4 ? 4 : controls.children.length - 1;
|
||||
controls.insertBefore(wrapper, controls.children[insertIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
function initPlyr(enableAudio = false) {
|
||||
|
||||
@@ -520,7 +520,7 @@ body.stop-scrolling {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
backdrop-filter: blur(10px);
|
||||
height: 36px; /* Para igualar la altura de los selects/toggles */
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.glass-btn-mpv:hover {
|
||||
@@ -538,13 +538,65 @@ body.stop-scrolling {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
#audio-select {
|
||||
.plyr__custom-select-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* El select real: invisible pero clickable */
|
||||
.plyr__custom-select-wrapper select {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
z-index: 2; /* Encima del botón visual */
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/* El botón visual que imita a Plyr */
|
||||
.plyr__custom-control-btn {
|
||||
position: relative;
|
||||
background: transparent;
|
||||
color: white;
|
||||
border: none;
|
||||
color: #fff; /* Plyr default white */
|
||||
padding: 7px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s ease, color 0.3s ease;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
padding: 4px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
line-height: 1;
|
||||
}
|
||||
#audio-select option {
|
||||
color: black;
|
||||
|
||||
.plyr__custom-control-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.15); /* Plyr hover effect */
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.plyr__custom-control-btn svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: currentColor;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Badge pequeño para indicar calidad actual (opcional) */
|
||||
.quality-badge {
|
||||
background: var(--brand-color);
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
Reference in New Issue
Block a user