Files
halo-theme-pix/templates/assets/js/pixplayer.js
T

698 lines
20 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* pix主题音乐播放器
*/
function updateMusicBtnColor(state) {
if (state === 'play') {
// 播放
$('.bg_music').css("background", "rgb(172, 202, 181)");
$('.bg_music i').css("color", "white");
} else if (state === 'pause') {
// 暂停
$('.bg_music').css("background", "#EBF2ED");
$('.bg_music i').css("color", "rgb(174, 174, 174)");
} else {
// 默认
$('.bg_music').css("background", "#EBF2ED");
$('.bg_music i').css("color", "rgb(174, 174, 174)");
// ✅ 初始化:隐藏歌词容器(真正关闭歌词功能)
if (Theme.play.lrc_open && typeof lyricsContainer !== 'undefined') {
lyricsContainer.css('display', 'none');
}
// ✅ 按钮样式置为关闭状态视觉
$('a.bg_lrc i').css("color", "#aeaeae");
$('a.bg_lrc').css("background", "#EBF2ED");
$('.t_dark.top_tool.icon_color').hide();
}
}
var rem = [];
rem.audio = $('<audio id="pix_player"></audio>');
var audiobox = $('<audio id="pix_player">');
var au = $('#pix_player');
var volume = 1;
var loop = Theme.play.m_loop;
var playlist = [];
var post_playlist = [];
var Paused = true;
var playLrc = '';
var m_cover = $('.player_mod .m_cover img');
var m_title = $('.player_mod .m_info h2');
var m_artist = $('.player_mod .m_info small');
$(document).on('click', '.play_btn', function () {
$('.player_box').append(audiobox);
$('.pix_player').removeClass('playing');
$(this).parents('.pix_player').addClass('playing');
var url = $(this).attr('data');
var lrc = $(this).attr('lrc');
var audio_s = $('#pix_player').attr('src');
var meta = $(this).siblings('.player_meta').find('.title');
playLrc = lrc;
m_title.text(meta.find('.name').text());
m_artist.text(meta.find('.author').text());
m_cover.attr('src', $('.pix_player.playing .player_thum img').attr('src'));
if (audio_s == '' || audio_s !== url) {
$('#pix_player').attr('src', url);
audiobox[0].play();
} else {
pasued();
}
$(".play_btn").html("<i class='ri-play-line'></i>");
initAudio();
});
// 初始化函数
function initAudio() {
audiobox[0].addEventListener("play", audioplay);
audiobox[0].addEventListener("pause", audiopause);
audiobox[0].addEventListener("timeupdate", updateProcess);
if (Theme.bgm_open == true) {
audiobox[0].addEventListener("ended", endplay);
}
}
//音乐结束触发
function endplay() {
var index = $('.musci_list_box li.active').index() + 1;
var max = $('.musci_list_box li').length;
var new_mid = 0;
if (loop == "one") {
new_mid = index - 1;
} else if (loop == "none") {
new_mid = (Math.floor(Math.random() * max) + 1) - 1;
} else if (loop == "all") {
new_mid = index > (max - 1) ? 0 : index;
}
mulist_play(new_mid);
}
// 当音乐标签加载完成之后所触发的函数
audiobox[0].oncanplay = function () {
var duration = handleTime(this.duration);
var currenttime = handleTime(this.currentTime);
$(".timer .total_time").text(duration);
$(".timer .current_time").text(currenttime);
initAudio();
}
// 音乐播放暂停的函数
function pasued() {
if (Paused === false) {
audiobox[0].pause();
} else {
audiobox[0].play();
}
}
// 音乐播放之后触发的函数
function audioplay() {
box_up = true;
// 播放时
updateMusicBtnColor('play');
var mheight = $('.footer_nav_box').height();
$('.footer_nav_box').animate({ top: -mheight }, 200, 'linear');
Paused = false;
$(".pix_player.playing .play_btn").html("<i class='ri-pause-line'></i>");
$('.m_play').html('<i class="ri-pause-circle-fill"></i>');
// 播放时显示歌词
if (Theme.play.lrc_open && typeof lyricsContainer !== 'undefined') {
lyricsContainer.css('display', 'block');
$('a.bg_lrc i').css("color", "");
$('a.bg_lrc').css("background", "");
}
}
// 音乐暂停之后触发的函数
function audiopause() {
// 暂停时
updateMusicBtnColor('pause');
Paused = true;
$(".pix_player.playing .play_btn").html("<i class='ri-play-line'></i>");
$('.m_play').html('<i class="ri-play-circle-fill"></i>');
// 暂停时隐藏歌词
if (Theme.play.lrc_open && typeof lyricsContainer !== 'undefined') {
lyricsContainer.css('display', 'none');
$('a.bg_lrc i').css("color", "#aeaeae");
$('a.bg_lrc').css("background", "#EBF2ED");
}
}
// 更新进度条
function updateProcess() {
if (Paused !== false) return true;
var duration = handleTime(this.duration);
var currenttime = handleTime(this.currentTime);
var percent = audiobox[0].currentTime / audiobox[0].duration;
$(".player_mod .player_bar .progress").css('width', (percent) * 100 + "%");
$(".timer .total_time").text(duration);
$(".timer .current_time").text(currenttime);
}
//循环歌曲 m_loop
$(document).on('click', '.m_loop', function () {
if ($(this).hasClass('all')) {
$(this).removeClass('all');
$(this).addClass('one');
$(this).html('<i class="ri-repeat-one-line"></i>');
loop = 'one';
} else if (($(this).hasClass('one'))) {
$(this).removeClass('one');
$(this).addClass('none');
$(this).html('<i class="ri-shuffle-line"></i>');
loop = 'none';
} else {
$(this).removeClass('none');
$(this).addClass('all');
$(this).html('<i class="ri-repeat-line"></i>');
loop = 'all';
}
});
// 时间处理的函数
function handleTime(seconedTime) {
var minute = parseInt(seconedTime / 60, 10);
if (minute < 10) { minute = "0" + minute };
var second = (seconedTime - minute * 60).toFixed(2).split(".")[0];
if (second < 10) { second = "0" + second };
var Time = minute + ":" + second;
return Time;
}
//视频播放
var video = $('#pix_video_player');
$(document).on('click', '.video_play_btn', function () {
var video = $(this).siblings('#pix_video_player');
video.attr('controls', 'controls');
$(this).remove();
video[0].play();
});
function stopOtherMedia(element) {
$("video").not(element).each(function (index, video) {
video.pause();
});
}
//背景音乐
function autoload_music() {
var state = Theme.bgm_open;
var api = `${Theme.play.pix_mu_api || 'https://api.i-meto.com/meting/api'}?server=:server&type=:type&id=:id&r=:r`
var meta = {
server: Theme.play.mu_source,
type: Theme.play.mu_type,
id: Theme.play.play_id,
auth: ''
}
if (state == true) {
let url = api.replace(":server", meta.server).replace(":type", meta.type).replace(":id", meta.id).replace(":auth", meta.auth).replace(":r", Math.random());
$.ajax({
type: "get",
url: url,
success: function (res) {
if (res.length > 0) {
var new_mid = 0;
if (loop == "none") {
new_mid = (Math.floor(Math.random() * res.length) + 1) - 1;
}
var f = res[new_mid];
var playnum = 1;
audiobox.attr('src', f.url);
playLrc = f.lrc;
$('.player_mod .m_cover img').attr('src', f.pic);
$('.player_mod .m_info h2').text(f.title || f.name);
$('.player_mod .m_info small').text(f.author || f.artist);
$('.player_box').append(audiobox);
playlist.push(res);
$.each(res, function (key, data) {
$(".musci_list_box").append('<li class="item" id=' + key + '>' + playnum++ + '. ' + (data.title || data.name) + ' - ' + (data.author || data.artist) + '</li>');
});
$(".musci_list_box li").removeClass('active').eq(new_mid).addClass('active');
} else {
$(".musci_list_box").append('<div class="nodata">背景音乐未设置</div>');
}
}
});
}
}
//播放选中音乐
function mulist_play(index) {
audiobox[0].removeEventListener("play", audioplay);
audiobox[0].removeEventListener("pause", audiopause);
$(".pix_player.playing .play_btn").html("<i class='ri-play-line'></i>");
$(".m_play").html('<i class="ri-pause-circle-fill"></i>');
$('.musci_list_box li').eq(index).addClass('active').siblings().removeClass('active');
scrollToPosition(index);
var data = playlist[0][index];
playLrc = data.lrc;
audiobox.attr('src', data.url);
m_cover.attr('src', data.pic);
m_title.text(data.title || data.name);
m_artist.text(data.author || data.artist);
audiobox[0].play();
Paused = false;
updateMusicBtnColor('play');
// 新增:切换歌曲后强制显示歌词
if (Theme.play.lrc_open && typeof lyricsContainer !== 'undefined') {
lyricsContainer.css('display', 'block');
$('a.bg_lrc i').css("color", "");
$('a.bg_lrc').css("background", "");
}
}
//点击展开播放列表
$(document).on('click', '.ri-bar-chart-horizontal-line', function () {
var position = $('.musci_list_box li.active').index()
setTimeout(function () {
if ($('.m_list').attr('aria-expanded')) {
scrollToPosition(position)
}
}, 200);
});
//点击列表播放
$(document).on('click', '.musci_list_box li', function () {
$('.musci_list_box li').removeClass('active');
$(this).addClass('active');
var id = $(this).attr('id');
mulist_play(id)
});
//上一首
$(document).on('click', '.m_prev', function () {
var index = $('.musci_list_box li.active').index() - 1;
var max = $('.musci_list_box li').length;
var new_mid = 0;
if (loop == "none") {
new_mid = (Math.floor(Math.random() * max) + 1) - 1;
} else {
new_mid = index < 0 ? max - 1 : index;
}
mulist_play(new_mid);
});
//下一首
$(document).on('click', '.m_next', function () {
var index = $('.musci_list_box li.active').index() + 1;
var max = $('.musci_list_box li').length;
var new_mid = 0;
if (loop == "none") {
new_mid = (Math.floor(Math.random() * max) + 1) - 1;
} else {
new_mid = index > (max - 1) ? 0 : index;
}
mulist_play(new_mid);
});
//播放和暂停
function m_play() {
if (Paused === false) {
audiobox[0].pause();
$('.m_play').html('<i class="ri-play-circle-fill"></i>');
Paused = true;
} else {
audiobox[0].play();
$('.m_play').html('<i class="ri-pause-circle-fill"></i>');
Paused = false;
}
}
//播放按钮
$(document).on('click', '.m_play', function () {
if (!$("#pix_player").length > 0) {
cocoMessage.error('没有音乐可播放');
return false;
} else {
m_play();
}
});
//触发显示播放器
var trigger;
let box_up = false;
function mu_box_show() {
clearTimeout(trigger);
box_up = true;
var mheight = $('.footer_nav_box').height();
$('.footer_nav_box').animate({ top: -mheight }, 200, 'linear');
}
function mu_box_hide(time = 2000) {
clearTimeout(trigger);
trigger = setTimeout(function () {
// 获取屏幕宽度判断是否为手机端(与歌词容器响应式逻辑保持一致)
const isMobile = $(window).width() <= 767;
// 手机端隐藏时额外向下偏移50px(可根据需要调整数值),非手机端保持默认0px
const hideTop = isMobile ? "50px" : "0px";
// 执行隐藏动画
$('.footer_nav_box').animate({
top: hideTop
}, 200, 'linear');
box_up = false;
}, time);
}
$(document).on('mouseenter', '.player_hand , .footer_nav_box', function (event) {
mu_box_show();
});
$(document).on('mouseleave', '.footer_nav_box .right_inner', function (event) {
trigger = setTimeout(function () {
mu_box_hide();
}, 2000);
});
//音乐进度条跳转
function getMousePosition(e) {
var e = e || window.event;
var x = e.pageX;
var y = e.pageY;
return { 'left': x, 'top': y }
}
$(document).on('click', '.player_bar', function () {
var long = (getMousePosition().left) - ($('.progress').offset().left);
$('.progress').width(long);
allTime = parseInt(audiobox[0].duration);
var nowtime = (long / $('.player_bar').width()) * allTime;
audiobox[0].currentTime = nowtime;
});
//音量调节 m_volume
$(document).on('click', '.m_volume', function () {
if ($(this).hasClass('mute')) {
$(this).removeClass('mute');
$(this).html('<i class="ri-volume-down-line"></i>');
audiobox[0].muted = false;
} else {
$(this).addClass('mute');
audiobox[0].muted = true;
$(this).html('<i class="ri-volume-mute-line"></i>');
}
});
$(document).on('click', '.vo_bar', function () {
var long = (getMousePosition().top) - ($(this).offset().top)
var meter = long / $(this).height();
var finalLong = 1 - meter;
$('.vo_size').height(finalLong * $(this).height());
audiobox[0].volume = finalLong;
});
//文章歌曲
function autoload_posts_music() {
post_playlist.splice(0, post_playlist.length);
var pid = $('.posts_mu_list').attr('pid');
var api = `${Theme.play.pix_mu_api || 'https://api.i-meto.com/meting/api'}?server=:server&type=:type&id=:id&r=:r`
var meta = {
server: $('.posts_mu_list').attr('mus_source'),
type: $('.posts_mu_list').attr('mus_type'),
id: $('.posts_mu_list').attr('plays_id'),
mu_on: $('.posts_mu_list').attr('mu_on'),
auth: ''
}
if (pid && meta.mu_on == 'true') {
let url = api.replace(":server", meta.server).replace(":type", meta.type).replace(":id", meta.id).replace(":auth", meta.auth).replace(":r", Math.random());
$.ajax({
type: "get",
url: url,
beforeSend: function () {
$('.posts_mu_list').html('<div class="loading_box"><div uk-spinner></div></div>');
},
success: function (res) {
if (res.length > 0) {
$('.posts_mu_list .loading_box').remove();
var playnum = 1;
if (!$('#pix_player').length > 0) {
$('.player_box').append(audiobox);
}
post_playlist.push(res);
$.each(res, function (key, data) {
$(".posts_mu_list").append('<li class="item" id=' + key + '><div class="mu_id">' + playnum++ + '</div><a class="s_play_btn"><i class="ri-play-circle-line"></i></a><div class="mus_info">' + (data.title || data.name) + ' <span>- ' + (data.author || data.artist) + '</span></div></li>');
});
}
}
});
}
}
//文章歌曲播放
$(document).on('click', '.s_play_btn', function () {
mu_box_show();
// 1. 同步更新文章内播放列表选中状态
$('.posts_mu_list li').removeClass('active');
$(this).parent().addClass('active');
// 2. 同步更新全局播放列表选中状态(避免后续操作信息混乱)
$('.musci_list_box li').removeClass('active');
// 移除旧事件监听,防止重复触发
audiobox[0].removeEventListener("play", audioplay);
audiobox[0].removeEventListener("pause", audiopause);
$(".m_play").html('<i class="ri-pause-circle-fill"></i>');
var id = $(this).parents('li').attr('id');
var data = post_playlist[0][id];
playLrc = data.lrc;
// 3. 修复歌手信息字段:优先用 data.author,其次用 data.artist
audiobox.attr('src', data.url);
m_cover.attr('src', data.pic);
m_title.text(data.title || data.name); // 歌曲标题:优先 title,其次 name
m_artist.text(data.author || data.artist); // 歌手信息:优先 author,其次 artist
audiobox[0].play();
Paused = false;
// 新增:文章歌曲切换后强制显示歌词
if (Theme.play.lrc_open && typeof lyricsContainer !== 'undefined') {
lyricsContainer.css('display', 'block');
$('a.bg_lrc i').css("color", "");
$('a.bg_lrc').css("background", "");
}
});
//播放器按钮
$(document).on('click', 'a.bg_music', function () {
if (!box_up) mu_box_show();
else mu_box_hide(0);
});
$(function () {
autoload_music();
autoload_posts_music();
});
//播放类型切换
$(document).on('click', '.audio_c_btn', function () {
var type = $(this).attr('au_type');
var input = $('<input type="text" placeholder="歌曲ID" name="moment_audio_api" id="moment_audio_api" class="required" required="required">');
$('.type_audio_text').empty();
$('.' + type + '_audio.type_audio_text').append(input);
});
$('.bg_lrc').click(function () {
if (lyricsContainer.css('display') === 'none') {
lyricsContainer.css('display', 'block');
$('a.bg_lrc i').css({
"color": "",
});
$('a.bg_lrc').css({
"background": "",
});
} else {
lyricsContainer.css('display', 'none');
$('a.bg_lrc i').css({
"color": "#aeaeae",
});
$('a.bg_lrc').css({
"background": "#EBF2ED",
});
}
});
//创建容器
if (Theme.play.lrc_open) {
var lyricsContainer = $('<div class="lyrics-container"></div>');
$('.player_box').append(lyricsContainer);
var css = $(window).width() > 767 ?
{
//桌面歌词css(按照下面格式自行修改)
position: 'fixed',
bottom: '10px',
left: '2%',
width: '350px',
height: '100px',
overflow: 'hidden',
zIndex: '999',
pointerEvents: 'none',
} :
{
//移动端歌词css(按照下面格式自行修改)
position: 'fixed',
top: '6px',
left: '0',
width: '100%',
height: '40px',
textAlign: 'center',
overflow: 'hidden',
zIndex: '999',
pointerEvents: 'none',
};
lyricsContainer.css(css);
}
var lyricsMap = {};
// 获取歌词
async function fetchLyrics(url) {
if (!lyricsMap[url]) {
var lrcOriginal = await $.get(url);
lyricsMap[url] = parseLyrics(lrcOriginal);
}
return lyricsMap[url];
}
// 解析歌词
function parseLyrics(lrcOriginal) {
var lyrics = [];
var lines = lrcOriginal.split("\n");
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (!line.trim()) {
continue;
}
var timeAndText = line.split("]");
var time = timeAndText[0].substr(1);
var text = timeAndText[1];
if (!text.trim()) {
continue;
}
var timeInSeconds = 0;
var timeParts = time.split(":");
timeInSeconds += parseInt(timeParts[0], 10) * 60 - 0.5;
timeInSeconds += parseFloat(timeParts[1]);
lyrics.push({
time: timeInSeconds,
text: text
});
}
return lyrics;
}
// 更新歌词
function updateLyrics(currentTime, lyrics) {
for (var i = 0; i < lyrics.length; i++) {
if (currentTime >= lyrics[i].time && (i === lyrics.length - 1 || currentTime < lyrics[i + 1].time)) {
// 定义各行列歌词内容
var prevLine = (i - 1 >= 0 && typeof lyrics[i - 1].text === "string") ? lyrics[i - 1].text : ""; // 上一行(i-1
var currentLine = (typeof lyrics[i].text === "string") ? lyrics[i].text : ""; // 当前行(i
var nextLine = (i + 1 < lyrics.length && typeof lyrics[i + 1].text === "string") ? lyrics[i + 1].text : ""; // 下一行(i+1
var nextNextLine = (i + 2 < lyrics.length && typeof lyrics[i + 2].text === "string") ? lyrics[i + 2].text : ""; // 下下一行(i+2
// 判断设备类型(<=767px为移动端)
var isMobile = $(window).width() <= 767;
if (isMobile) {
// 移动端:仅显示当前行+下一行
lyricsContainer.html(`
<div class="current-line active" style="font-size: 14px; margin-bottom: 6px; line-height: 1.2;">${currentLine}</div>
<div class="current-line" style="font-size: 12px; opacity: 0.7; line-height: 1.2;">${nextLine}</div>
`);
// 移动端适配动画(2行滚动距离)
$('.current-line').animate({
top: '-=25px'
}, 1000, function () {
$(this).css({
top: '25px'
});
});
} else {
// 电脑端:保持原有4行显示
lyricsContainer.html(`
<div class="current-line" style="font-size: 10px; opacity: .4;">${prevLine}</div>
<div class="current-line active" style="font-size: 14px;">${currentLine}</div>
<div class="current-line" style="font-size: 12px; opacity: .4;">${nextLine}</div>
<div class="current-line" style="font-size: 10px; opacity: .1;">${nextNextLine}</div>
`);
// 电脑端原动画
$('.current-line').animate({
top: '-=30px'
}, 2000, function () {
$(this).css({
top: '30px'
});
});
}
}
}
}
// 监听音频播放进度更新事件,更新歌词
Theme.play.lrc_open && audiobox[0].addEventListener("timeupdate", async function () {
// 新增:只有歌词容器显示时才更新歌词(优化性能)
if (Theme.play.lrc_open && typeof lyricsContainer !== 'undefined' && lyricsContainer.css('display') !== 'none') {
var lyrics = await fetchLyrics(playLrc)
updateLyrics(this.currentTime, lyrics);
}
});
// 根据选择的位置定位滚动条
function scrollToPosition(position) {
let container = document.getElementById("musci_list");
let items = container.getElementsByClassName("item");
if (position >= 0 && position < items.length) {
items[position].scrollIntoView();
}
}
// 更新底部音乐图标颜色(根据是否播放)
function updateFooterMusicIcon(isPlaying) {
// 查找底部菜单中包含音乐图标的链接
var $entry = $('.footer_menu a').filter(function () {
return $(this).find('.ri-netease-cloud-music-line').length > 0;
}).first();
if ($entry.length) {
if (isPlaying) {
$entry.addClass('playing-music');
} else {
$entry.removeClass('playing-music');
}
}
}
// 绑定 audio 播放/暂停事件
audiobox[0].addEventListener("play", function () {
updateFooterMusicIcon(true);
});
audiobox[0].addEventListener("pause", function () {
updateFooterMusicIcon(false);
});
// 初始和 PJAX 完成后同步状态
function syncFooterWithAudioState() {
var isPlaying = !!(audiobox && audiobox[0] && !audiobox[0].paused && !audiobox[0].ended);
updateFooterMusicIcon(isPlaying);
}