const anzhiyu = {
debounce: (func, wait = 0, immediate = false) => {
let timeout;
return (...args) => {
const later = () => {
timeout = null;
if (!immediate) func(...args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func(...args);
};
},
throttle: function (func, wait, options = {}) {
let timeout, context, args;
let previous = 0;
const later = () => {
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
func.apply(context, args);
if (!timeout) context = args = null;
};
const throttled = (...params) => {
const now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
const remaining = wait - (now - previous);
context = this;
args = params;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
};
return throttled;
},
sidebarPaddingR: () => {
const innerWidth = window.innerWidth;
const clientWidth = document.body.clientWidth;
const paddingRight = innerWidth - clientWidth;
if (innerWidth !== clientWidth) {
document.body.style.paddingRight = paddingRight + "px";
}
},
snackbarShow: (text, showActionFunction = false, duration = 2000, actionText = false) => {
const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar;
const bg = document.documentElement.getAttribute("data-theme") === "light" ? bgLight : bgDark;
const root = document.querySelector(":root");
root.style.setProperty("--anzhiyu-snackbar-time", duration + "ms");
Snackbar.show({
text: text,
backgroundColor: bg,
onActionClick: showActionFunction,
actionText: actionText,
showAction: actionText,
duration: duration,
pos: position,
customClass: "snackbar-css",
});
},
loadComment: (dom, callback) => {
if ("IntersectionObserver" in window) {
const observerItem = new IntersectionObserver(
entries => {
if (entries[0].isIntersecting) {
callback();
observerItem.disconnect();
}
},
{ threshold: [0] }
);
observerItem.observe(dom);
} else {
callback();
}
},
scrollToDest: (pos, time = 500) => {
const currentPos = window.pageYOffset;
if ("scrollBehavior" in document.documentElement.style) {
window.scrollTo({
top: pos,
behavior: "smooth",
});
return;
}
let start = null;
pos = +pos;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
const progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress) / time + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress) / time);
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
},
initJustifiedGallery: function (selector) {
const runJustifiedGallery = i => {
if (!anzhiyu.isHidden(i)) {
fjGallery(i, {
itemSelector: ".fj-gallery-item",
rowHeight: i.getAttribute("data-rowHeight"),
gutter: 4,
onJustify: function () {
this.$container.style.opacity = "1";
},
});
}
};
if (Array.from(selector).length === 0) runJustifiedGallery(selector);
else
selector.forEach(i => {
runJustifiedGallery(i);
});
},
animateIn: (ele, text) => {
ele.style.display = "block";
ele.style.animation = text;
},
animateOut: (ele, text) => {
ele.addEventListener("animationend", function f() {
ele.style.display = "";
ele.style.animation = "";
ele.removeEventListener("animationend", f);
});
ele.style.animation = text;
},
/**
* @param {*} selector
* @param {*} eleType the type of create element
* @param {*} options object key: value
*/
wrap: (selector, eleType, options) => {
const creatEle = document.createElement(eleType);
for (const [key, value] of Object.entries(options)) {
creatEle.setAttribute(key, value);
}
selector.parentNode.insertBefore(creatEle, selector);
creatEle.appendChild(selector);
},
isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0,
getEleTop: ele => {
let actualTop = ele.offsetTop;
let current = ele.offsetParent;
while (current !== null) {
actualTop += current.offsetTop;
current = current.offsetParent;
}
return actualTop;
},
loadLightbox: ele => {
const service = GLOBAL_CONFIG.lightbox;
if (service === "mediumZoom") {
const zoom = mediumZoom(ele);
zoom.on("open", e => {
const photoBg = document.documentElement.getAttribute("data-theme") === "dark" ? "#121212" : "#fff";
zoom.update({
background: photoBg,
});
});
}
if (service === "fancybox") {
Array.from(ele).forEach(i => {
if (i.parentNode.tagName !== "A") {
const dataSrc = i.dataset.lazySrc || i.src;
const dataCaption = i.title || i.alt || "";
anzhiyu.wrap(i, "a", {
href: dataSrc,
"data-fancybox": "gallery",
"data-caption": dataCaption,
"data-thumb": dataSrc,
});
}
});
if (!window.fancyboxRun) {
Fancybox.bind("[data-fancybox]", {
Hash: false,
Thumbs: {
autoStart: false,
},
});
window.fancyboxRun = true;
}
}
},
setLoading: {
add: ele => {
const html = `
`;
ele.insertAdjacentHTML("afterend", html);
},
remove: ele => {
ele.nextElementSibling.remove();
},
},
updateAnchor: anchor => {
if (anchor !== window.location.hash) {
if (!anchor) anchor = location.pathname;
const title = GLOBAL_CONFIG_SITE.title;
window.history.replaceState(
{
url: location.href,
title,
},
title,
anchor
);
}
},
getScrollPercent: (currentTop, ele) => {
const docHeight = ele.clientHeight;
const winHeight = document.documentElement.clientHeight;
const headerHeight = ele.offsetTop;
const contentMath =
docHeight > winHeight ? docHeight - winHeight : document.documentElement.scrollHeight - winHeight;
const scrollPercent = (currentTop - headerHeight) / contentMath;
const scrollPercentRounded = Math.round(scrollPercent * 100);
const percentage = scrollPercentRounded > 100 ? 100 : scrollPercentRounded <= 0 ? 0 : scrollPercentRounded;
return percentage;
},
addGlobalFn: (key, fn, name = false, parent = window) => {
const globalFn = parent.globalFn || {};
const keyObj = globalFn[key] || {};
if (name && keyObj[name]) return;
name = name || Object.keys(keyObj).length;
keyObj[name] = fn;
globalFn[key] = keyObj;
parent.globalFn = globalFn;
},
addEventListenerPjax: (ele, event, fn, option = false) => {
ele.addEventListener(event, fn, option);
anzhiyu.addGlobalFn("pjax", () => {
ele.removeEventListener(event, fn, option);
});
},
removeGlobalFnEvent: (key, parent = window) => {
const { globalFn = {} } = parent;
const keyObj = globalFn[key] || {};
const keyArr = Object.keys(keyObj);
if (!keyArr.length) return;
keyArr.forEach(i => {
keyObj[i]();
});
delete parent.globalFn[key];
},
//更改主题色
changeThemeMetaColor: function (color) {
// console.info(`%c ${color}`, `font-size:36px;color:${color};`);
if (themeColorMeta !== null) {
themeColorMeta.setAttribute("content", color);
}
},
//顶栏自适应主题色
initThemeColor: function () {
let themeColor = getComputedStyle(document.documentElement)
.getPropertyValue("--anzhiyu-bar-background")
.trim()
.replace('"', "")
.replace('"', "");
const currentTop = window.scrollY || document.documentElement.scrollTop;
if (currentTop > 26) {
if (anzhiyu.is_Post()) {
themeColor = getComputedStyle(document.documentElement)
.getPropertyValue("--anzhiyu-meta-theme-post-color")
.trim()
.replace('"', "")
.replace('"', "");
}
if (themeColorMeta.getAttribute("content") === themeColor) return;
this.changeThemeMetaColor(themeColor);
} else {
if (themeColorMeta.getAttribute("content") === themeColor) return;
this.changeThemeMetaColor(themeColor);
}
},
//是否是文章页
is_Post: function () {
var url = window.location.href; //获取url
if (url.indexOf("/posts/") >= 0) {
//判断url地址中是否包含code字符串
return true;
} else {
return false;
}
},
//监测是否在页面开头
addNavBackgroundInit: function () {
var scrollTop = 0,
bodyScrollTop = 0,
documentScrollTop = 0;
if ($bodyWrap) {
bodyScrollTop = $bodyWrap.scrollTop;
}
if (document.documentElement) {
documentScrollTop = document.documentElement.scrollTop;
}
scrollTop = bodyScrollTop - documentScrollTop > 0 ? bodyScrollTop : documentScrollTop;
if (scrollTop != 0) {
pageHeaderEl.classList.add("nav-fixed");
pageHeaderEl.classList.add("nav-visible");
}
},
// 下载图片
downloadImage: function (imgsrc, name) {
//下载图片地址和图片名
rm.hideRightMenu();
if (rm.downloadimging == false) {
rm.downloadimging = true;
anzhiyu.snackbarShow("正在下载中,请稍后", false, 10000);
setTimeout(function () {
let image = new Image();
// 解决跨域 Canvas 污染问题
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据
let a = document.createElement("a"); // 生成一个a元素
let event = new MouseEvent("click"); // 创建一个单击事件
a.download = name || "photo"; // 设置图片名称
a.href = url; // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
};
image.src = imgsrc;
anzhiyu.snackbarShow("图片已添加盲水印,请遵守版权协议");
rm.downloadimging = false;
}, "10000");
} else {
anzhiyu.snackbarShow("有正在进行中的下载,请稍后再试");
}
},
//禁止图片右键单击
stopImgRightDrag: function () {
var img = document.getElementsByTagName("img");
for (var i = 0; i < img.length; i++) {
img[i].addEventListener("dragstart", function () {
return false;
});
}
},
//滚动到指定id
scrollTo: function (id) {
var domTop = document.querySelector(id).offsetTop;
window.scrollTo(0, domTop - 80);
},
//隐藏侧边栏
hideAsideBtn: () => {
// Hide aside
const $htmlDom = document.documentElement.classList;
$htmlDom.contains("hide-aside")
? saveToLocal.set("aside-status", "show", 2)
: saveToLocal.set("aside-status", "hide", 2);
$htmlDom.toggle("hide-aside");
$htmlDom.contains("hide-aside")
? document.querySelector("#consoleHideAside").classList.add("on")
: document.querySelector("#consoleHideAside").classList.remove("on");
},
// 热评切换
switchCommentBarrage: function () {
let commentBarrage = document.querySelector(".comment-barrage");
if (commentBarrage) {
if (window.getComputedStyle(commentBarrage).display === "flex") {
commentBarrage.style.display = "none";
anzhiyu.snackbarShow("✨ 已关闭评论弹幕");
document.querySelector(".menu-commentBarrage-text").textContent = "显示热评";
document.querySelector("#consoleCommentBarrage").classList.remove("on");
localStorage.setItem("commentBarrageSwitch", "false");
} else {
commentBarrage.style.display = "flex";
document.querySelector(".menu-commentBarrage-text").textContent = "关闭热评";
document.querySelector("#consoleCommentBarrage").classList.add("on");
anzhiyu.snackbarShow("✨ 已开启评论弹幕");
localStorage.removeItem("commentBarrageSwitch");
}
}
rm && rm.hideRightMenu();
},
initPaginationObserver: () => {
const commentElement = document.getElementById("post-comment");
const paginationElement = document.getElementById("pagination");
if (commentElement && paginationElement) {
new IntersectionObserver(entries => {
const commentBarrage = document.querySelector(".comment-barrage");
entries.forEach(entry => {
if (entry.isIntersecting) {
paginationElement.classList.add("show-window");
if (commentBarrage) {
commentBarrage.style.bottom = "-200px";
}
} else {
paginationElement.classList.remove("show-window");
if (commentBarrage) {
commentBarrage.style.bottom = "0px";
}
}
});
}).observe(commentElement);
}
},
// 初始化即刻
initIndexEssay: function () {
if (!document.getElementById("bbTimeList")) return;
setTimeout(() => {
let essay_bar_swiper = new Swiper(".essay_bar_swiper_container", {
passiveListeners: true,
direction: "vertical",
loop: true,
autoplay: {
disableOnInteraction: true,
delay: 3000,
},
mousewheel: true,
});
let essay_bar_comtainer = document.getElementById("bbtalk");
if (essay_bar_comtainer !== null) {
essay_bar_comtainer.onmouseenter = function () {
essay_bar_swiper.autoplay.stop();
};
essay_bar_comtainer.onmouseleave = function () {
essay_bar_swiper.autoplay.start();
};
}
}, 100);
},
scrollByMouseWheel: function ($list, $target) {
const scrollHandler = function (e) {
$list.scrollLeft -= e.wheelDelta / 2;
e.preventDefault();
};
$list.addEventListener("mousewheel", scrollHandler, { passive: false });
if ($target) {
$target.classList.add("selected");
$list.scrollLeft = $target.offsetLeft - $list.offsetLeft - ($list.offsetWidth - $target.offsetWidth) / 2;
}
},
// catalog激活
catalogActive: function () {
const $list = document.getElementById("catalog-list");
if ($list) {
const pathname = decodeURIComponent(window.location.pathname);
const catalogListItems = $list.querySelectorAll(".catalog-list-item");
let $catalog = null;
catalogListItems.forEach(item => {
if (pathname.startsWith(item.id)) {
$catalog = item;
return;
}
});
anzhiyu.scrollByMouseWheel($list, $catalog);
}
},
// Page Tag 激活
tagsPageActive: function () {
const $list = document.getElementById("tag-page-tags");
if ($list) {
const $tagPageTags = document.getElementById(decodeURIComponent(window.location.pathname));
anzhiyu.scrollByMouseWheel($list, $tagPageTags);
}
},
// 修改时间显示"最近"
diffDate: function (d, more = false, simple = false) {
const dateNow = new Date();
const datePost = new Date(d);
const dateDiff = dateNow.getTime() - datePost.getTime();
const minute = 1000 * 60;
const hour = minute * 60;
const day = hour * 24;
const month = day * 30;
let result;
if (more) {
const monthCount = dateDiff / month;
const dayCount = dateDiff / day;
const hourCount = dateDiff / hour;
const minuteCount = dateDiff / minute;
if (monthCount >= 1) {
result = datePost.toLocaleDateString().replace(/\//g, "-");
} else if (dayCount >= 1) {
result = parseInt(dayCount) + " " + GLOBAL_CONFIG.date_suffix.day;
} else if (hourCount >= 1) {
result = parseInt(hourCount) + " " + GLOBAL_CONFIG.date_suffix.hour;
} else if (minuteCount >= 1) {
result = parseInt(minuteCount) + " " + GLOBAL_CONFIG.date_suffix.min;
} else {
result = GLOBAL_CONFIG.date_suffix.just;
}
} else if (simple) {
const monthCount = dateDiff / month;
const dayCount = dateDiff / day;
const hourCount = dateDiff / hour;
const minuteCount = dateDiff / minute;
if (monthCount >= 1) {
result = datePost.toLocaleDateString().replace(/\//g, "-");
} else if (dayCount >= 1 && dayCount <= 3) {
result = parseInt(dayCount) + " " + GLOBAL_CONFIG.date_suffix.day;
} else if (dayCount > 3) {
result = datePost.getMonth() + 1 + "/" + datePost.getDate();
} else if (hourCount >= 1) {
result = parseInt(hourCount) + " " + GLOBAL_CONFIG.date_suffix.hour;
} else if (minuteCount >= 1) {
result = parseInt(minuteCount) + " " + GLOBAL_CONFIG.date_suffix.min;
} else {
result = GLOBAL_CONFIG.date_suffix.just;
}
} else {
result = parseInt(dateDiff / day);
}
return result;
},
// 修改即刻中的时间显示
changeTimeInEssay: function () {
document.querySelector("#bber") &&
document.querySelectorAll("#bber time").forEach(function (e) {
var t = e,
datetime = t.getAttribute("datetime");
(t.innerText = anzhiyu.diffDate(datetime, true)), (t.style.display = "inline");
});
},
// 修改相册集中的时间
changeTimeInAlbumDetail: function () {
document.querySelector("#album_detail") &&
document.querySelectorAll("#album_detail time").forEach(function (e) {
var t = e,
datetime = t.getAttribute("datetime");
(t.innerText = anzhiyu.diffDate(datetime, true)), (t.style.display = "inline");
});
},
// 刷新瀑布流
reflashEssayWaterFall: function () {
const waterfallEl = document.getElementById("waterfall");
if (waterfallEl) {
setTimeout(function () {
waterfall(waterfallEl);
waterfallEl.classList.add("show");
}, 800);
}
},
sayhi: function () {
const $sayhiEl = document.getElementById("author-info__sayhi");
const getTimeState = () => {
const hour = new Date().getHours();
let message = "";
if (hour >= 0 && hour <= 5) {
message = "睡个好觉,保证精力充沛";
} else if (hour > 5 && hour <= 10) {
message = "一日之计在于晨";
} else if (hour > 10 && hour <= 14) {
message = "吃饱了才有力气干活";
} else if (hour > 14 && hour <= 18) {
message = "集中精力,攻克难关";
} else if (hour > 18 && hour <= 24) {
message = "不要太劳累了,早睡更健康";
}
return message;
};
if ($sayhiEl) {
$sayhiEl.innerHTML = getTimeState();
}
},
// 友链注入预设评论
addFriendLink() {
var input = document.getElementsByClassName("el-textarea__inner")[0];
if (!input) return;
const evt = new Event("input", { cancelable: true, bubbles: true });
const defaultPlaceholder =
"昵称(请勿包含博客等字样):\n网站地址(要求博客地址,请勿提交个人主页):\n头像图片url(请提供尽可能清晰的图片,我会上传到我自己的图床):\n描述:\n站点截图(可选):\n";
input.value = this.getConfigIfPresent(GLOBAL_CONFIG.linkPageTop, "addFriendPlaceholder", defaultPlaceholder);
input.dispatchEvent(evt);
input.focus();
input.setSelectionRange(-1, -1);
},
// 获取配置,如果为空则返回默认值
getConfigIfPresent: function (config, configKey, defaultValue) {
if (!config) return defaultValue;
if (!config.hasOwnProperty(configKey)) return defaultValue;
if (!config[configKey]) return defaultValue;
return config[configKey];
},
//切换音乐播放状态
musicToggle: function (changePaly = true) {
if (!anzhiyu_musicFirst) {
anzhiyu.musicBindEvent();
anzhiyu_musicFirst = true;
}
let msgPlay = '播放音乐';
let msgPause = '暂停音乐';
if (anzhiyu_musicPlaying) {
navMusicEl.classList.remove("playing");
document.getElementById("menu-music-toggle").innerHTML = msgPlay;
document.getElementById("nav-music-hoverTips").innerHTML = "音乐已暂停";
document.querySelector("#consoleMusic").classList.remove("on");
anzhiyu_musicPlaying = false;
navMusicEl.classList.remove("stretch");
} else {
navMusicEl.classList.add("playing");
document.getElementById("menu-music-toggle").innerHTML = msgPause;
document.querySelector("#consoleMusic").classList.add("on");
anzhiyu_musicPlaying = true;
navMusicEl.classList.add("stretch");
}
if (changePaly) document.querySelector("#nav-music meting-js").aplayer.toggle();
rm && rm.hideRightMenu();
},
// 音乐伸缩
musicTelescopic: function () {
if (navMusicEl.classList.contains("stretch")) {
navMusicEl.classList.remove("stretch");
} else {
navMusicEl.classList.add("stretch");
}
},
//音乐上一曲
musicSkipBack: function () {
navMusicEl.querySelector("meting-js").aplayer.skipBack();
rm && rm.hideRightMenu();
},
//音乐下一曲
musicSkipForward: function () {
navMusicEl.querySelector("meting-js").aplayer.skipForward();
rm && rm.hideRightMenu();
},
//获取音乐中的名称
musicGetName: function () {
var x = document.querySelector(".aplayer-title");
var arr = [];
for (var i = x.length - 1; i >= 0; i--) {
arr[i] = x[i].innerText;
}
return arr[0];
},
//初始化console图标
initConsoleState: function () {
//初始化隐藏边栏
const $htmlDomClassList = document.documentElement.classList;
$htmlDomClassList.contains("hide-aside")
? document.querySelector("#consoleHideAside").classList.add("on")
: document.querySelector("#consoleHideAside").classList.remove("on");
},
// 显示打赏中控台
rewardShowConsole: function () {
// 判断是否为赞赏打开控制台
consoleEl.classList.add("reward-show");
anzhiyu.initConsoleState();
},
// 显示中控台
showConsole: function () {
consoleEl.classList.add("show");
anzhiyu.initConsoleState();
},
//隐藏中控台
hideConsole: function () {
if (consoleEl.classList.contains("show")) {
// 如果是一般控制台,就关闭一般控制台
consoleEl.classList.remove("show");
} else if (consoleEl.classList.contains("reward-show")) {
// 如果是打赏控制台,就关闭打赏控制台
consoleEl.classList.remove("reward-show");
}
// 获取center-console元素
const centerConsole = document.getElementById("center-console");
// 检查center-console是否被选中
if (centerConsole.checked) {
// 取消选中状态
centerConsole.checked = false;
}
},
// 取消加载动画
hideLoading: function () {
document.getElementById("loading-box").classList.add("loaded");
},
// 将音乐缓存播放
cacheAndPlayMusic() {
let data = localStorage.getItem("musicData");
if (data) {
data = JSON.parse(data);
const currentTime = new Date().getTime();
if (currentTime - data.timestamp < 24 * 60 * 60 * 1000) {
// 如果缓存的数据没有过期,直接使用
anzhiyu.playMusic(data.songs);
return;
}
}
// 否则重新从服务器获取数据
fetch("/json/music.json")
.then(response => response.json())
.then(songs => {
const cacheData = {
timestamp: new Date().getTime(),
songs: songs,
};
localStorage.setItem("musicData", JSON.stringify(cacheData));
anzhiyu.playMusic(songs);
});
},
// 播放音乐
playMusic(songs) {
const anMusicPage = document.getElementById("anMusic-page");
const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
const randomIndex = Math.floor(Math.random() * songs.length);
const randomSong = songs[randomIndex];
const allAudios = metingAplayer.list.audios;
if (!selectRandomSong.includes(randomSong.name)) {
// 如果随机到的歌曲已经未被随机到过,就添加进metingAplayer.list
metingAplayer.list.add([randomSong]);
// 播放最后一首(因为是添加到了最后)
metingAplayer.list.switch(allAudios.length);
// 添加到已被随机的歌曲列表
selectRandomSong.push(randomSong.name);
} else {
// 随机到的歌曲已经在播放列表中了
// 直接继续随机直到随机到没有随机过的歌曲,如果全部随机过了就切换到对应的歌曲播放即可
let songFound = false;
while (!songFound) {
const newRandomIndex = Math.floor(Math.random() * songs.length);
const newRandomSong = songs[newRandomIndex];
if (!selectRandomSong.includes(newRandomSong.name)) {
metingAplayer.list.add([newRandomSong]);
metingAplayer.list.switch(allAudios.length);
selectRandomSong.push(newRandomSong.name);
songFound = true;
}
// 如果全部歌曲都已被随机过,跳出循环
if (selectRandomSong.length === songs.length) {
break;
}
}
if (!songFound) {
// 如果全部歌曲都已被随机过,切换到对应的歌曲播放
const palyMusicIndex = allAudios.findIndex(song => song.name === randomSong.name);
if (palyMusicIndex != -1) metingAplayer.list.switch(palyMusicIndex);
}
}
console.info("已随机歌曲:", selectRandomSong, "本次随机歌曲:", randomSong.name);
},
// 音乐节目切换背景
changeMusicBg: function (isChangeBg = true) {
const anMusicBg = document.getElementById("an_music_bg");
if (isChangeBg) {
// player listswitch 会进入此处
const musiccover = document.querySelector("#anMusic-page .aplayer-pic");
anMusicBg.style.backgroundImage = musiccover.style.backgroundImage;
} else {
// 第一次进入,绑定事件,改背景
let timer = setInterval(() => {
const musiccover = document.querySelector("#anMusic-page .aplayer-pic");
// 确保player加载完成
if (musiccover) {
clearInterval(timer);
// 绑定事件
anzhiyu.addEventListenerMusic();
// 确保第一次能够正确替换背景
anzhiyu.changeMusicBg();
// 暂停nav的音乐
if (
document.querySelector("#nav-music meting-js").aplayer &&
!document.querySelector("#nav-music meting-js").aplayer.audio.paused
) {
anzhiyu.musicToggle();
}
}
}, 100);
}
},
// 获取自定义播放列表
getCustomPlayList: function () {
if (!window.location.pathname.startsWith("/music/")) {
return;
}
const urlParams = new URLSearchParams(window.location.search);
const userId = "8152976493";
const userServer = "netease";
const anMusicPageMeting = document.getElementById("anMusic-page-meting");
if (urlParams.get("id") && urlParams.get("server")) {
const id = urlParams.get("id");
const server = urlParams.get("server");
anMusicPageMeting.innerHTML = ``;
} else {
anMusicPageMeting.innerHTML = ``;
}
anzhiyu.changeMusicBg(false);
},
//隐藏今日推荐
hideTodayCard: function () {
if (document.getElementById("todayCard")) {
document.getElementById("todayCard").classList.add("hide");
const topGroup = document.querySelector(".topGroup");
const recentPostItems = topGroup.querySelectorAll(".recent-post-item");
recentPostItems.forEach(item => {
item.style.display = "flex";
});
}
},
// 监听音乐背景改变
addEventListenerMusic: function () {
const anMusicPage = document.getElementById("anMusic-page");
const aplayerIconMenu = anMusicPage.querySelector(".aplayer-info .aplayer-time .aplayer-icon-menu");
const anMusicBtnGetSong = anMusicPage.querySelector("#anMusicBtnGetSong");
const anMusicRefreshBtn = anMusicPage.querySelector("#anMusicRefreshBtn");
const anMusicSwitchingBtn = anMusicPage.querySelector("#anMusicSwitching");
const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
//初始化音量
metingAplayer.volume(0.8, true);
metingAplayer.on("loadeddata", function () {
anzhiyu.changeMusicBg();
});
aplayerIconMenu.addEventListener("click", function () {
document.getElementById("menu-mask").style.display = "block";
document.getElementById("menu-mask").style.animation = "0.5s ease 0s 1 normal none running to_show";
anMusicPage.querySelector(".aplayer.aplayer-withlist .aplayer-list").style.opacity = "1";
});
function anMusicPageMenuAask() {
if (window.location.pathname != "/music/") {
document.getElementById("menu-mask").removeEventListener("click", anMusicPageMenuAask);
return;
}
anMusicPage.querySelector(".aplayer-list").classList.remove("aplayer-list-hide");
}
document.getElementById("menu-mask").addEventListener("click", anMusicPageMenuAask);
// 监听增加单曲按钮
anMusicBtnGetSong.addEventListener("click", () => {
if (changeMusicListFlag) {
const anMusicPage = document.getElementById("anMusic-page");
const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
const allAudios = metingAplayer.list.audios;
const randomIndex = Math.floor(Math.random() * allAudios.length);
// 随机播放一首
metingAplayer.list.switch(randomIndex);
} else {
anzhiyu.cacheAndPlayMusic();
}
});
anMusicRefreshBtn.addEventListener("click", () => {
localStorage.removeItem("musicData");
anzhiyu.snackbarShow("已移除相关缓存歌曲");
});
anMusicSwitchingBtn.addEventListener("click", () => {
anzhiyu.changeMusicList();
});
// 监听键盘事件
//空格控制音乐
document.addEventListener("keydown", function (event) {
//暂停开启音乐
if (event.code === "Space") {
event.preventDefault();
metingAplayer.toggle();
}
//切换下一曲
if (event.keyCode === 39) {
event.preventDefault();
metingAplayer.skipForward();
}
//切换上一曲
if (event.keyCode === 37) {
event.preventDefault();
metingAplayer.skipBack();
}
//增加音量
if (event.keyCode === 38) {
if (musicVolume <= 1) {
musicVolume += 0.1;
metingAplayer.volume(musicVolume, true);
}
}
//减小音量
if (event.keyCode === 40) {
if (musicVolume >= 0) {
musicVolume += -0.1;
metingAplayer.volume(musicVolume, true);
}
}
});
},
// 切换歌单
changeMusicList: async function () {
const anMusicPage = document.getElementById("anMusic-page");
const metingAplayer = anMusicPage.querySelector("meting-js").aplayer;
const currentTime = new Date().getTime();
const cacheData = JSON.parse(localStorage.getItem("musicData")) || { timestamp: 0 };
let songs = [];
if (changeMusicListFlag) {
songs = defaultPlayMusicList;
} else {
// 保存当前默认播放列表,以使下次可以切换回来
defaultPlayMusicList = metingAplayer.list.audios;
// 如果缓存的数据没有过期,直接使用
if (currentTime - cacheData.timestamp < 24 * 60 * 60 * 1000) {
songs = cacheData.songs;
} else {
// 否则重新从服务器获取数据
const response = await fetch("/json/music.json");
songs = await response.json();
cacheData.timestamp = currentTime;
cacheData.songs = songs;
localStorage.setItem("musicData", JSON.stringify(cacheData));
}
}
// 清除当前播放列表并添加新的歌曲
metingAplayer.list.clear();
metingAplayer.list.add(songs);
// 切换标志位
changeMusicListFlag = !changeMusicListFlag;
},
// 控制台音乐列表监听
addEventListenerConsoleMusicList: function () {
const navMusic = document.getElementById("nav-music");
if (!navMusic) return;
navMusic.addEventListener("click", e => {
const aplayerList = navMusic.querySelector(".aplayer-list");
const listBtn = navMusic.querySelector(
"div.aplayer-info > div.aplayer-controller > div.aplayer-time.aplayer-time-narrow > button.aplayer-icon.aplayer-icon-menu svg"
);
if (e.target != listBtn && aplayerList.classList.contains("aplayer-list-hide")) {
aplayerList.classList.remove("aplayer-list-hide");
}
});
},
// 监听按键
toPage: function () {
var toPageText = document.getElementById("toPageText"),
toPageButton = document.getElementById("toPageButton"),
pageNumbers = document.querySelectorAll(".page-number"),
lastPageNumber = Number(pageNumbers[pageNumbers.length - 1].innerHTML),
pageNumber = Number(toPageText.value);
if (!isNaN(pageNumber) && pageNumber >= 1 && Number.isInteger(pageNumber)) {
var url = "/page/" + (pageNumber > lastPageNumber ? lastPageNumber : pageNumber) + "/";
toPageButton.href = pageNumber === 1 ? "/" : url;
} else {
toPageButton.href = "javascript:void(0);";
}
},
//删除多余的class
removeBodyPaceClass: function () {
document.body.className = "pace-done";
},
// 修改body的type类型以适配css
setValueToBodyType: function () {
const input = document.getElementById("page-type"); // 获取input元素
const value = input.value; // 获取input的value值
document.body.dataset.type = value; // 将value值赋值到body的type属性上
},
//匿名评论
addRandomCommentInfo: function () {
// 从形容词数组中随机取一个值
const randomAdjective = adjectives[Math.floor(Math.random() * adjectives.length)];
// 从蔬菜水果动物名字数组中随机取一个值
const randomName = vegetablesAndFruits[Math.floor(Math.random() * vegetablesAndFruits.length)];
// 将两个值组合成一个字符串
const name = `${randomAdjective}${randomName}`;
function dr_js_autofill_commentinfos() {
var lauthor = [
"#author",
"input[name='comname']",
"#inpName",
"input[name='author']",
"#ds-dialog-name",
"#name",
"input[name='nick']",
"#comment_author",
],
lmail = [
"#mail",
"#email",
"input[name='commail']",
"#inpEmail",
"input[name='email']",
"#ds-dialog-email",
"input[name='mail']",
"#comment_email",
],
lurl = [
"#url",
"input[name='comurl']",
"#inpHomePage",
"#ds-dialog-url",
"input[name='url']",
"input[name='website']",
"#website",
"input[name='link']",
"#comment_url",
];
for (var i = 0; i < lauthor.length; i++) {
var author = document.querySelector(lauthor[i]);
if (author != null) {
author.value = name;
author.dispatchEvent(new Event("input"));
author.dispatchEvent(new Event("change"));
break;
}
}
for (var j = 0; j < lmail.length; j++) {
var mail = document.querySelector(lmail[j]);
if (mail != null) {
mail.value = visitorMail;
mail.dispatchEvent(new Event("input"));
mail.dispatchEvent(new Event("change"));
break;
}
}
return !1;
}
dr_js_autofill_commentinfos();
var input = document.getElementsByClassName("el-textarea__inner")[0];
input.focus();
input.setSelectionRange(-1, -1);
},
// 跳转开往
totraveling: function () {
anzhiyu.snackbarShow(
"即将跳转到「开往」项目的成员博客,不保证跳转网站的安全性和可用性",
element => {
element.style.opacity = 0;
travellingsTimer && clearTimeout(travellingsTimer);
},
5000,
"取消"
);
travellingsTimer = setTimeout(function () {
window.open("https://www.travellings.cn/go.html", "_blank");
}, "5000");
},
// 工具函数替换字符串
replaceAll: function (e, n, t) {
return e.split(n).join(t);
},
// 音乐绑定事件
musicBindEvent: function () {
document.querySelector("#nav-music .aplayer-music").addEventListener("click", function () {
anzhiyu.musicTelescopic();
});
document.querySelector("#nav-music .aplayer-button").addEventListener("click", function () {
anzhiyu.musicToggle(false);
});
},
// 判断是否是移动端
hasMobile: function () {
let isMobile = false;
if (
navigator.userAgent.match(
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
) ||
document.body.clientWidth < 800
) {
// 移动端
isMobile = true;
}
return isMobile;
},
// 创建二维码
qrcodeCreate: function () {
if (document.getElementById("qrcode")) {
document.getElementById("qrcode").innerHTML = "";
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: window.location.href,
width: 250,
height: 250,
colorDark: "#000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H,
});
}
},
// 判断是否在el内
isInViewPortOfOne: function (el) {
if (!el) return;
const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
const offsetTop = el.offsetTop;
const scrollTop = document.documentElement.scrollTop;
const top = offsetTop - scrollTop;
return top <= viewPortHeight;
},
//添加赞赏蒙版
addRewardMask: function () {
if (!document.querySelector(".reward-main")) return;
document.querySelector(".reward-main").style.display = "flex";
document.querySelector(".reward-main").style.zIndex = "102";
document.getElementById("quit-box").style.display = "flex";
},
// 移除赞赏蒙版
removeRewardMask: function () {
if (!document.querySelector(".reward-main")) return;
document.querySelector(".reward-main").style.display = "none";
document.getElementById("quit-box").style.display = "none";
},
keyboardToggle: function () {
const isKeyboardOn = anzhiyu_keyboard;
if (isKeyboardOn) {
const consoleKeyboard = document.querySelector("#consoleKeyboard");
consoleKeyboard.classList.remove("on");
anzhiyu_keyboard = false;
} else {
const consoleKeyboard = document.querySelector("#consoleKeyboard");
consoleKeyboard.classList.add("on");
anzhiyu_keyboard = true;
}
localStorage.setItem("keyboardToggle", isKeyboardOn ? "false" : "true");
},
rightMenuToggle: function () {
if (window.oncontextmenu) {
window.oncontextmenu = null;
} else if (!window.oncontextmenu && oncontextmenuFunction) {
window.oncontextmenu = oncontextmenuFunction;
}
},
switchConsole: () => {
// switch console
const consoleEl = document.getElementById("console");
//初始化隐藏边栏
const $htmlDom = document.documentElement.classList;
$htmlDom.contains("hide-aside")
? document.querySelector("#consoleHideAside").classList.add("on")
: document.querySelector("#consoleHideAside").classList.remove("on");
if (consoleEl.classList.contains("show")) {
consoleEl.classList.remove("show");
} else {
consoleEl.classList.add("show");
}
const consoleKeyboard = document.querySelector("#consoleKeyboard");
if (consoleKeyboard) {
if (localStorage.getItem("keyboardToggle") === "true") {
consoleKeyboard.classList.add("on");
anzhiyu_keyboard = true;
} else {
consoleKeyboard.classList.remove("on");
anzhiyu_keyboard = false;
}
}
},
// 定义 intersectionObserver 函数,并接收两个可选参数
intersectionObserver: function (enterCallback, leaveCallback) {
let observer;
return () => {
if (!observer) {
observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
enterCallback?.();
} else {
leaveCallback?.();
}
});
});
} else {
// 如果 observer 对象已经存在,则先取消对之前元素的观察
observer.disconnect();
}
return observer;
};
},
// CategoryBar滚动
scrollCategoryBarToRight: function () {
// 获取需要操作的元素
const items = document.getElementById("catalog-list");
const nextButton = document.getElementById("category-bar-next");
// 检查元素是否存在
if (items && nextButton) {
const itemsWidth = items.clientWidth;
// 判断是否已经滚动到最右侧
if (items.scrollLeft + items.clientWidth + 1 >= items.scrollWidth) {
// 滚动到初始位置并更新按钮内容
items.scroll({
left: 0,
behavior: "smooth",
});
nextButton.innerHTML = '';
} else {
// 滚动到下一个视图
items.scrollBy({
left: itemsWidth,
behavior: "smooth",
});
}
} else {
console.error("Element(s) not found: 'catalog-list' and/or 'category-bar-next'.");
}
},
// 分类条
categoriesBarActive: function () {
const urlinfo = decodeURIComponent(window.location.pathname);
const $categoryBar = document.getElementById("category-bar");
if (!$categoryBar) return;
if (urlinfo === "/") {
$categoryBar.querySelector("#首页").classList.add("select");
} else {
const pattern = /\/categories\/.*?\//;
const patbool = pattern.test(urlinfo);
if (!patbool) return;
const nowCategorie = urlinfo.split("/")[2];
$categoryBar.querySelector(`#${nowCategorie}`).classList.add("select");
}
},
topCategoriesBarScroll: function () {
const $categoryBarItems = document.getElementById("category-bar-items");
if (!$categoryBarItems) return;
$categoryBarItems.addEventListener("mousewheel", function (e) {
const v = -e.wheelDelta / 2;
this.scrollLeft += v;
e.preventDefault();
});
},
// 切换菜单显示热评
switchRightClickMenuHotReview: function () {
const postComment = document.getElementById("post-comment");
const menuCommentBarrageDom = document.getElementById("menu-commentBarrage");
if (postComment) {
menuCommentBarrageDom.style.display = "flex";
} else {
menuCommentBarrageDom.style.display = "none";
}
},
// 切换作者卡片状态文字
changeSayHelloText: function () {
const greetings = GLOBAL_CONFIG.authorStatus.skills;
const authorInfoSayHiElement = document.getElementById("author-info__sayhi");
// 如果只有一个问候语,设置为默认值
if (greetings.length === 1) {
authorInfoSayHiElement.textContent = greetings[0];
return;
}
let lastSayHello = authorInfoSayHiElement.textContent;
let randomGreeting = lastSayHello;
while (randomGreeting === lastSayHello) {
randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
}
authorInfoSayHiElement.textContent = randomGreeting;
},
};
const anzhiyuPopupManager = {
queue: [],
processing: false,
Jump: false,
enqueuePopup(title, tip, url, duration = 3000) {
this.queue.push({ title, tip, url, duration });
if (!this.processing) {
this.processQueue();
}
},
processQueue() {
if (this.queue.length > 0 && !this.processing) {
this.processing = true;
const { title, tip, url, duration } = this.queue.shift();
this.popupShow(title, tip, url, duration);
}
},
popupShow(title, tip, url, duration) {
const popupWindow = document.getElementById("popup-window");
if (!popupWindow) return;
const windowTitle = popupWindow.querySelector(".popup-window-title");
const windowContent = popupWindow.querySelector(".popup-window-content");
const cookiesTip = windowContent.querySelector(".popup-tip");
if (popupWindow.classList.contains("show-popup-window")) {
popupWindow.classList.add("popup-hide");
}
// 等待上一个弹窗完全消失
setTimeout(() => {
// 移除之前的点击事件处理程序
popupWindow.removeEventListener("click", this.clickEventHandler);
if (url) {
if (window.pjax) {
this.clickEventHandler = event => {
event.preventDefault();
pjax.loadUrl(url);
popupWindow.classList.remove("show-popup-window");
popupWindow.classList.remove("popup-hide");
this.Jump = true;
// 处理队列中的下一个弹出窗口
this.processing = false;
this.processQueue();
};
popupWindow.addEventListener("click", this.clickEventHandler);
} else {
this.clickEventHandler = () => {
window.location.href = url;
};
popupWindow.addEventListener("click", this.clickEventHandler);
}
if (popupWindow.classList.contains("no-url")) {
popupWindow.classList.remove("no-url");
}
} else {
if (!popupWindow.classList.contains("no-url")) {
popupWindow.classList.add("no-url");
}
this.clickEventHandler = () => {
popupWindow.classList.add("popup-hide");
setTimeout(() => {
popupWindow.classList.remove("popup-hide");
popupWindow.classList.remove("show-popup-window");
}, 1000);
};
popupWindow.addEventListener("click", this.clickEventHandler);
}
if (popupWindow.classList.contains("popup-hide")) {
popupWindow.classList.remove("popup-hide");
}
popupWindow.classList.add("show-popup-window");
windowTitle.textContent = title;
cookiesTip.textContent = tip;
}, 800);
setTimeout(() => {
if (url && !this.Jump) {
this.Jump = false;
}
if (!popupWindow.classList.contains("popup-hide") && popupWindow.className != "") {
popupWindow.classList.add("popup-hide");
}
// 处理队列中的下一个弹出窗口
this.processing = false;
this.processQueue();
}, duration);
},
};