Добавлена возможность добавлять свою музыку и аудиокниги через YouTube ссылки
This commit is contained in:
parent
875d3d6518
commit
7859dfed10
195
index.html
195
index.html
@ -396,6 +396,68 @@
|
||||
to { height: 20px; }
|
||||
}
|
||||
.equalizer.off span { animation: none; height: 5px; }
|
||||
|
||||
/* Моя музыка */
|
||||
.my-music {
|
||||
margin-top: 20px;
|
||||
background: rgba(255,255,255,0.1);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
}
|
||||
.my-music h4 { margin: 0 0 15px; font-size: 16px; }
|
||||
.add-music-form {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.add-music-form input {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
.add-music-form button {
|
||||
padding: 12px 24px;
|
||||
background: white;
|
||||
color: #667eea;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
.my-playlist {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.playlist-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
background: rgba(255,255,255,0.1);
|
||||
border-radius: 8px;
|
||||
margin: 8px 0;
|
||||
cursor: pointer;
|
||||
transition: 0.2s;
|
||||
}
|
||||
.playlist-item:hover { background: rgba(255,255,255,0.2); }
|
||||
.playlist-item.active { background: rgba(255,255,255,0.3); }
|
||||
.playlist-item .remove {
|
||||
margin-left: auto;
|
||||
opacity: 0.7;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
}
|
||||
.playlist-item .remove:hover { opacity: 1; }
|
||||
.music-type {
|
||||
font-size: 12px;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
background: rgba(255,255,255,0.2);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -441,6 +503,22 @@
|
||||
<span>🔊</span>
|
||||
</div>
|
||||
<div class="now-playing" id="now-playing">Выберите плейлист и нажмите ▶</div>
|
||||
|
||||
<!-- Моя музыка -->
|
||||
<div class="my-music">
|
||||
<h4>🎵 Моя музыка</h4>
|
||||
<div class="add-music-form">
|
||||
<input type="text" id="music-url" placeholder="YouTube ссылка (https://youtube.com/watch?v=...)">
|
||||
<input type="text" id="music-name" placeholder="Название песни/аудиокниги">
|
||||
<select id="music-type" style="padding:12px; border-radius:8px; border:none;">
|
||||
<option value="song">Песня</option>
|
||||
<option value="audiobook">Аудиокнига</option>
|
||||
<option value="motivation">Мотивация</option>
|
||||
</select>
|
||||
<button onclick="addMyMusic()">+ Добавить</button>
|
||||
</div>
|
||||
<div class="my-playlist" id="my-playlist"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="goal-info">
|
||||
@ -671,6 +749,9 @@
|
||||
]
|
||||
};
|
||||
|
||||
// Моя музыка (загружается из localStorage)
|
||||
let myMusic = JSON.parse(localStorage.getItem('myMusic') || '[]');
|
||||
|
||||
let currentPlaylist = 'workout';
|
||||
let currentTrackIndex = 0;
|
||||
let isPlaying = false;
|
||||
@ -717,6 +798,105 @@
|
||||
loadTrack(currentTrackIndex);
|
||||
}
|
||||
|
||||
// === МОЯ МУЗЫКА ===
|
||||
function addMyMusic() {
|
||||
const url = document.getElementById('music-url').value.trim();
|
||||
const name = document.getElementById('music-name').value.trim() || 'Мой трек';
|
||||
const type = document.getElementById('music-type').value;
|
||||
|
||||
if (!url) {
|
||||
alert('Вставь ссылку на YouTube');
|
||||
return;
|
||||
}
|
||||
|
||||
// Конвертация YouTube ссылки в embed
|
||||
let embedUrl = url;
|
||||
const videoId = extractVideoId(url);
|
||||
if (videoId) {
|
||||
embedUrl = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&loop=1&playlist=' + videoId;
|
||||
}
|
||||
|
||||
myMusic.push({
|
||||
id: Date.now(),
|
||||
name: name,
|
||||
url: embedUrl,
|
||||
type: type,
|
||||
videoId: videoId
|
||||
});
|
||||
|
||||
localStorage.setItem('myMusic', JSON.stringify(myMusic));
|
||||
renderMyPlaylist();
|
||||
|
||||
document.getElementById('music-url').value = '';
|
||||
document.getElementById('music-name').value = '';
|
||||
}
|
||||
|
||||
function extractVideoId(url) {
|
||||
const match = url.match(/(?:v=|\/)([a-zA-Z0-9_-]{11})/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
function renderMyPlaylist() {
|
||||
const container = document.getElementById('my-playlist');
|
||||
if (!container) return;
|
||||
|
||||
if (myMusic.length === 0) {
|
||||
container.innerHTML = '<p style="opacity:0.7; font-size:14px;">Пока нет добавленных треков. Добавь любимую музыку!</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = myMusic.map(track => {
|
||||
const typeLabels = { song: '🎵', audiobook: '📚', motivation: '🔥' };
|
||||
const isActive = currentPlaylist === 'my' && currentTrackIndex === myMusic.findIndex(t => t.id === track.id);
|
||||
|
||||
return '<div class="playlist-item' + (isActive ? ' active' : '') + '" onclick="playMyTrack(' + track.id + ')">' +
|
||||
'<span style="font-size:20px;">' + typeLabels[track.type] + '</span>' +
|
||||
'<span style="flex:1; font-size:14px;">' + track.name + '</span>' +
|
||||
'<span class="music-type">' + (track.type === 'song' ? 'Песня' : track.type === 'audiobook' ? 'Аудиокнига' : 'Мотивация') + '</span>' +
|
||||
'<span class="remove" onclick="event.stopPropagation(); removeMyTrack(' + track.id + ')">×</span>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function playMyTrack(id) {
|
||||
const index = myMusic.findIndex(t => t.id === id);
|
||||
if (index === -1) return;
|
||||
|
||||
currentPlaylist = 'my';
|
||||
currentTrackIndex = index;
|
||||
loadTrack(index, true);
|
||||
}
|
||||
|
||||
function removeMyTrack(id) {
|
||||
myMusic = myMusic.filter(t => t.id !== id);
|
||||
localStorage.setItem('myMusic', JSON.stringify(myMusic));
|
||||
renderMyPlaylist();
|
||||
}
|
||||
|
||||
function loadTrack(index, isMyMusic = false) {
|
||||
let playlist;
|
||||
if (isMyMusic || currentPlaylist === 'my') {
|
||||
playlist = myMusic;
|
||||
if (isMyMusic) currentPlaylist = 'my';
|
||||
} else {
|
||||
playlist = playlists[currentPlaylist];
|
||||
}
|
||||
|
||||
if (!playlist || playlist.length === 0) return;
|
||||
|
||||
const track = playlist[index];
|
||||
document.getElementById('now-playing').textContent = '🎵 ' + track.name;
|
||||
|
||||
if (player && player.loadVideoById) {
|
||||
const videoId = track.videoId || track.url.split('v=')[1].split('&')[0];
|
||||
player.loadVideoById(videoId);
|
||||
player.setVolume(70);
|
||||
}
|
||||
|
||||
updatePlayButton();
|
||||
if (currentPlaylist === 'my') renderMyPlaylist();
|
||||
}
|
||||
|
||||
function loadTrack(index) {
|
||||
const playlist = playlists[currentPlaylist];
|
||||
if (!playlist || playlist.length === 0) return;
|
||||
@ -1360,19 +1540,10 @@
|
||||
// Инициализация плеера при загрузке
|
||||
setTimeout(() => initPlayer(), 1000);
|
||||
|
||||
init();
|
||||
// Загрузка моей музыки
|
||||
renderMyPlaylist();
|
||||
|
||||
// Сброс воды каждый день
|
||||
setInterval(() => {
|
||||
const lastWaterDate = localStorage.getItem('lastWaterDate');
|
||||
const todayStr = new Date().toDateString();
|
||||
if (lastWaterDate !== todayStr) {
|
||||
progressData.waterToday = 0;
|
||||
localStorage.setItem('lastWaterDate', todayStr);
|
||||
localStorage.setItem('madinaProgress', JSON.stringify(progressData));
|
||||
renderNutrition();
|
||||
}
|
||||
}, 60000); // Проверка каждую минуту
|
||||
init();
|
||||
</script>
|
||||
|
||||
<!-- Скрытый iframe для музыкального плеера -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user