live2d-widget/waifu-tips.js
2021-02-14 21:13:01 +08:00

315 lines
14 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.

/*
* Live2D Widget
* https://github.com/stevenjoezhang/live2d-widget
*/
function loadWidget(config) {
let { waifuPath, apiPath, cdnPath } = config;
let useCDN = false, modelList;
if (typeof cdnPath === "string") {
useCDN = true;
if (!cdnPath.endsWith("/")) cdnPath += "/";
} else if (typeof apiPath === "string") {
if (!apiPath.endsWith("/")) apiPath += "/";
} else {
console.error("Invalid initWidget argument!");
return;
}
localStorage.removeItem("waifu-display");
sessionStorage.removeItem("waifu-text");
document.body.insertAdjacentHTML("beforeend", `<div id="waifu">
<div id="waifu-tips"></div>
<canvas id="live2d" width="800" height="800"></canvas>
<div id="waifu-tool" name="waifu-tool" onloud>
<span class="fa fa-lg fa-comment"></span>
<span class="fa fa-lg fa-paper-plane"></span>
<span class="fa fa-lg fa-user-circle"></span>
<span class="fa fa-lg fa-street-view"></span>
<span class="fa fa-lg fa-camera-retro"></span>
<span class="fa fa-lg fa-info-circle"></span>
<span class="fa fa-lg fa-times"></span>
<span class="fa fa-lg fa-chevron-right" id="live2d-go-right"></span>
<span class="fa fa-lg fa-chevron-left" id="live2d-go-left"></span>
</div>
</div>`);
// https://stackoverflow.com/questions/24148403/trigger-css-transition-on-appended-element
setTimeout(() => {
document.getElementById("waifu").style.bottom = 0;
}, 0);
function randomSelection(obj) {
return Array.isArray(obj) ? obj[Math.floor(Math.random() * obj.length)] : obj;
}
// 检测用户活动状态,并在空闲时显示消息
let userAction = false,
userActionTimer,
messageTimer,
messageArray = ["好久不见,日子过得好快呢……", "大坏蛋!你都多久没理人家了呀,嘤嘤嘤~", "嗨~快来逗我玩吧!", "拿小拳拳锤你胸口!", "记得把小家加入 Adblock 白名单哦!"];
window.addEventListener("mousemove", () => userAction = true);
window.addEventListener("keydown", () => userAction = true);
setInterval(() => {
if (userAction) {
userAction = false;
clearInterval(userActionTimer);
userActionTimer = null;
} else if (!userActionTimer) {
userActionTimer = setInterval(() => {
showMessage(randomSelection(messageArray), 6000, 9);
}, 20000);
}
}, 1000);
(function () { // 根据位置加载
if (localStorage.getItem("Live2DPlace") === "left") {
document.getElementById("live2d-go-left").style.display = "none";
} else if (localStorage.getItem("Live2DPlace") === "right") {
document.getElementById("live2d-go-right").style.display = "none";
document.getElementById("live2d_css").href = live2d_path + "waifu_right.css";
}
})();
(function registerEventListener() { // 工具栏菜单效果
document.querySelector("#waifu-tool .fa-comment").addEventListener("click", showHitokoto); // 一言API对话
document.querySelector("#waifu-tool .fa-paper-plane").addEventListener("click", () => { // 飞机大战(雾)
if (window.Asteroids) {
if (!window.ASTEROIDSPLAYERS) window.ASTEROIDSPLAYERS = [];
window.ASTEROIDSPLAYERS.push(new Asteroids());
} else {
const script = document.createElement("script");
script.src = "https://cdn.jsdelivr.net/gh/stevenjoezhang/asteroids/asteroids.js";
document.head.appendChild(script);
}
});
document.querySelector("#waifu-tool .fa-user-circle").addEventListener("click", loadOtherModel); // 切换模型
document.querySelector("#waifu-tool .fa-street-view").addEventListener("click", loadRandModel); // 切换材质
document.querySelector("#waifu-tool .fa-camera-retro").addEventListener("click", () => { // 输出照片
showMessage("照好了嘛,是不是很可爱呢?", 6000, 9);
Live2D.captureName = "photo.png"; // 输出照片的名字
Live2D.captureFrame = true;
});
document.querySelector("#waifu-tool .fa-info-circle").addEventListener("click", () => { // 关于页转跳
open("https://github.com/PFiS1737/PFiS_Public_Repository/tree/main/page/effect/Live2D/live2d-widget"); //关于页链接
});
document.querySelector("#waifu-tool .fa-times").addEventListener("click", () => { // 关闭看板娘
localStorage.setItem("waifu-display", Date.now());
showMessage("愿你有一天能与重要的人重逢。", 2000, 11);
document.getElementById("waifu").style.bottom = "-500px";
setTimeout(() => {
document.getElementById("waifu").style.display = "none";
document.getElementById("waifu-toggle").classList.add("waifu-toggle-active");
}, 3000);
});
document.querySelector("#waifu-tool .fa-chevron-right").addEventListener("click", () => { // 切换看板娘位置(左 => 右)
localStorage.setItem("Live2DPlace", "right");
showMessage("耶,可以去右边了呢~。", 2000, 11);
document.getElementById("waifu").style.bottom = "-500px";
setTimeout('document.getElementById("live2d_css").setAttribute("href",live2d_path + "waifu_right.css")',3000);
setTimeout('document.getElementById("waifu").style.bottom = "0px"',3000);
});
document.querySelector("#waifu-tool .fa-chevron-left").addEventListener("click", () => { // 切换看板娘位置(左 <= 右)
localStorage.setItem("Live2DPlace", "left");
showMessage("耶,可以去左边了呢~。", 2000, 11);
document.getElementById("waifu").style.bottom = "-500px";
setTimeout('document.getElementById("live2d_css").setAttribute("href",live2d_path + "waifu_left.css")',3000);
setTimeout('document.getElementById("waifu").style.bottom = "0px"',3000);
});
const devtools = () => { };
console.log("%c", devtools);
devtools.toString = () => {
showMessage("哈哈,你打开了控制台,是想要看看我的小秘密吗?", 6000, 9);
};
window.addEventListener("copy", () => {
showMessage("你都复制了些什么呀,转载要记得加上出处哦!", 6000, 9);
});
window.addEventListener("visibilitychange", () => {
if (!document.hidden) showMessage("哇,你终于回来了~", 6000, 9);
});
})();
(function welcomeMessage() {
let text;
if (location.pathname === "/") { // 如果是主页
const now = new Date().getHours();
if (now > 5 && now <= 7) text = "早上好!一日之计在于晨,美好的一天就要开始了。";
else if (now > 7 && now <= 11) text = "上午好!工作顺利嘛,不要久坐,多起来走动走动哦!";
else if (now > 11 && now <= 13) text = "中午了,工作了一个上午,现在是午餐时间!";
else if (now > 13 && now <= 17) text = "午后很容易犯困呢,今天的运动目标完成了吗?";
else if (now > 17 && now <= 19) text = "傍晚了!窗外夕阳的景色很美丽呢,最美不过夕阳红~";
else if (now > 19 && now <= 21) text = "晚上好,今天过得怎么样?";
else if (now > 21 && now <= 23) text = ["已经这么晚了呀,早点休息吧,晚安~", "深夜时要爱护眼睛呀!"];
else text = "你是夜猫子呀?这么晚还不睡觉,明天起的来嘛?";
} else if (document.referrer !== "") {
const referrer = new URL(document.referrer),
domain = referrer.hostname.split(".")[1];
if (location.hostname === referrer.hostname) text = `欢迎阅读<span>「${document.title.split(" - ")[0]}」</span>`;
else if (domain === "baidu") text = `Hello来自 百度搜索 的朋友<br>你是搜索 <span>${referrer.search.split("&wd=")[1].split("&")[0]}</span> 找到的我吗?`;
else if (domain === "so") text = `Hello来自 360搜索 的朋友<br>你是搜索 <span>${referrer.search.split("&q=")[1].split("&")[0]}</span> 找到的我吗?`;
else if (domain === "google") text = `Hello来自 谷歌搜索 的朋友<br>欢迎阅读<span>「${document.title.split(" - ")[0]}」</span>`;
else text = `Hello来自 <span>${referrer.hostname}</span> 的朋友`;
} else {
text = `欢迎阅读<span>「${document.title.split(" - ")[0]}」</span>`;
}
showMessage(text, 7000, 8);
})();
function showHitokoto() { // 增加 hitokoto.cn 的 API
fetch("https://v1.hitokoto.cn")
.then(response => response.json())
.then(result => {
const text = `这句一言来自 <span>「${result.from}」</span>,是 <span>${result.creator}</span> 在 hitokoto.cn 投稿的。`;
showMessage(result.hitokoto, 6000, 9);
setTimeout(() => {
showMessage(text, 4000, 9);
}, 6000);
});
}
function showMessage(text, timeout, priority) {
if (!text || (sessionStorage.getItem("waifu-text") && sessionStorage.getItem("waifu-text") > priority)) return;
if (messageTimer) {
clearTimeout(messageTimer);
messageTimer = null;
}
text = randomSelection(text);
sessionStorage.setItem("waifu-text", priority);
const tips = document.getElementById("waifu-tips");
tips.innerHTML = text;
tips.classList.add("waifu-tips-active");
messageTimer = setTimeout(() => {
sessionStorage.removeItem("waifu-text");
tips.classList.remove("waifu-tips-active");
}, timeout);
}
(function initModel() {
let modelId = localStorage.getItem("modelId"),
modelTexturesId = localStorage.getItem("modelTexturesId");
if (modelId === null) {
// 首次访问时加载 指定模型 的 指定材质
modelId = 2; // 模型 ID
modelTexturesId = 39; // 材质 ID
}
loadModel(modelId, modelTexturesId);
fetch(waifuPath)
.then(response => response.json())
.then(result => {
window.addEventListener("mouseover", event => {
for (let tips of result.mouseover) {
if (!event.target.matches(tips.selector)) continue;
let text = randomSelection(tips.text);
text = text.replace("{text}", event.target.innerText);
showMessage(text, 4000, 8);
return;
}
});
window.addEventListener("click", event => {
for (let tips of result.click) {
if (!event.target.matches(tips.selector)) continue;
let text = randomSelection(tips.text);
text = text.replace("{text}", event.target.innerText);
showMessage(text, 4000, 8);
return;
}
});
result.seasons.forEach(tips => {
const now = new Date(),
after = tips.date.split("-")[0],
before = tips.date.split("-")[1] || after;
if ((after.split("/")[0] <= now.getMonth() + 1 && now.getMonth() + 1 <= before.split("/")[0]) && (after.split("/")[1] <= now.getDate() && now.getDate() <= before.split("/")[1])) {
let text = randomSelection(tips.text);
text = text.replace("{year}", now.getFullYear());
//showMessage(text, 7000, true);
messageArray.push(text);
}
});
});
})();
async function loadModelList() {
const response = await fetch(`${cdnPath}model_list.json`);
modelList = await response.json();
}
async function loadModel(modelId, modelTexturesId, message) {
localStorage.setItem("modelId", modelId);
localStorage.setItem("modelTexturesId", modelTexturesId);
showMessage(message, 4000, 10);
if (useCDN) {
if (!modelList) await loadModelList();
const target = randomSelection(modelList.models[modelId]);
loadlive2d("live2d", `${cdnPath}model/${target}/index.json`);
} else {
loadlive2d("live2d", `${apiPath}get/?id=${modelId}-${modelTexturesId}`);
console.log(`Live2D 模型 ${modelId}-${modelTexturesId} 加载完成`);
}
}
async function loadRandModel() {
const modelId = localStorage.getItem("modelId"),
modelTexturesId = localStorage.getItem("modelTexturesId");
if (useCDN) {
if (!modelList) await loadModelList();
const target = randomSelection(modelList.models[modelId]);
loadlive2d("live2d", `${cdnPath}model/${target}/index.json`);
showMessage("我的新衣服好看嘛?", 4000, 10);
} else {
// 材质加载方式, 可选 "rand"(随机), "switch"(顺序)
fetch(`${apiPath}switch_textures/?id=${modelId}-${modelTexturesId}`)
.then(response => response.json())
.then(result => {
if (result.textures.id === 1 && (modelTexturesId === 1 || modelTexturesId === 0)) showMessage("我还没有其他衣服呢!", 4000, 10);
else loadModel(modelId, result.textures.id, "我的新衣服好看嘛?");
});
}
}
async function loadOtherModel() {
let modelId = localStorage.getItem("modelId");
if (useCDN) {
if (!modelList) await loadModelList();
const index = (++modelId >= modelList.models.length) ? 0 : modelId;
loadModel(index, 0, modelList.messages[index]);
} else {
fetch(`${apiPath}switch/?id=${modelId}`)
.then(response => response.json())
.then(result => {
loadModel(result.model.id, 0, result.model.message);
});
}
}
}
function initWidget(config, apiPath) {
if (typeof config === "string") {
config = {
waifuPath: config,
apiPath
};
}
document.body.insertAdjacentHTML("beforeend", `<div id="waifu-toggle">
<span>看板娘</span>
</div>`);
const toggle = document.getElementById("waifu-toggle");
toggle.addEventListener("click", () => {
toggle.classList.remove("waifu-toggle-active");
if (toggle.getAttribute("first-time")) {
loadWidget(config);
toggle.removeAttribute("first-time");
} else {
localStorage.removeItem("waifu-display");
document.getElementById("waifu").style.display = "";
setTimeout(() => {
document.getElementById("waifu").style.bottom = 0;
}, 0);
}
});
if (localStorage.getItem("waifu-display") && Date.now() - localStorage.getItem("waifu-display") <= 86400000) {
toggle.setAttribute("first-time", true);
setTimeout(() => {
toggle.classList.add("waifu-toggle-active");
}, 0);
} else {
loadWidget(config);
}
}