From df35f18c80360406246bbaa7070d8c4cb580dd21 Mon Sep 17 00:00:00 2001
From: PFiS <69380732+PFiS1737@users.noreply.github.com>
Date: Sun, 14 Feb 2021 21:11:27 +0800
Subject: [PATCH] Add files via upload
---
autoload.js | 65 ++++++++++
waifu-tips.js | 317 +++++++++++++++++++++++++++++++++++++++++++++
waifu_left.css | 332 ++++++++++++++++++++++++++++++++++++++++++++++++
waifu_right.css | 332 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1046 insertions(+)
create mode 100644 autoload.js
create mode 100644 waifu-tips.js
create mode 100644 waifu_left.css
create mode 100644 waifu_right.css
diff --git a/autoload.js b/autoload.js
new file mode 100644
index 0000000..83fd938
--- /dev/null
+++ b/autoload.js
@@ -0,0 +1,65 @@
+// 注意:live2d_path 参数应使用绝对路径
+const live2d_path = "/effect/Live2D/live2d-widget/";
+
+// 封装异步加载资源的方法
+function loadExternalResource(url, type) {
+ return new Promise((resolve, reject) => {
+ let tag;
+
+ if (type === "css") {
+ tag = document.createElement("link");
+ tag.rel = "stylesheet";
+ tag.href = url;
+ tag.id = "live2d_css";
+ }
+ else if (type === "js") {
+ tag = document.createElement("script");
+ tag.src = url;
+ }
+ if (tag) {
+ tag.onload = () => resolve(url);
+ tag.onerror = () => reject(url);
+ document.head.appendChild(tag);
+ }
+ });
+}
+
+// 加载 waifu.css live2d.min.js waifu-tips.js
+if (screen.width >= 768) {
+ // "768"为最低显示宽度,单位为像素
+ Promise.all([
+ loadExternalResource(live2d_path + "waifu_left.css", "css"),
+ loadExternalResource(live2d_path + "live2d.min.js", "js"),
+ loadExternalResource(live2d_path + "waifu-tips.js", "js")
+ ]).then(() => {
+ initWidget({
+ waifuPath: live2d_path + "waifu-tips.json",
+ // apiPath: "https://api.zsq.im/live2d/",
+ apiPath: "https://live2d.fghrsh.net/api/",
+ // cdnPath: "https://cdn.jsdelivr.net/gh/fghrsh/live2d_api/"
+ });
+ });
+}
+// initWidget 第一个参数为 waifu-tips.json 的路径,第二个参数为 API 地址
+// API 后端可自行搭建,参考 https://github.com/fghrsh/live2d_api
+// 初始化看板娘会自动加载指定目录下的 waifu-tips.json
+
+console.log(`
+ く__,.ヘヽ. / ,ー、 〉
+ \ ', !-─‐-i / /´
+ /`ー' L//`ヽ、
+ / /, /| , , ',
+ イ / /-‐/ i L_ ハ ヽ! i
+ レ ヘ 7イ`ト レ'ァ-ト、!ハ| |
+ !,/7 '0' ´0iソ| |
+ |.从" _ ,,,, / |./ |
+ レ'| i>.、,,__ _,.イ / .i |
+ レ'| | / k_7_/レ'ヽ, ハ. |
+ | |/i 〈|/ i ,.ヘ | i |
+ .|/ / i: ヘ! \ |
+ kヽ>、ハ _,.ヘ、 /、!
+ !'〈//`T´', \ `'7'ーr'
+ レ'ヽL__|___i,___,ンレ|ノ
+ ト-,/ |___./
+ 'ー' !_,.:
+`);
diff --git a/waifu-tips.js b/waifu-tips.js
new file mode 100644
index 0000000..6ebb312
--- /dev/null
+++ b/waifu-tips.js
@@ -0,0 +1,317 @@
+/*
+ * Live2D Widget
+ * Original from https://github.com/stevenjoezhang/live2d-widget
+ * https://github.com/PFiS1737/PFiS_Public_Repository/tree/main/live2d
+ */
+
+const live2d_path = "/effect/Live2D/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", `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`);
+ // 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 = `欢迎阅读「${document.title.split(" - ")[0]}」`;
+ else if (domain === "baidu") text = `Hello!来自 百度搜索 的朋友
你是搜索 ${referrer.search.split("&wd=")[1].split("&")[0]} 找到的我吗?`;
+ else if (domain === "so") text = `Hello!来自 360搜索 的朋友
你是搜索 ${referrer.search.split("&q=")[1].split("&")[0]} 找到的我吗?`;
+ else if (domain === "google") text = `Hello!来自 谷歌搜索 的朋友
欢迎阅读「${document.title.split(" - ")[0]}」`;
+ else text = `Hello!来自 ${referrer.hostname} 的朋友`;
+ } else {
+ text = `欢迎阅读「${document.title.split(" - ")[0]}」`;
+ }
+ showMessage(text, 7000, 8);
+ })();
+
+ function showHitokoto() { // 增加 hitokoto.cn 的 API
+ fetch("https://v1.hitokoto.cn")
+ .then(response => response.json())
+ .then(result => {
+ const text = `这句一言来自 「${result.from}」,是 ${result.creator} 在 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", `
+ 看板娘
+
`);
+ 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);
+ }
+}
diff --git a/waifu_left.css b/waifu_left.css
new file mode 100644
index 0000000..04b52ec
--- /dev/null
+++ b/waifu_left.css
@@ -0,0 +1,332 @@
+/* 看板娘隐藏后的“看板娘”按钮 */
+#waifu-toggle {
+ background-color: #fa0;
+ border-radius: 5px;
+ bottom: 66px;
+ color: #fff;
+ cursor: pointer;
+ font-size: 12px;
+ left: 0;
+ margin-left: -100px;
+ padding: 5px 2px 5px 5px;
+ position: fixed;
+ transition: margin-left 1s;
+ width: 60px;
+ writing-mode: vertical-rl;
+ z-index: 1000;
+}
+
+#waifu-toggle.waifu-toggle-active {
+ margin-left: -50px;
+}
+
+#waifu-toggle.waifu-toggle-active:hover {
+ margin-left: -30px;
+}
+
+/* 看板娘主体 */
+#waifu {
+ bottom: -1000px;
+ left: 0;
+ line-height: 0;
+ position: fixed;
+ transform: translateY(3px);
+ /* margin-bottom: -10px; */
+ transition: transform .3s ease-in-out, bottom 3s ease-in-out;
+ z-index: 1000;
+}
+
+#waifu:hover {
+ transform: translateY(0);
+}
+
+/* 看板娘对话框 */
+#waifu-tips {
+ animation: shake 50s ease-in-out 5s infinite;
+ background-color: rgba(236, 217, 188, .5);
+ border: 1px solid rgba(224, 186, 140, .62);
+ border-radius: 12px;
+ box-shadow: 0 3px 15px 2px rgba(191, 158, 118, .2);
+ font-size: 14px;
+ line-height: 24px;
+ margin: -30px 20px;
+ min-height: 70px;
+ opacity: 0;
+ overflow: hidden;
+ padding: 5px 10px;
+ position: absolute;
+ text-overflow: ellipsis;
+ transition: opacity 1s;
+ width: 250px;
+ word-break: break-all;
+ /* display: none !important; */
+}
+
+#waifu-tips.waifu-tips-active {
+ opacity: 1;
+ transition: opacity .2s;
+}
+
+#waifu-tips span {
+ color: #0099cc;
+}
+
+#waifu #live2d {
+ cursor: grab;
+ height: 300px;
+ position: relative;
+ width: 300px;
+}
+
+#waifu #live2d:active {
+ cursor: grabbing;
+}
+
+/* 工具栏 */
+#waifu-tool {
+ color: #aaa;
+ opacity: 0;
+ position: absolute;
+ right: -10px;
+ top: 55px;
+ transition: opacity 1s;
+}
+
+#waifu:hover #waifu-tool {
+ opacity: 1;
+}
+
+#waifu-tool span {
+ color: #5b6c7d;
+ cursor: pointer;
+ display: block;
+ line-height: 30px;
+ text-align: center;
+ transition: color .3s;
+}
+
+#waifu-tool .fa-chevron-right {
+ color: #5b6c7d;
+ cursor: pointer;
+ display: block;
+ margin: 7px 0px;
+ text-align: center;
+ transition: color .3s;
+}
+
+#waifu-tool .fa-chevron-left {
+ color: #5b6c7d;
+ cursor: pointer;
+ display: block;
+ margin-top: 23px;
+ text-align: center;
+ transition: color .3s;
+}
+
+/* 工具栏触碰后的颜色 */
+#waifu-tool span:hover {
+ color: #0684bd;
+ /* color: #34495e; */
+}
+
+@keyframes shake {
+ 2% {
+ transform: translate(.5px, -1.5px) rotate(-.5deg);
+ }
+
+ 4% {
+ transform: translate(.5px, 1.5px) rotate(1.5deg);
+ }
+
+ 6% {
+ transform: translate(1.5px, 1.5px) rotate(1.5deg);
+ }
+
+ 8% {
+ transform: translate(2.5px, 1.5px) rotate(.5deg);
+ }
+
+ 10% {
+ transform: translate(.5px, 2.5px) rotate(.5deg);
+ }
+
+ 12% {
+ transform: translate(1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 14% {
+ transform: translate(.5px, .5px) rotate(.5deg);
+ }
+
+ 16% {
+ transform: translate(-1.5px, -.5px) rotate(1.5deg);
+ }
+
+ 18% {
+ transform: translate(.5px, .5px) rotate(1.5deg);
+ }
+
+ 20% {
+ transform: translate(2.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 22% {
+ transform: translate(.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 24% {
+ transform: translate(-1.5px, 1.5px) rotate(-.5deg);
+ }
+
+ 26% {
+ transform: translate(1.5px, .5px) rotate(1.5deg);
+ }
+
+ 28% {
+ transform: translate(-.5px, -.5px) rotate(-.5deg);
+ }
+
+ 30% {
+ transform: translate(1.5px, -.5px) rotate(-.5deg);
+ }
+
+ 32% {
+ transform: translate(2.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 34% {
+ transform: translate(2.5px, 2.5px) rotate(-.5deg);
+ }
+
+ 36% {
+ transform: translate(.5px, -1.5px) rotate(.5deg);
+ }
+
+ 38% {
+ transform: translate(2.5px, -.5px) rotate(-.5deg);
+ }
+
+ 40% {
+ transform: translate(-.5px, 2.5px) rotate(.5deg);
+ }
+
+ 42% {
+ transform: translate(-1.5px, 2.5px) rotate(.5deg);
+ }
+
+ 44% {
+ transform: translate(-1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 46% {
+ transform: translate(1.5px, -.5px) rotate(-.5deg);
+ }
+
+ 48% {
+ transform: translate(2.5px, -.5px) rotate(.5deg);
+ }
+
+ 50% {
+ transform: translate(-1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 52% {
+ transform: translate(-.5px, 1.5px) rotate(.5deg);
+ }
+
+ 54% {
+ transform: translate(-1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 56% {
+ transform: translate(.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 58% {
+ transform: translate(2.5px, 2.5px) rotate(.5deg);
+ }
+
+ 60% {
+ transform: translate(2.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 62% {
+ transform: translate(-1.5px, .5px) rotate(1.5deg);
+ }
+
+ 64% {
+ transform: translate(-1.5px, 1.5px) rotate(1.5deg);
+ }
+
+ 66% {
+ transform: translate(.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 68% {
+ transform: translate(2.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 70% {
+ transform: translate(2.5px, 2.5px) rotate(.5deg);
+ }
+
+ 72% {
+ transform: translate(-.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 74% {
+ transform: translate(-1.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 76% {
+ transform: translate(-1.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 78% {
+ transform: translate(-1.5px, 2.5px) rotate(.5deg);
+ }
+
+ 80% {
+ transform: translate(-1.5px, .5px) rotate(-.5deg);
+ }
+
+ 82% {
+ transform: translate(-1.5px, .5px) rotate(-.5deg);
+ }
+
+ 84% {
+ transform: translate(-.5px, .5px) rotate(1.5deg);
+ }
+
+ 86% {
+ transform: translate(2.5px, 1.5px) rotate(.5deg);
+ }
+
+ 88% {
+ transform: translate(-1.5px, .5px) rotate(1.5deg);
+ }
+
+ 90% {
+ transform: translate(-1.5px, -.5px) rotate(-.5deg);
+ }
+
+ 92% {
+ transform: translate(-1.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 94% {
+ transform: translate(.5px, .5px) rotate(-.5deg);
+ }
+
+ 96% {
+ transform: translate(2.5px, -.5px) rotate(-.5deg);
+ }
+
+ 98% {
+ transform: translate(-1.5px, -1.5px) rotate(-.5deg);
+ }
+
+ 0%, 100% {
+ transform: translate(0, 0) rotate(0);
+ }
+}
diff --git a/waifu_right.css b/waifu_right.css
new file mode 100644
index 0000000..3598560
--- /dev/null
+++ b/waifu_right.css
@@ -0,0 +1,332 @@
+/* 看板娘隐藏后的“看板娘”按钮 */
+#waifu-toggle {
+ background-color: #fa0;
+ border-radius: 5px;
+ bottom: 66px;
+ color: #fff;
+ cursor: pointer;
+ font-size: 12px;
+ right: 0;
+ margin-right: -100px;
+ padding: 5px 2px 5px 5px;
+ position: fixed;
+ transition: margin-right 1s;
+ width: 60px;
+ writing-mode: vertical-lr;
+ z-index: 1000;
+}
+
+#waifu-toggle.waifu-toggle-active {
+ margin-right: -40px;
+}
+
+#waifu-toggle.waifu-toggle-active:hover {
+ margin-right: -20px;
+}
+
+/* 看板娘主体 */
+#waifu {
+ bottom: -1000px;
+ right: 0;
+ line-height: 0;
+ position: fixed;
+ transform: translateY(3px);
+ /* margin-bottom: -10px; */
+ transition: transform .3s ease-in-out, bottom 3s ease-in-out;
+ z-index: 1000;
+}
+
+#waifu:hover {
+ transform: translateY(0);
+}
+
+/* 看板娘对话框 */
+#waifu-tips {
+ animation: shake 50s ease-in-out 5s infinite;
+ background-color: rgba(236, 217, 188, .5);
+ border: 1px solid rgba(224, 186, 140, .62);
+ border-radius: 12px;
+ box-shadow: 0 3px 15px 2px rgba(191, 158, 118, .2);
+ font-size: 14px;
+ line-height: 24px;
+ margin: -30px 20px;
+ min-height: 70px;
+ opacity: 0;
+ overflow: hidden;
+ padding: 5px 10px;
+ position: absolute;
+ text-overflow: ellipsis;
+ transition: opacity 1s;
+ width: 250px;
+ word-break: break-all;
+ /* display: none !important; */
+}
+
+#waifu-tips.waifu-tips-active {
+ opacity: 1;
+ transition: opacity .2s;
+}
+
+#waifu-tips span {
+ color: #0099cc;
+}
+
+#waifu #live2d {
+ cursor: grab;
+ height: 300px;
+ position: relative;
+ width: 300px;
+}
+
+#waifu #live2d:active {
+ cursor: grabbing;
+}
+
+/* 工具栏 */
+#waifu-tool {
+ color: #aaa;
+ opacity: 0;
+ position: absolute;
+ left: 10px;
+ top: 55px;
+ transition: opacity 1s;
+}
+
+#waifu:hover #waifu-tool {
+ opacity: 1;
+}
+
+#waifu-tool span {
+ color: #5b6c7d;
+ cursor: pointer;
+ display: block;
+ line-height: 30px;
+ text-align: center;
+ transition: color .3s;
+}
+
+#waifu-tool .fa-chevron-right {
+ color: #5b6c7d;
+ cursor: pointer;
+ display: block;
+ margin: 7px 0px;
+ text-align: center;
+ transition: color .3s;
+}
+
+#waifu-tool .fa-chevron-left {
+ color: #5b6c7d;
+ cursor: pointer;
+ display: block;
+ margin-top: 23px;
+ text-align: center;
+ transition: color .3s;
+}
+
+/* 工具栏触碰后的颜色 */
+#waifu-tool span:hover {
+ color: #0684bd;
+ /* color: #34495e; */
+}
+
+@keyframes shake {
+ 2% {
+ transform: translate(.5px, -1.5px) rotate(-.5deg);
+ }
+
+ 4% {
+ transform: translate(.5px, 1.5px) rotate(1.5deg);
+ }
+
+ 6% {
+ transform: translate(1.5px, 1.5px) rotate(1.5deg);
+ }
+
+ 8% {
+ transform: translate(2.5px, 1.5px) rotate(.5deg);
+ }
+
+ 10% {
+ transform: translate(.5px, 2.5px) rotate(.5deg);
+ }
+
+ 12% {
+ transform: translate(1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 14% {
+ transform: translate(.5px, .5px) rotate(.5deg);
+ }
+
+ 16% {
+ transform: translate(-1.5px, -.5px) rotate(1.5deg);
+ }
+
+ 18% {
+ transform: translate(.5px, .5px) rotate(1.5deg);
+ }
+
+ 20% {
+ transform: translate(2.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 22% {
+ transform: translate(.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 24% {
+ transform: translate(-1.5px, 1.5px) rotate(-.5deg);
+ }
+
+ 26% {
+ transform: translate(1.5px, .5px) rotate(1.5deg);
+ }
+
+ 28% {
+ transform: translate(-.5px, -.5px) rotate(-.5deg);
+ }
+
+ 30% {
+ transform: translate(1.5px, -.5px) rotate(-.5deg);
+ }
+
+ 32% {
+ transform: translate(2.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 34% {
+ transform: translate(2.5px, 2.5px) rotate(-.5deg);
+ }
+
+ 36% {
+ transform: translate(.5px, -1.5px) rotate(.5deg);
+ }
+
+ 38% {
+ transform: translate(2.5px, -.5px) rotate(-.5deg);
+ }
+
+ 40% {
+ transform: translate(-.5px, 2.5px) rotate(.5deg);
+ }
+
+ 42% {
+ transform: translate(-1.5px, 2.5px) rotate(.5deg);
+ }
+
+ 44% {
+ transform: translate(-1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 46% {
+ transform: translate(1.5px, -.5px) rotate(-.5deg);
+ }
+
+ 48% {
+ transform: translate(2.5px, -.5px) rotate(.5deg);
+ }
+
+ 50% {
+ transform: translate(-1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 52% {
+ transform: translate(-.5px, 1.5px) rotate(.5deg);
+ }
+
+ 54% {
+ transform: translate(-1.5px, 1.5px) rotate(.5deg);
+ }
+
+ 56% {
+ transform: translate(.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 58% {
+ transform: translate(2.5px, 2.5px) rotate(.5deg);
+ }
+
+ 60% {
+ transform: translate(2.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 62% {
+ transform: translate(-1.5px, .5px) rotate(1.5deg);
+ }
+
+ 64% {
+ transform: translate(-1.5px, 1.5px) rotate(1.5deg);
+ }
+
+ 66% {
+ transform: translate(.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 68% {
+ transform: translate(2.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 70% {
+ transform: translate(2.5px, 2.5px) rotate(.5deg);
+ }
+
+ 72% {
+ transform: translate(-.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 74% {
+ transform: translate(-1.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 76% {
+ transform: translate(-1.5px, 2.5px) rotate(1.5deg);
+ }
+
+ 78% {
+ transform: translate(-1.5px, 2.5px) rotate(.5deg);
+ }
+
+ 80% {
+ transform: translate(-1.5px, .5px) rotate(-.5deg);
+ }
+
+ 82% {
+ transform: translate(-1.5px, .5px) rotate(-.5deg);
+ }
+
+ 84% {
+ transform: translate(-.5px, .5px) rotate(1.5deg);
+ }
+
+ 86% {
+ transform: translate(2.5px, 1.5px) rotate(.5deg);
+ }
+
+ 88% {
+ transform: translate(-1.5px, .5px) rotate(1.5deg);
+ }
+
+ 90% {
+ transform: translate(-1.5px, -.5px) rotate(-.5deg);
+ }
+
+ 92% {
+ transform: translate(-1.5px, -1.5px) rotate(1.5deg);
+ }
+
+ 94% {
+ transform: translate(.5px, .5px) rotate(-.5deg);
+ }
+
+ 96% {
+ transform: translate(2.5px, -.5px) rotate(-.5deg);
+ }
+
+ 98% {
+ transform: translate(-1.5px, -1.5px) rotate(-.5deg);
+ }
+
+ 0%, 100% {
+ transform: translate(0, 0) rotate(0);
+ }
+}