Initial commit
@@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 419 KiB |
|
After Width: | Height: | Size: 177 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,126 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>原神主题网站 | Genshin Theme</title>
|
||||||
|
|
||||||
|
<!-- 样式文件 | CSS file -->
|
||||||
|
<link rel="stylesheet" href="indexstyle.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!--日志弹窗-->
|
||||||
|
<div id="changelog-modal" class="changelog-modal">
|
||||||
|
<div class="changelog-content">
|
||||||
|
<h2 id="logtitle">(由JS控制)</h2>
|
||||||
|
<p id="groupdescribe">-----------------------------讨论群 856992001-----------------------------<br></p>
|
||||||
|
<p id="logtext">(由JS控制)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--功能区-->
|
||||||
|
<div class="buttons-container">
|
||||||
|
<!--更新日志按钮-->
|
||||||
|
<div id="changelog-button" class="changelog-button">
|
||||||
|
<i class="changelog-icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--网站主体-->
|
||||||
|
<div class="shell" id="shell">
|
||||||
|
<div class="header">
|
||||||
|
<h2 class="title">原神 · 印象</h2>
|
||||||
|
<h3 class="subtitle">Genshin | Character image</h3>
|
||||||
|
</div>
|
||||||
|
<div class="timeline">
|
||||||
|
<!-- 可莉 -->
|
||||||
|
<div class="item" data-text="2023.06.12 上线">
|
||||||
|
<div class="content">
|
||||||
|
<a href="./webs/KleeWeb/klee.html" target="_blank"><img src="./img/01.jpg" alt="" class="img"></a>
|
||||||
|
<h2 class="content-title">Klee</h2>
|
||||||
|
<p class="content-desc">
|
||||||
|
“那边那个小红帽是谁?” <br />
|
||||||
|
“一个经常闯祸的火花骑士。”
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 纳西妲 -->
|
||||||
|
<div class="item" data-text="2023.06.20 上线">
|
||||||
|
<div class="content">
|
||||||
|
<a href="./webs/NahidaWeb/nahida.html" target="_blank"><img src="./img/02.jpeg" alt="" class="img"></a>
|
||||||
|
<h2 class="content-title">Nahida</h2>
|
||||||
|
<p class="content-desc">
|
||||||
|
“净善宫里藏着什么?” <br />
|
||||||
|
“藏着美好与悲伤。”
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 绮良良 -->
|
||||||
|
<div class="item" data-text="2023.06.24 上线">
|
||||||
|
<div class="content">
|
||||||
|
<a href="./webs/KiraraWeb/kirara.html" target="_blank"><img src="./img/03.jpg" alt="" class="img"></a>
|
||||||
|
<h2 class="content-title">Kirara</h2>
|
||||||
|
<p class="content-desc">
|
||||||
|
“送快递是什么感觉?” <br />
|
||||||
|
“在超时与未超时之间反复徘徊......”
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 多莉 -->
|
||||||
|
<div class="item" data-text="2023.06.27 上线">
|
||||||
|
<div class="content">
|
||||||
|
<a href="./webs/DoriWeb/dori.html" target="_blank"><img src="./img/04.jpg" alt="" class="img"></a>
|
||||||
|
<h2 class="content-title">Dori</h2>
|
||||||
|
<p class="content-desc">
|
||||||
|
“什么是双赢?” <br />
|
||||||
|
“多莉会告诉你答案。”
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 芭芭拉 -->
|
||||||
|
<div class="item" data-text="2023.06.27 上线">
|
||||||
|
<div class="content">
|
||||||
|
<a href="./webs/BabaraWeb/babara.html" target="_blank"><img src="./img/05.jpg" alt="" class="img"></a>
|
||||||
|
<h2 class="content-title">Babara</h2>
|
||||||
|
<p class="content-desc">
|
||||||
|
“人们总是会对任何美好报以憧憬, <br />
|
||||||
|
“天籁之声也不例外。”
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 敬请期待 -->
|
||||||
|
<div class="item" data-text="未来会是谁呢……?">
|
||||||
|
<div class="content">
|
||||||
|
<a href="#"><img src="./img/last.jpg" alt="" class="img"></a>
|
||||||
|
<h2 class="content-title">?</h2>
|
||||||
|
<p class="content-desc">
|
||||||
|
讨论群: 856992001<br />
|
||||||
|
将你的创造展示于群星 。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 引入 JS文件 -->
|
||||||
|
<script src="./jquery.min.js"></script>
|
||||||
|
<script src="./indexscript.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
// 禁用右键菜单
|
||||||
|
document.addEventListener('contextmenu', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===============================网页主体==========================
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
$.fn.timeline = function () {
|
||||||
|
var selectors = {
|
||||||
|
id: $(this),
|
||||||
|
item: $(this).find(".item"),
|
||||||
|
activeClass: "item--active",
|
||||||
|
img: ".img"
|
||||||
|
};
|
||||||
|
// 将第一个时间轴项目激活,并设置时间轴背景图片为第一个项目的图片
|
||||||
|
selectors.item.eq(0).addClass(selectors.activeClass);
|
||||||
|
selectors.id.css(
|
||||||
|
"background-image",
|
||||||
|
"url(" +
|
||||||
|
selectors.item.first()
|
||||||
|
.find(selectors.img)
|
||||||
|
.attr("src") +
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
// 获取时间轴项目的总数
|
||||||
|
var itemLength = selectors.item.length;
|
||||||
|
// 当页面滚动时,触发滚动事件
|
||||||
|
$(window).scroll(function () {
|
||||||
|
var max, min;
|
||||||
|
// 获取页面滚动的距离
|
||||||
|
var pos = $(this).scrollTop();
|
||||||
|
selectors.item.each(function (i) {
|
||||||
|
// 获取当前时间轴项目的最小和最大高度
|
||||||
|
min = $(this).offset().top; //min:元素距离文档顶部的距离
|
||||||
|
max = $(this).height() + $(this).offset().top; //max:元素距离文档顶部的距离 + 元素的高度
|
||||||
|
|
||||||
|
var that = $(this);
|
||||||
|
// 如果滚动到最后一个项目,并且超过了当前项目高度的一半,
|
||||||
|
// 则将最后一个项目设置为激活状态,并设置背景图片为最后一个项目的图片
|
||||||
|
if (i == itemLength - 2 && pos > min + $(this).height() / 2) {
|
||||||
|
selectors.item.removeClass(selectors.activeClass);
|
||||||
|
selectors.id.css(
|
||||||
|
"background-image",
|
||||||
|
"url(" +
|
||||||
|
selectors.item.last()
|
||||||
|
.find(selectors.img)
|
||||||
|
.attr("src") +
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
selectors.item.last().addClass(selectors.activeClass);
|
||||||
|
}
|
||||||
|
// 如果当前滚动位置在当前项目的最小和最大高度之间,
|
||||||
|
// 则将当前项目设置为激活状态,并设置背景图片为当前项目的图片
|
||||||
|
else if (pos <= max && pos >= min - 220) {
|
||||||
|
selectors.id.css(
|
||||||
|
"background-image",
|
||||||
|
"url(" +
|
||||||
|
$(this)
|
||||||
|
.find(selectors.img)
|
||||||
|
.attr("src") +
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
selectors.item.removeClass(selectors.activeClass);
|
||||||
|
$(this).addClass(selectors.activeClass);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
})(jQuery)
|
||||||
|
/*
|
||||||
|
最后,我们调用 timeline 插件并传入时间轴的 ID 作为参数。
|
||||||
|
这将启用时间轴插件并为该时间轴绑定滚动事件。
|
||||||
|
*/
|
||||||
|
$("#shell").timeline();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================================================================【日志功能】==================================================
|
||||||
|
const changelogButton = document.getElementById('changelog-button'); //日志功能点击按钮
|
||||||
|
const changelogModal = document.getElementById('changelog-modal'); //
|
||||||
|
|
||||||
|
changelogButton.addEventListener('click', toggleChangelogModal);
|
||||||
|
|
||||||
|
function toggleChangelogModal() {
|
||||||
|
changelogModal.style.display = 'block';
|
||||||
|
changelogModal.classList.toggle('fade-in');
|
||||||
|
changelogModal.classList.toggle('fade-out');
|
||||||
|
}
|
||||||
|
|
||||||
|
var isFirstClick = true;
|
||||||
|
document.addEventListener('click', function (event) {
|
||||||
|
//第一次弹窗默认弹窗,点击哪里都能关闭弹窗
|
||||||
|
if (isFirstClick == true) {
|
||||||
|
//移除弹窗的渐入动画、增加淡出动画
|
||||||
|
changelogModal.classList.remove('fade-in');
|
||||||
|
changelogModal.classList.add('fade-out');
|
||||||
|
//淡出动画的CSS持续时间为0.5s,因此这0.5s内,弹窗的display="none"需要延迟0.5s执行
|
||||||
|
setTimeout(function () {
|
||||||
|
changelogModal.style.display = 'none';
|
||||||
|
}, 500 // 0.5秒延时,和CSS代码中的 fade-out 持续时间一致
|
||||||
|
);
|
||||||
|
isFirstClick = false;
|
||||||
|
}
|
||||||
|
//第二次点击弹窗之后,只能点击弹窗外的地方才能关闭
|
||||||
|
else if (!changelogModal.contains(event.target) && !changelogButton.contains(event.target)) {
|
||||||
|
//逻辑同上
|
||||||
|
changelogModal.classList.remove('fade-in');
|
||||||
|
changelogModal.classList.add('fade-out');
|
||||||
|
setTimeout(function () {
|
||||||
|
changelogModal.style.display = 'none';
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//更新日志设置(模板字符串)
|
||||||
|
const logTitle = document.getElementById("logtitle");
|
||||||
|
const logText = document.getElementById("logtext");
|
||||||
|
const title = "6.27 V3.0网站更新日志";
|
||||||
|
const content = `
|
||||||
|
<br>
|
||||||
|
1.【多莉】还有【芭芭拉】的主题页面登场!全球计数器同步上线!~<br>
|
||||||
|
2.【纳西妲】新增中文语音 “呐呐”,欢迎体验<br>
|
||||||
|
3. 优化了其它逻辑<br>
|
||||||
|
`;
|
||||||
|
|
||||||
|
logTitle.innerHTML = `<h2>${title}</h2>`;
|
||||||
|
logText.innerHTML = `<p>${content}</p>`;
|
||||||
@@ -0,0 +1,354 @@
|
|||||||
|
/* ==========================网页主体========================= */
|
||||||
|
|
||||||
|
* {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
/* Safari 和 Chrome */
|
||||||
|
-moz-user-select: none;
|
||||||
|
/* Firefox */
|
||||||
|
-ms-user-select: none;
|
||||||
|
/* Internet Explorer/Edge */
|
||||||
|
user-select: none;
|
||||||
|
/* 标准语法 */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.shell {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
padding: 80px 0;
|
||||||
|
transition: 0.3s ease 0s;
|
||||||
|
background-attachment: fixed;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shell:before {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(99, 99, 99, 0.8);
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 80px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 46px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline {
|
||||||
|
display: flex;
|
||||||
|
margin: 0 auto;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 700px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-title {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 66px;
|
||||||
|
margin: -10px 0 0 0;
|
||||||
|
transition: 0.4s;
|
||||||
|
padding: 0 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-desc {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline:before {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
width: 2px;
|
||||||
|
height: 100%;
|
||||||
|
margin-left: -1px;
|
||||||
|
content: "";
|
||||||
|
background: rgba(255, 255, 255, 0.07);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 40px 0;
|
||||||
|
opacity: 0.3;
|
||||||
|
filter: blur(2px);
|
||||||
|
transition: 0.5s;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: calc(50% - 40px);
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
transform: translateY(-80px);
|
||||||
|
/* 元素之间的距离 */
|
||||||
|
margin-bottom: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 伪元素样式 */
|
||||||
|
.item:before {
|
||||||
|
content: attr(data-text);
|
||||||
|
letter-spacing: 3px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
font-size: 13px;
|
||||||
|
border-left: 2px solid rgba(255, 255, 255, 0.5);
|
||||||
|
top: 70%;
|
||||||
|
margin-top: -5px;
|
||||||
|
padding-left: 15px;
|
||||||
|
opacity: 0;
|
||||||
|
right: calc(-100% - 56px);
|
||||||
|
font: 900 20px '';
|
||||||
|
letter-spacing: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:nth-child(even) {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 改变伪元素的产生位置,对称产生 */
|
||||||
|
.item:nth-child(even):before {
|
||||||
|
right: auto;
|
||||||
|
text-align: right;
|
||||||
|
left: calc(-100% - 56px);
|
||||||
|
padding-left: 0;
|
||||||
|
border-left: none;
|
||||||
|
border-right: 2px solid rgba(255, 255, 255, 0.5);
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动到对应元素的位置 */
|
||||||
|
.item--active {
|
||||||
|
opacity: 1;
|
||||||
|
/* transform: translateY(0); */
|
||||||
|
filter: blur(0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 激活状态鼠标悬浮变化 */
|
||||||
|
.item--active:hover {
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图片旁边的伪元素文字 */
|
||||||
|
.item--active:before {
|
||||||
|
top: 70%;
|
||||||
|
transition: 0.3s all 0.2s;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item--active .content-title {
|
||||||
|
margin: -50px 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
max-width: 100%;
|
||||||
|
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 5px;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding: 95px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a {
|
||||||
|
color: #999;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 767px) {
|
||||||
|
.item {
|
||||||
|
align-self: baseline !important;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 30px 150px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:before {
|
||||||
|
left: 10px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
top: 50px;
|
||||||
|
text-align: center !important;
|
||||||
|
width: 60px;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:last-child {
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 767px) {
|
||||||
|
.timeline:before {
|
||||||
|
left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ==================日志============ */
|
||||||
|
|
||||||
|
/* 功能区大盒子 */
|
||||||
|
.buttons-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 8888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 更新日志按钮 */
|
||||||
|
.changelog-button {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
|
border-radius: 5%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-button:hover {
|
||||||
|
background-color: #e5e2e2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-image: url("./img/log_icon.png");
|
||||||
|
/* 替换为你的更新日志图标的路径 */
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 日志弹窗样式 */
|
||||||
|
.changelog-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 60%;
|
||||||
|
height: 70%;
|
||||||
|
background-color: rgba(8, 8, 8, 0.9);
|
||||||
|
/* 淡红色背景 */
|
||||||
|
z-index: 9999;
|
||||||
|
overflow: auto;
|
||||||
|
border-radius: 1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-content #logtitle {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-content #groupdescribe {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgb(188, 230, 96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-content #logtext {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.changelog-content {
|
||||||
|
/* 公告文字颜色 */
|
||||||
|
color: rgb(188, 230, 96);
|
||||||
|
/* 白色文字 */
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in {
|
||||||
|
animation: fade-in 0.5s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-out {
|
||||||
|
animation: fade-out 0.5s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-out {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
|
||||||
|
/* 小屏幕设备的日志弹窗样式 */
|
||||||
|
#changelog-modal {
|
||||||
|
width: 90%;
|
||||||
|
height: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-content #logtitle {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 15px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-content #groupdescribe {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgb(230, 216, 29)
|
||||||
|
}
|
||||||
|
|
||||||
|
.changelog-content #logtext {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
1.新增语音:
|
||||||
|
①中文语音:“嗷呜” 、“略略略”、“呜..”
|
||||||
|
②日语语音:“哒咩”、“呜nia”、“呜..”
|
||||||
|
③刘照坤老师的可莉彩蛋语音
|
||||||
|
④花玲老师的可莉彩蛋语音
|
||||||
|
|
||||||
|
2.新增功能:永久保存本地的点击数
|
||||||
|
3.添加Windows客户端版本(群文件在群里~)
|
||||||
|
4.新增两个语音模式选项 “仅哒哒哒”、“彩蛋”
|
||||||
|
5.优化了语言选择栏的文本显示逻辑
|
||||||
|
6.减小了移动端可莉图像的大小和移动速度
|
||||||
|
7.新增“版本日志”功能,点击左上角就可以查看本网站的更新日志了!
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
1.「可莉哒哒哒」移进了网页的二级入口
|
||||||
|
2. 设置网站首页的目的是为未来编写其它角色的主体网页做准备
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
1.全新角色展示页面 『纳西妲』 上线。目前仅开发了中文语音。从首页第二个角色标签点入即可。
|
||||||
|
2.我们将在不久的将来上线全球计数器功能,目前的功能已经开发完毕,接下来我们还需要进行部署和线上测试,请大家敬请期待
|
||||||
|
3.有更多建议和想法,欢迎加入我们的讨论群一起讨论。
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
1.本次上线了大家最期待的功能【全球计数器】
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
1.新任务【绮良良】的主页登场!绮良良的全球点击计数器也同步上线!
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
1.【多莉】还有【芭芭拉】的主题页面登场!全球计数器同步上线!~
|
||||||
|
2.【纳西妲】新增中文语音 “呐呐”,欢迎体验
|
||||||
|
3. 优化了其它逻辑
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# 原神角色の主题网站……持续更新~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
本网站所参考的源码:[Herta Kuru~](https://github.com/duiqt/herta_kuru) |
|
||||||
|
|
||||||
|
このウェブサイトは、参考元のソースコード:[Herta Kuru~](https://github.com/duiqt/herta_kuru) |
|
||||||
|
|
||||||
|
The source code referenced by this website: [Herta Kuru~](https://github.com/duiqt/herta_kuru)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
感谢 [@Seseren_kr](https://twitter.com/Seseren_kr) 提供的GIF图片 |
|
||||||
|
|
||||||
|
[@Seseren_kr](https://twitter.com/Seseren_kr) さんが提供してくれたGIF画像に感謝します|
|
||||||
|
|
||||||
|
Thanks [@Seseren_kr](https://twitter.com/Seseren_kr) for the gif picture
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
角色版权归米哈游所有 |
|
||||||
|
|
||||||
|
キャラクターの著作権はmiHoYoに帰属します |
|
||||||
|
|
||||||
|
The art the relevant copyright of Genshin Impact belongs to miHoYo/HoYoverse.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title id="doc-title">Babara~</title><!--change-->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||||
|
<link rel="stylesheet" href="./babarastyle.css" type="text/css" /><!--change-->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<script src="https://code.iconify.design/iconify-icon/1.0.2/iconify-icon.min.js"></script>
|
||||||
|
<link href="img/favicon.ico" rel="shortcut icon">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="welcome-page">
|
||||||
|
<h2>Click to Continue</h2>
|
||||||
|
<br />
|
||||||
|
<img src="./img/welcome.gif">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--功能区-->
|
||||||
|
<div class="buttons-container">
|
||||||
|
<!-- 音乐播放按钮-->
|
||||||
|
<div id="volume-control" class="volume-control">
|
||||||
|
<i id="volume-icon" class="volume-icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--主体部分 | Main page-->
|
||||||
|
<main class="wrapper">
|
||||||
|
<div id="wrapper-background-filter"></div>
|
||||||
|
<div id="wrapper-background"></div>
|
||||||
|
<img src="img/background.gif" class="preload" />
|
||||||
|
<div id="content">
|
||||||
|
<div id="title-container">
|
||||||
|
<h1 id="page-title">Welcome to Babara's Page~ </h1>
|
||||||
|
<img id="title-img" alt="img of Babara" class="shake" src="img/favicon.png">
|
||||||
|
</div>
|
||||||
|
<div id="container">
|
||||||
|
<select id="language-selector">
|
||||||
|
<option id="lan1" value="cn" selected>Chinese</option>
|
||||||
|
<option id="lan2" value="ja">Japanese</option>
|
||||||
|
<option id="lan3" value="en">English</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="mode-selector">
|
||||||
|
<option id="mode1">Default</option>
|
||||||
|
<!-- <option id="mode2">Just Dadada</option>
|
||||||
|
<option id="mode3">Easter egg</option> -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<hr id="subtitle-seperator" />
|
||||||
|
<h2 id="page-descriptions">
|
||||||
|
The website for Babara, the shiniest idol in Genshin Impact.
|
||||||
|
</h2>
|
||||||
|
<div id="counter-container">
|
||||||
|
<h3 id="counter-descriptions">Babara has been performed for</h3>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p id="global-counter">0</p>
|
||||||
|
<p id="local-counter">0</p>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<button id="counter-button">
|
||||||
|
Let Babara Performes~!
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div id="grid">
|
||||||
|
<noscript>Your browser does not support JavaScript or JavaScript has been
|
||||||
|
disabled.<br />This website relies on JavaScript, so please enable it
|
||||||
|
or use another browser.</noscript>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- 尾部部分 | Footer -->
|
||||||
|
<div id="footer">
|
||||||
|
<img id="babara-card" loading="lazy" src="" alt="" /> <!--由JS控制src的具体路径-->
|
||||||
|
<div id="footer-text">
|
||||||
|
|
||||||
|
<p id="footer-repository-text">
|
||||||
|
You can check out the Gitee repository here:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<!--这里填写本网站的Github地址-->
|
||||||
|
<a href="https://gitee.com/KleeGitee/Klee" target="_blank">
|
||||||
|
<span class="footer-icon-text"
|
||||||
|
id="footer-repository-text-2">Web_OF_Genshin (Gitee)</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p id="footer-repository-text3">
|
||||||
|
This website is based on the repository source code changes
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<!--source code-->
|
||||||
|
<a href="https://github.com/duiqt/herta_kuru" target="_blank"><iconify-icon icon="mdi:github" id="github-footer-icon"
|
||||||
|
class="footer-icon"></iconify-icon><span class="footer-icon-text"
|
||||||
|
id="footer-repository-text-4">SourceCode's repository</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p id="credits-gif">Babara gif made by</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://twitter.com/Seseren_kr" target="_blank"><iconify-icon icon="mdi:twitter"
|
||||||
|
id="twitter-footer-icon" class="footer-icon"></iconify-icon><span
|
||||||
|
class="footer-icon-text">@Seseren_kr</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="./babarascript.js" async></script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
//加载数据库信息
|
||||||
|
require_once('../config.php');
|
||||||
|
// 创建连接
|
||||||
|
$conn = new mysqli($servername, $username, $password, $dbname);
|
||||||
|
// 连接成功,可以进行数据库操作
|
||||||
|
$sql = "SELECT globalcount FROM ys WHERE name = 'babara'";
|
||||||
|
// 执行查询
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
// 处理 POST 请求
|
||||||
|
//接收前端数据
|
||||||
|
$localcount = $_POST["localcount"];
|
||||||
|
//检查查询结果
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
$globalCount = $row['globalcount'];
|
||||||
|
|
||||||
|
// 将本地计数值加给全局计数
|
||||||
|
$globalCount += $localcount;
|
||||||
|
|
||||||
|
// 更新数据库中的全局计数值
|
||||||
|
$updateSql = "UPDATE ys SET globalcount = $globalCount WHERE name = 'babara';";
|
||||||
|
|
||||||
|
if ($conn->query($updateSql) === TRUE) {
|
||||||
|
// 更新成功
|
||||||
|
echo "更新成功";
|
||||||
|
} else {
|
||||||
|
// 更新失败
|
||||||
|
echo "更新失败: " . $conn->error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有找到全局计数值
|
||||||
|
echo "没有找到全局计数值";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回响应
|
||||||
|
//echo "这是 POST 请求的响应";
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] === "GET") {
|
||||||
|
// 处理 GET 请求
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
// 有数据返回
|
||||||
|
$rows = array();
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$rows[] = $row;
|
||||||
|
}
|
||||||
|
// 将查询结果转换为 JSON 格式发送回前端
|
||||||
|
echo json_encode($rows);
|
||||||
|
} else {
|
||||||
|
// 无数据返回
|
||||||
|
echo "没有数据";
|
||||||
|
}
|
||||||
|
// 返回响应
|
||||||
|
//echo "这是 GET 请求的响应";
|
||||||
|
} else {
|
||||||
|
// 不支持其他请求方法
|
||||||
|
http_response_code(405); // 返回“Method Not Allowed”状态码
|
||||||
|
echo "不支持的请求方法";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -0,0 +1,613 @@
|
|||||||
|
|
||||||
|
// 禁用右键菜单
|
||||||
|
document.addEventListener('contextmenu', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//图片摇摆
|
||||||
|
const img = document.getElementById('title-img');
|
||||||
|
// 定期执行动画
|
||||||
|
setInterval(() => {
|
||||||
|
// 添加 CSS 类来触发动画
|
||||||
|
img.classList.add('shake');
|
||||||
|
|
||||||
|
// 设置一个定时器,在一段时间后移除 CSS 类停止动画
|
||||||
|
setTimeout(() => {
|
||||||
|
img.classList.remove('shake');
|
||||||
|
}, 2500); // 动画持续时间为 2.5 秒
|
||||||
|
}, 5000); // 每隔 5 秒执行一次动画
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================================【BGM】=============================================================
|
||||||
|
// 欢迎页面淡出控制,音乐控制
|
||||||
|
var isMusicPlayed = false; // 记录音乐是否已经播放
|
||||||
|
var isWelcomed = false; //记录您是否已离开欢迎页面
|
||||||
|
var BGM = new Audio("./music/Babara's song.mp3"); //BGM
|
||||||
|
|
||||||
|
document.addEventListener("click", function (event) {
|
||||||
|
if (!isWelcomed) {
|
||||||
|
removeWelcomePageAndPlayMusic();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function removeWelcomePageAndPlayMusic() {
|
||||||
|
var welcomePage = document.getElementById("welcome-page");
|
||||||
|
welcomePage.style.opacity = 0;
|
||||||
|
setTimeout(function () {
|
||||||
|
welcomePage.style.display = "none";
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
if (!isMusicPlayed && !isWelcomed) {
|
||||||
|
playBackgroundMusic();
|
||||||
|
isMusicPlayed = true;
|
||||||
|
isWelcomed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function playBackgroundMusic() {
|
||||||
|
BGM.loop = true; // 循环播放
|
||||||
|
BGM.play(); // 播放BGM
|
||||||
|
BGM.volume = 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//音乐播放控制
|
||||||
|
var volumeControl = document.getElementById("volume-control");
|
||||||
|
var volumeIcon = document.getElementById("volume-icon");
|
||||||
|
|
||||||
|
|
||||||
|
//音乐暂停和播放逻辑
|
||||||
|
volumeControl.addEventListener("click", function () {
|
||||||
|
if (!isMusicPlayed) {
|
||||||
|
// Play music
|
||||||
|
BGM.play();
|
||||||
|
volumeIcon.style.animationPlayState = "running";
|
||||||
|
isMusicPlayed = true;
|
||||||
|
} else {
|
||||||
|
// Pause music
|
||||||
|
BGM.pause();
|
||||||
|
volumeIcon.style.animationPlayState = "paused";
|
||||||
|
isMusicPlayed = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================【多语言支持】============================================
|
||||||
|
|
||||||
|
|
||||||
|
var audioList = []; // 角色音频
|
||||||
|
let firstSquish = true; //第一次点击
|
||||||
|
|
||||||
|
//多语言支持
|
||||||
|
|
||||||
|
//语言属性数组
|
||||||
|
const LANGUAGES = {
|
||||||
|
//默认
|
||||||
|
"_": { fallbackLanguage: "cn" },
|
||||||
|
|
||||||
|
//中文语音、文本、海报
|
||||||
|
"cn": {
|
||||||
|
audioList: [
|
||||||
|
//0-3:默认模式 mode1
|
||||||
|
"audio/CN_voice/芭芭拉冲呀.mp3",
|
||||||
|
"audio/CN_voice/哒哒哒.mp3",
|
||||||
|
"audio/CN_voice/打起精神来哟.mp3",
|
||||||
|
"audio/CN_voice/哼哼哼哼哼.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "芭芭拉闪耀登场~",
|
||||||
|
"doc-title": "Kirakira~",
|
||||||
|
"page-descriptions": "给芭芭拉写的小网站,对,就是那个原神中最闪耀的偶像!",
|
||||||
|
"counter-descriptions": "芭芭拉已经演唱了~",
|
||||||
|
"counter-button": ["演奏~", "哒~哒哒哒哒~哒~哒!"],
|
||||||
|
"credits-gif": "鸣谢:Seseren_kr提供的芭芭拉GIF图片",
|
||||||
|
"footer-repository-text": "本网站的Gitee仓库在这儿:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "鸣谢:duiqt提供的本网站基础源代码",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_cn.jpg"
|
||||||
|
},
|
||||||
|
|
||||||
|
//日文语音、文本、海报
|
||||||
|
"ja": {
|
||||||
|
audioList: [
|
||||||
|
//0-3:默认模式 mode1
|
||||||
|
"audio/CN_voice/芭芭拉冲呀.mp3",
|
||||||
|
"audio/CN_voice/哒哒哒.mp3",
|
||||||
|
"audio/CN_voice/打起精神来哟.mp3",
|
||||||
|
"audio/CN_voice/哼哼哼哼哼.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "バーバラキラキラ",
|
||||||
|
"doc-title": "キラキラ",
|
||||||
|
"page-descriptions": "このサイトはバーバラのために作られた、 あの原神の最も輝いているアイドルです",
|
||||||
|
"counter-descriptions": "歌唱回数~",
|
||||||
|
"counter-button": "キラキラー!",
|
||||||
|
"credits-gif": "感謝: Seseren_kr さんが提供してくれたバーバラのGIF画像",
|
||||||
|
"footer-repository-text": "こちらはこのページGitee (Mainland China) リポジトリ:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "感謝:duiqt さんが提供してくれたこのウェブサイトの基礎ソースコード",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_jp.jpg"
|
||||||
|
},
|
||||||
|
//英文语音、文本、海报
|
||||||
|
"en": {
|
||||||
|
audioList: [
|
||||||
|
//0-3:默认模式 mode1
|
||||||
|
"audio/CN_voice/芭芭拉冲呀.mp3",
|
||||||
|
"audio/CN_voice/哒哒哒.mp3",
|
||||||
|
"audio/CN_voice/打起精神来哟.mp3",
|
||||||
|
"audio/CN_voice/哼哼哼哼哼.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "Welcome to Babara kirakira~",
|
||||||
|
"doc-title": "Kirakira~",
|
||||||
|
"page-descriptions": "The website for Babara, the shiniest idol in Genshin Impact",
|
||||||
|
"counter-descriptions": "The Babara~ has been performed for",
|
||||||
|
"counter-button": "Kirakira~",
|
||||||
|
"credits-gif": "Acknowledgment: GIF images of Babara provided by Seseren_kr.",
|
||||||
|
"footer-repository-text": "You can check out the Gitee repository (Mainland China) here:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "Special thanks to duiqt for providing the source code for this website.",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_en.jpg"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//设置语言选择器的文本语言
|
||||||
|
function refreshLanguageSelector(selectedLanguage) {
|
||||||
|
switch (selectedLanguage) {
|
||||||
|
case "cn":
|
||||||
|
document.getElementById("lan1").innerHTML = "🌏中文";
|
||||||
|
document.getElementById("lan2").innerHTML = "日文";
|
||||||
|
document.getElementById("lan3").innerHTML = "英文";
|
||||||
|
break;
|
||||||
|
case "ja":
|
||||||
|
document.getElementById("lan1").innerHTML = "中国語";
|
||||||
|
document.getElementById("lan2").innerHTML = "🌏日本語";
|
||||||
|
document.getElementById("lan3").innerHTML = "英語";
|
||||||
|
break;
|
||||||
|
case "en":
|
||||||
|
document.getElementById("lan1").innerHTML = "Chinese";
|
||||||
|
document.getElementById("lan2").innerHTML = "Japanese";
|
||||||
|
document.getElementById("lan3").innerHTML = "🌏English";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置模式选择器的文本语言
|
||||||
|
function refreshModeSelector(selectedLanguage) {
|
||||||
|
switch (selectedLanguage) {
|
||||||
|
case "cn":
|
||||||
|
document.getElementById("mode1").innerHTML = "默认模式";
|
||||||
|
// document.getElementById("mode2").innerHTML = "只要哒哒哒";
|
||||||
|
// document.getElementById("mode3").innerHTML = "隐藏彩蛋";
|
||||||
|
break;
|
||||||
|
case "ja":
|
||||||
|
document.getElementById("mode1").innerHTML = "デフォルトモード";
|
||||||
|
// document.getElementById("mode2").innerHTML = "ダダダだけ";
|
||||||
|
// document.getElementById("mode3").innerHTML = "ひみつ";
|
||||||
|
break;
|
||||||
|
case "en":
|
||||||
|
document.getElementById("mode1").innerHTML = "DefaultMode";
|
||||||
|
// document.getElementById("mode2").innerHTML = "Just Dadada";
|
||||||
|
// document.getElementById("mode3").innerHTML = "Easter egg";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//获取默认语言并赋值给语言选择框
|
||||||
|
var current_language = localStorage.getItem("lang") || "cn";
|
||||||
|
if (current_language != "cn") {
|
||||||
|
document.getElementById("language-selector").value = current_language;
|
||||||
|
};
|
||||||
|
|
||||||
|
//通过获取当前语言和对应的文本数组,遍历文本数组中的每个键值对。如果文本值是一个数组,就从数组中随机选择一个元素作为新的文本内容,并将其更新到对应的 HTML 元素中
|
||||||
|
function randomChoice(myArr) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * myArr.length);
|
||||||
|
const randomItem = myArr[randomIndex];
|
||||||
|
return randomItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
//核心函数!动态刷新动态文本内容(将新的DOM值渲染到前端)
|
||||||
|
function refreshDynamicTexts() {
|
||||||
|
let curLang = LANGUAGES[current_language];
|
||||||
|
let localTexts = curLang.texts;
|
||||||
|
Object.entries(localTexts).forEach(([textId, value]) => {
|
||||||
|
if (value instanceof Array)
|
||||||
|
if (document.getElementById(textId) != undefined)
|
||||||
|
document.getElementById(textId).innerHTML = randomChoice(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//定义函数:根据当前语言,渲染页面
|
||||||
|
function multiLangMutation() {
|
||||||
|
let curLang = LANGUAGES[current_language]; //获取当前的网站语言
|
||||||
|
let localTexts = curLang.texts; //获取当前语言的文本数组
|
||||||
|
Object.entries(localTexts).forEach(([textId, value]) => { //将各个DOM元素的值变为文本值
|
||||||
|
if (!(value instanceof Array))
|
||||||
|
if (document.getElementById(textId) != undefined)
|
||||||
|
document.getElementById(textId).innerHTML = value;
|
||||||
|
});
|
||||||
|
refreshDynamicTexts() //刷新动态文本内容(将新的DOM值渲染到前端)
|
||||||
|
document.getElementById("babara-card").src = curLang.cardImage; //动态获取klee-card在当前语言文本环境下的Dom元素并更新
|
||||||
|
|
||||||
|
var selectedLanguage = document.getElementById("language-selector").value;
|
||||||
|
refreshLanguageSelector(selectedLanguage) //更新语言选择器的文本语言
|
||||||
|
refreshModeSelector(selectedLanguage) //更新模式选择器的文本语言
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
curLang 变量获取了当前选择的网站语言对应的语言对象(假设为 LANGUAGES 全局对象中的一个属性)。
|
||||||
|
localTexts 变量获取了当前语言对象中的文本数组。
|
||||||
|
使用 Object.entries() 方法遍历 localTexts 中的键值对。
|
||||||
|
对于每一个键值对,解构赋值为 [textId, value],其中 textId 是 DOM 元素的 ID,value 是对应的文本值。
|
||||||
|
首先检查 value 是否为数组,如果不是数组,表示是单个文本值(例如字符串)。
|
||||||
|
检查当前网页是否存在具有对应 textId 的 DOM 元素(通过 document.getElementById(textId) 来判断)。
|
||||||
|
如果存在对应的 DOM 元素,则将其内部的 HTML 内容更新为 value。
|
||||||
|
这样就实现了根据当前语言选择动态更新网页中的文本内容。
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
multiLangMutation() //初始化网站语言
|
||||||
|
|
||||||
|
//通过这段代码,当语言选择器的值发生变化时,会根据选择的语言重新渲染页面的文本内容和动态图片,实现动态调整网站语言的功能。
|
||||||
|
document.getElementById("language-selector").addEventListener("change", (ev) => {
|
||||||
|
current_language = ev.target.value;
|
||||||
|
localStorage.setItem("lang", ev.target.value);
|
||||||
|
multiLangMutation();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======================================================================【按钮点击、计数器】============================================
|
||||||
|
|
||||||
|
// 初始化计数器
|
||||||
|
//本地计数器
|
||||||
|
const localCounter = document.querySelector('#local-counter'); //获取展示本地点击数的DOM元素
|
||||||
|
let localCount = localStorage.getItem('count-local-babara') || 0; //获取本地点击数的值
|
||||||
|
localCounter.textContent = localCount.toLocaleString('en-US'); //使用美式英语的格式进行格式化。这样可以确保数值以适当的方式显示,例如添加千位分隔符
|
||||||
|
|
||||||
|
|
||||||
|
let prevTime = 0;
|
||||||
|
|
||||||
|
//获取时间戳
|
||||||
|
const getTimestamp = () => Date.parse(new Date());
|
||||||
|
|
||||||
|
//点击按钮事件
|
||||||
|
const counterButton = document.querySelector('#counter-button');
|
||||||
|
counterButton.addEventListener('click', (e) => {
|
||||||
|
prevTime = getTimestamp(); //当前时间
|
||||||
|
localCount++;
|
||||||
|
localStorage.setItem('count-local-babara', localCount); //缓存localCount到本地
|
||||||
|
|
||||||
|
localCounter.textContent = localCount.toLocaleString('en-US');
|
||||||
|
|
||||||
|
triggerRipple(e); //按钮的水波纹效果
|
||||||
|
playKirakira(); //播放可莉语音
|
||||||
|
animateBabara(); //播放可莉动画
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================================【资源缓存】========================================================
|
||||||
|
var cachedObjects = {};
|
||||||
|
function tryCachedObject(origUrl) {
|
||||||
|
// 检查对象是否已经被缓存
|
||||||
|
if (cachedObjects[origUrl]) {
|
||||||
|
return cachedObjects[origUrl];
|
||||||
|
} else {
|
||||||
|
// 开始缓存
|
||||||
|
fetch(origUrl)
|
||||||
|
.then((response) => response.blob())
|
||||||
|
.then((blob) => {
|
||||||
|
// 为对象创建一个blob URL
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
// 通过在cachedObjects对象中存储blob URL来获取缓存的对象
|
||||||
|
cachedObjects[origUrl] = blobUrl;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(`Error caching object from ${origUrl}: ${error}`);
|
||||||
|
});
|
||||||
|
return origUrl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//缓存所有资源
|
||||||
|
function cacheAllResources() {
|
||||||
|
// 缓存图片资源
|
||||||
|
for (let i = 1; i < 7; i++) {
|
||||||
|
const imageUrl = `img/animation/${i}.gif`;
|
||||||
|
tryCachedObject(imageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存中文音频资源(含通用语音资源)
|
||||||
|
const cnAudioList = LANGUAGES.cn.audioList;
|
||||||
|
cnAudioList.forEach((audioUrl) => {
|
||||||
|
tryCachedObject(audioUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 缓存日文音频资源(含通用语音资源)
|
||||||
|
const jaAudioList = LANGUAGES.ja.audioList;
|
||||||
|
jaAudioList.forEach((audioUrl) => {
|
||||||
|
tryCachedObject(audioUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
//只需要执行一次该功能
|
||||||
|
firstLoadClick = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当页面加载完成后触发缓存资源
|
||||||
|
// var firstLoadClick = true;
|
||||||
|
// window.addEventListener('click', cacheAllResources);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================【按钮点击后的动画、音频】================================================
|
||||||
|
|
||||||
|
//返回当前语言的音频数组
|
||||||
|
function getLocalAudioList() {
|
||||||
|
return LANGUAGES[current_language].audioList;
|
||||||
|
};
|
||||||
|
//从音频数组中获取一个随机的音频URL(传入一个当前模式。curMode==mode1 默认模式,cueMode==mode3)
|
||||||
|
function getRandomAudioUrl(curMode) {
|
||||||
|
var localAudioList = getLocalAudioList()
|
||||||
|
|
||||||
|
//根据模式产生符合模式的音频下标
|
||||||
|
if (curMode == "mode1") {
|
||||||
|
randomIndex = Math.floor(Math.random() * 4); //默认语音的文件是:文件下标0-3.这儿的数字就写4.
|
||||||
|
}
|
||||||
|
// if (curMode == "mode3") {
|
||||||
|
// randomIndex = Math.floor(Math.random() * 17); //文件下标0-16.这儿的数字就写14. 【这儿写彩蛋对应的audioList下标】
|
||||||
|
// }
|
||||||
|
|
||||||
|
const randomItem = localAudioList[randomIndex];
|
||||||
|
return randomItem;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//播放音频
|
||||||
|
var isFirstVoice = true;
|
||||||
|
function playKirakira() {
|
||||||
|
|
||||||
|
//先获取当前的模式:1-默认;2-只哒哒哒;3-彩蛋
|
||||||
|
const modeSelectElement = document.getElementById("mode-selector");
|
||||||
|
const modeSelectedOption = modeSelectElement.options[modeSelectElement.selectedIndex];
|
||||||
|
const curMode = modeSelectedOption.id;
|
||||||
|
|
||||||
|
//要播放的音频Url
|
||||||
|
let audioUrl;
|
||||||
|
|
||||||
|
//根据当前模式获取符合模式语音的 AudioURL
|
||||||
|
switch (curMode) {
|
||||||
|
//curMode==mode1 默认模式
|
||||||
|
case "mode1": {
|
||||||
|
if (isFirstVoice == true) {//随机获取一个音频的URL,第一个必定是哒哒哒哒哒哒
|
||||||
|
isFirstVoice = false;
|
||||||
|
audioUrl = getLocalAudioList()[1] //First play fixed Dadadadadada
|
||||||
|
} else {
|
||||||
|
audioUrl = getRandomAudioUrl(curMode);
|
||||||
|
}
|
||||||
|
}; break;
|
||||||
|
|
||||||
|
//curMode==mode2 只哒哒哒
|
||||||
|
// case "mode2": {
|
||||||
|
// audioUrl = getLocalAudioList()[1]
|
||||||
|
// }; break;
|
||||||
|
|
||||||
|
//cueMode==mode3 彩蛋
|
||||||
|
// case "mode3": {
|
||||||
|
// if (isFirstVoice == true) {//随机获取一个音频的URL,第一个必定是哒哒哒
|
||||||
|
// isFirstVoice = false;
|
||||||
|
// audioUrl = getLocalAudioList()[1] //First play fixed Dadada
|
||||||
|
// } else {
|
||||||
|
// audioUrl = getRandomAudioUrl(curMode);
|
||||||
|
// }
|
||||||
|
// }; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//根据音频URL从本地获取音频资源。同时将该音频缓存到本地
|
||||||
|
let audio = new Audio(tryCachedObject(audioUrl)); //【缓存貌似可以删除】
|
||||||
|
|
||||||
|
//播放音频后监听音频结束事件,并在音频播放结束时将音频元素从 DOM 中移除
|
||||||
|
audio.play();
|
||||||
|
audio.addEventListener("ended", function () {
|
||||||
|
this.remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function animateBabara() {
|
||||||
|
let id = null;
|
||||||
|
|
||||||
|
const random = Math.floor(Math.random() * 6) + 1; //1-6,GIF
|
||||||
|
const elem = document.createElement("img");
|
||||||
|
elem.src = tryCachedObject(`img/animation/${random}.gif`);
|
||||||
|
|
||||||
|
//下面根据不同的窗口改变可莉动画的样式(响应式)
|
||||||
|
const screenWidth = window.innerWidth;
|
||||||
|
|
||||||
|
if (screenWidth > 768) {
|
||||||
|
elem.style.position = "absolute";
|
||||||
|
elem.style.right = "-500px";
|
||||||
|
elem.style.top = counterButton.getClientRects()[0].bottom + scrollY - 430 + "px"
|
||||||
|
elem.style.zIndex = "-10";
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
|
||||||
|
let pos = -500;
|
||||||
|
const limit = window.innerWidth + 500;
|
||||||
|
clearInterval(id);
|
||||||
|
id = setInterval(() => {
|
||||||
|
if (pos >= limit) {
|
||||||
|
clearInterval(id);
|
||||||
|
elem.remove()
|
||||||
|
} else {
|
||||||
|
pos += 20;
|
||||||
|
elem.style.right = pos + 'px';
|
||||||
|
}
|
||||||
|
}, 12);
|
||||||
|
} else {
|
||||||
|
//移动端,把动画变小、变慢一点
|
||||||
|
elem.style.position = "absolute";
|
||||||
|
elem.style.right = "-500px";
|
||||||
|
elem.style.top = counterButton.getClientRects()[0].bottom + scrollY - 180 + "px"
|
||||||
|
elem.style.zIndex = "-10";
|
||||||
|
elem.style.width = "250px"; // 设置宽度为 200px(让移动端方便观看)
|
||||||
|
elem.style.height = "auto"; // 自动计算高度,保持纵横比
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
|
||||||
|
let pos = -500;
|
||||||
|
const limit = window.innerWidth + 500;
|
||||||
|
clearInterval(id);
|
||||||
|
id = setInterval(() => {
|
||||||
|
if (pos >= limit) {
|
||||||
|
clearInterval(id);
|
||||||
|
elem.remove()
|
||||||
|
} else {
|
||||||
|
pos += 10;
|
||||||
|
elem.style.right = pos + 'px';
|
||||||
|
}
|
||||||
|
}, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//点击 counter-button 元素时,会在点击位置出现一个水波纹效果。
|
||||||
|
function triggerRipple(e) {
|
||||||
|
let ripple = document.createElement("span");
|
||||||
|
|
||||||
|
ripple.classList.add("ripple");
|
||||||
|
|
||||||
|
const counter_button = document.getElementById("counter-button");
|
||||||
|
counter_button.appendChild(ripple);
|
||||||
|
|
||||||
|
let x = e.clientX - e.target.offsetLeft;
|
||||||
|
let y = e.clientY - e.target.offsetTop;
|
||||||
|
|
||||||
|
ripple.style.left = `${x}px`;
|
||||||
|
ripple.style.top = `${y}px`;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
ripple.remove();
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================【全球计数器】======================================
|
||||||
|
//算法思路:先前的项目已经实现了永久保存本地计数。接下来要实现统计全球技术:
|
||||||
|
//1.为了节省流量,规定每一分钟自动上传一次【本次点击数】(定义一个区别于 localCount 的新变量 thisTimeCount)
|
||||||
|
//2.发送Ajax,发送 thisTimeCount 服务端返回 globalCount渲染到页面,同时将本地的 thisTimeCount 清零
|
||||||
|
|
||||||
|
|
||||||
|
var thisTimeCounts = 0; //本次轮询Ajax之前的点击数
|
||||||
|
var intervalID = setInterval(updateGlobalCount, 15000);//间隔多久上传一次,单位ms
|
||||||
|
|
||||||
|
//点击一次按钮,thisTimeCount++
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#counter-button').click(function () {
|
||||||
|
thisTimeCounts++ //本次定时轮询Ajax之前的点击数 +1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//上传数据
|
||||||
|
function updateGlobalCount() {
|
||||||
|
$.ajax({
|
||||||
|
url: './babara.php',
|
||||||
|
method: 'POST',
|
||||||
|
async: false,
|
||||||
|
data: { localcount: thisTimeCounts },
|
||||||
|
success: function(response) {
|
||||||
|
// 处理成功响应
|
||||||
|
console.log(response);
|
||||||
|
thisTimeCounts = 0;
|
||||||
|
$('#local-counter').text(localCount);
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
// 处理错误响应
|
||||||
|
console.error("请求失败: " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//首次访问网站的时候,立即获取 globalCounts并刷新 (页面加载完成后立即执行)
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
$.ajax({
|
||||||
|
url: './babara.php',
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
headers: {
|
||||||
|
'ajax-requests': 'true'
|
||||||
|
},
|
||||||
|
/*data: {
|
||||||
|
thistimecountFromFront: thisTimeCounts, //将前端的 thisTimeCount 传给后端,参数名为 thistimecountFromFront
|
||||||
|
},*/
|
||||||
|
success: function (response) {
|
||||||
|
var globalcount = response[0].globalcount;
|
||||||
|
//console.log(response);
|
||||||
|
console.log("初始化成功,globalcountsFromBackend = " + globalcount)
|
||||||
|
var globalCountElement = document.getElementById("global-counter");
|
||||||
|
globalCountElement.textContent = (globalcount).toLocaleString('en-US')
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 定时轮询后端获取 globalCounts
|
||||||
|
setInterval(function () {
|
||||||
|
$.ajax({
|
||||||
|
url: './babara.php',
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
headers: {
|
||||||
|
'ajax-requests': 'true'
|
||||||
|
},
|
||||||
|
//type: 'text',
|
||||||
|
/*data: {
|
||||||
|
thistimecountFromFront: thisTimeCounts, //将前端的 thisTimeCount 传给后端,参数名为 thistimecountFromFront
|
||||||
|
},*/
|
||||||
|
success: function (response) {
|
||||||
|
var globalcount = response[0].globalcount;
|
||||||
|
console.log("前端收到了后端返回的全球计数 = " + globalcount)
|
||||||
|
|
||||||
|
//thisTimeCounts = 0; //将前端本地点击数清零
|
||||||
|
|
||||||
|
var globalCountElement = document.getElementById("global-counter"); //获取全球计数器DOM
|
||||||
|
globalCountElement.textContent = (globalcount).toLocaleString('en-US') //更新全球计数器的值
|
||||||
|
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 5000); // 每5s执行一次
|
||||||
@@ -0,0 +1,479 @@
|
|||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
/* disable double_tap zoom on mobile devices */
|
||||||
|
-ms-touch-action: manipulation;
|
||||||
|
touch-action: manipulation;
|
||||||
|
/* strange margin-right occurs when vw<500px */
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* 底部颜色 */
|
||||||
|
background-color: rgba(233, 233, 233);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", 'Roboto', sans-serif;
|
||||||
|
font-size: 1.5em;
|
||||||
|
/* 顶部文字颜色 */
|
||||||
|
color: #2c5f74;
|
||||||
|
/* 禁用右键和选中 */
|
||||||
|
-webkit-user-select: none;
|
||||||
|
/* Chrome, Safari, Opera */
|
||||||
|
-moz-user-select: none;
|
||||||
|
/* Firefox */
|
||||||
|
-ms-user-select: none;
|
||||||
|
/* Internet Explorer/Edge */
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 欢迎页面 */
|
||||||
|
#welcome-page {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(36, 110, 194, 0.8);
|
||||||
|
color: rgb(255, 254, 254);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcome-page img {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 功能区大盒子 */
|
||||||
|
.buttons-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 8888;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 播放按钮 */
|
||||||
|
.volume-control {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: rgba(241, 243, 244, 0.6);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
/* 按钮和右边按钮间隔20px */
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-control:hover {
|
||||||
|
background-color: #e5e2e2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-image: url("./img/volume_icon.png");
|
||||||
|
background-size: cover;
|
||||||
|
animation: rotate-icon 5s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate-icon {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper-background {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-image: url("img/background.gif");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 50%;
|
||||||
|
background-size: contain;
|
||||||
|
z-index: -30;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper-background-filter {
|
||||||
|
/* 背景颜色 */
|
||||||
|
background-color: rgba(66, 156, 208, 0.9);
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preload {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
margin: 2vh auto;
|
||||||
|
width: 80vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 3em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
/* 分割线 */
|
||||||
|
border-bottom: 6px dashed rgb(227, 226, 223);
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-title {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* logo */
|
||||||
|
#title-img {
|
||||||
|
height: 3.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0% {
|
||||||
|
transform: rotate(-5deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(5deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(-5deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shake {
|
||||||
|
animation: shake 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container select {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language-selector,
|
||||||
|
#mode-selector {
|
||||||
|
width: 200px;
|
||||||
|
height: 40px;
|
||||||
|
/* 选择框颜色 */
|
||||||
|
background-color: #dee6eb;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
text-align-last: center;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 10px;
|
||||||
|
color: rgb(38, 36, 36);
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language-selector:hover,
|
||||||
|
#mode-selector:hover {
|
||||||
|
box-shadow: 0 0 10px #dee6eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#language-selector option {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #dee6eb;
|
||||||
|
color: rgb(118, 114, 114);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-container {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 64px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-container>p {
|
||||||
|
text-shadow: #dee6eb 0 0 10px, #dee6eb 0 0 10px, #dee6eb 0 0 10px, #dee6eb 0 0 10px, #dee6eb 0 0 10px;
|
||||||
|
}
|
||||||
|
/* 全球计数器文字颜色 */
|
||||||
|
#global-counter {
|
||||||
|
color: #2d9cd7;
|
||||||
|
font-size: 4em;
|
||||||
|
text-shadow:
|
||||||
|
-1px -1px 0 black,
|
||||||
|
1px -1px 0 black,
|
||||||
|
-1px 1px 0 black,
|
||||||
|
1px 1px 0 black; /* 描边效果 */
|
||||||
|
}
|
||||||
|
/* 本地计数器文字颜色 */
|
||||||
|
#local-counter {
|
||||||
|
color: #2d9cd7;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button {
|
||||||
|
/* 动画触发按钮颜色 */
|
||||||
|
background-color: #19457e;
|
||||||
|
border: none;
|
||||||
|
border-radius: 16px;
|
||||||
|
color: rgb(203, 213, 222);
|
||||||
|
padding: 16px 32px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 1em;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 6px 7px 40px -4px rgba(43, 42, 42, 0.2);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.1s ease-in-out, scale 0.1s cubic-bezier(0.075, 0.82, 0.165, 1);
|
||||||
|
}
|
||||||
|
/* 动画触发按钮的悬挂颜色 */
|
||||||
|
#counter-button:hover {
|
||||||
|
background-color: #10305d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button:active {
|
||||||
|
scale: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button span {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff50;
|
||||||
|
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
margin-top: -50px;
|
||||||
|
margin-left: -50px;
|
||||||
|
|
||||||
|
animation: ripple 1s;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ripple {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
background-color: rgb(253, 250, 244);
|
||||||
|
color: black;
|
||||||
|
padding: 16px 10vw;
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* babara banner 图片样式 */
|
||||||
|
#babara-card {
|
||||||
|
min-width: 256px;
|
||||||
|
max-width: 720px;
|
||||||
|
height: auto;
|
||||||
|
border-top-left-radius: 2% 3.5%;
|
||||||
|
border-top-right-radius: 2% 3.5%;
|
||||||
|
border-bottom-left-radius: 2% 3.5%;
|
||||||
|
border-bottom-right-radius: 2% 3.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-icon {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#twitter-footer-icon {
|
||||||
|
color: #1d9bf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#github-footer-icon {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-icon-text {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #footer-repository-text {
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
@media screen and (max-width: 2240px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(20% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1920px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(25% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1512px) {
|
||||||
|
body {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1280px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(100% / 3 - 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-text {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-header-text {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-repository-text {
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1265px) {
|
||||||
|
body {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 854px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(20% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 510px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 430px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#access-via-mirror,
|
||||||
|
#access-via-pages {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 294 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 226 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 226 KiB |
@@ -0,0 +1,131 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title id="doc-title">❤Duang~</title><!--change-->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||||
|
<link rel="stylesheet" href="./doristyle.css" type="text/css" /><!--change-->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<script src="https://code.iconify.design/iconify-icon/1.0.2/iconify-icon.min.js"></script>
|
||||||
|
<link href="img/favicon.ico" rel="shortcut icon">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="welcome-page">
|
||||||
|
<h2>Click to Continue</h2>
|
||||||
|
<br />
|
||||||
|
<img src="./img/welcome.gif">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--功能区-->
|
||||||
|
<div class="buttons-container">
|
||||||
|
<!-- 音乐播放按钮-->
|
||||||
|
<div id="volume-control" class="volume-control">
|
||||||
|
<i id="volume-icon" class="volume-icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--主体部分 | Main page-->
|
||||||
|
<main class="wrapper">
|
||||||
|
<div id="wrapper-background-filter"></div>
|
||||||
|
<div id="wrapper-background"></div>
|
||||||
|
<img src="img/background.gif" class="preload" />
|
||||||
|
<div id="content">
|
||||||
|
<div id="title-container">
|
||||||
|
<h1 id="page-title">Welcome to DORI's Duang~ </h1>
|
||||||
|
<img id="title-img" alt="img of Kirara" class="shake" src="img/favicon.png">
|
||||||
|
</div>
|
||||||
|
<div id="container">
|
||||||
|
<select id="language-selector">
|
||||||
|
<option id="lan1" value="cn" selected>Chinese</option>
|
||||||
|
<option id="lan2" value="ja">Japanese</option>
|
||||||
|
<option id="lan3" value="en">English</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="mode-selector">
|
||||||
|
<option id="mode1">Default</option>
|
||||||
|
<option id="mode2">Just Duang</option>
|
||||||
|
<!-- <option id="mode3">Easter egg</option> -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<hr id="subtitle-seperator" />
|
||||||
|
<h2 id="page-descriptions">
|
||||||
|
The website for Dori, the <del>moral</del> profiteering Genshin
|
||||||
|
Impact merchant out there.
|
||||||
|
</h2>
|
||||||
|
<div id="counter-container">
|
||||||
|
<h3 id="counter-descriptions">Dori has been Duang~ed for</h3>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p id="global-counter">0</p>
|
||||||
|
<p id="local-counter">0</p>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<button id="counter-button">
|
||||||
|
Let Dori Duang~!
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div id="grid">
|
||||||
|
<noscript>Your browser does not support JavaScript or JavaScript has been
|
||||||
|
disabled.<br />This website relies on JavaScript, so please enable it
|
||||||
|
or use another browser.</noscript>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- 尾部部分 | Footer -->
|
||||||
|
<div id="footer">
|
||||||
|
<img id="dori-card" loading="lazy" src="" alt="" /> <!--由JS控制src的具体路径-->
|
||||||
|
<div id="footer-text">
|
||||||
|
|
||||||
|
<p id="footer-repository-text">
|
||||||
|
You can check out the Gitee repository here:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<!--这里填写本网站的Github地址-->
|
||||||
|
<a href="https://gitee.com/KleeGitee/Klee" target="_blank">
|
||||||
|
<span class="footer-icon-text"
|
||||||
|
id="footer-repository-text-2">Web_OF_Genshin (Gitee)</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p id="footer-repository-text3">
|
||||||
|
This website is based on the repository source code changes
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<!--source code-->
|
||||||
|
<a href="https://github.com/duiqt/herta_kuru" target="_blank"><iconify-icon icon="mdi:github" id="github-footer-icon"
|
||||||
|
class="footer-icon"></iconify-icon><span class="footer-icon-text"
|
||||||
|
id="footer-repository-text-4">SourceCode's repository</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p id="credits-gif">Dori gif made by</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://twitter.com/Seseren_kr" target="_blank"><iconify-icon icon="mdi:twitter"
|
||||||
|
id="twitter-footer-icon" class="footer-icon"></iconify-icon><span
|
||||||
|
class="footer-icon-text">@Seseren_kr</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="./doriscript.js" async></script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
//加载数据库信息
|
||||||
|
require_once('../config.php');
|
||||||
|
// 创建连接
|
||||||
|
$conn = new mysqli($servername, $username, $password, $dbname);
|
||||||
|
// 连接成功,可以进行数据库操作
|
||||||
|
$sql = "SELECT globalcount FROM ys WHERE name = 'dori'";
|
||||||
|
// 执行查询
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
// 处理 POST 请求
|
||||||
|
//接收前端数据
|
||||||
|
$localcount = $_POST["localcount"];
|
||||||
|
//检查查询结果
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
$globalCount = $row['globalcount'];
|
||||||
|
|
||||||
|
// 将本地计数值加给全局计数
|
||||||
|
$globalCount += $localcount;
|
||||||
|
|
||||||
|
// 更新数据库中的全局计数值
|
||||||
|
$updateSql = "UPDATE ys SET globalcount = $globalCount WHERE name = 'dori';";
|
||||||
|
|
||||||
|
if ($conn->query($updateSql) === TRUE) {
|
||||||
|
// 更新成功
|
||||||
|
echo "更新成功";
|
||||||
|
} else {
|
||||||
|
// 更新失败
|
||||||
|
echo "更新失败: " . $conn->error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有找到全局计数值
|
||||||
|
echo "没有找到全局计数值";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回响应
|
||||||
|
//echo "这是 POST 请求的响应";
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] === "GET") {
|
||||||
|
// 处理 GET 请求
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
// 有数据返回
|
||||||
|
$rows = array();
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$rows[] = $row;
|
||||||
|
}
|
||||||
|
// 将查询结果转换为 JSON 格式发送回前端
|
||||||
|
echo json_encode($rows);
|
||||||
|
} else {
|
||||||
|
// 无数据返回
|
||||||
|
echo "没有数据";
|
||||||
|
}
|
||||||
|
// 返回响应
|
||||||
|
//echo "这是 GET 请求的响应";
|
||||||
|
} else {
|
||||||
|
// 不支持其他请求方法
|
||||||
|
http_response_code(405); // 返回“Method Not Allowed”状态码
|
||||||
|
echo "不支持的请求方法";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -0,0 +1,626 @@
|
|||||||
|
|
||||||
|
// 禁用右键菜单
|
||||||
|
document.addEventListener('contextmenu', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//图片摇摆
|
||||||
|
const img = document.getElementById('title-img');
|
||||||
|
// 定期执行动画
|
||||||
|
setInterval(() => {
|
||||||
|
// 添加 CSS 类来触发动画
|
||||||
|
img.classList.add('shake');
|
||||||
|
|
||||||
|
// 设置一个定时器,在一段时间后移除 CSS 类停止动画
|
||||||
|
setTimeout(() => {
|
||||||
|
img.classList.remove('shake');
|
||||||
|
}, 2500); // 动画持续时间为 2.5 秒
|
||||||
|
}, 5000); // 每隔 5 秒执行一次动画
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================================【BGM】=============================================================
|
||||||
|
// 欢迎页面淡出控制,音乐控制
|
||||||
|
var isMusicPlayed = false; // 记录音乐是否已经播放
|
||||||
|
var isWelcomed = false; //记录您是否已离开欢迎页面
|
||||||
|
var BGM = new Audio("./music/Thanks for Your Patronage! - HOYO-MiX.mp3"); //BGM
|
||||||
|
|
||||||
|
document.addEventListener("click", function (event) {
|
||||||
|
if (!isWelcomed) {
|
||||||
|
removeWelcomePageAndPlayMusic();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function removeWelcomePageAndPlayMusic() {
|
||||||
|
var welcomePage = document.getElementById("welcome-page");
|
||||||
|
welcomePage.style.opacity = 0;
|
||||||
|
setTimeout(function () {
|
||||||
|
welcomePage.style.display = "none";
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
if (!isMusicPlayed && !isWelcomed) {
|
||||||
|
playBackgroundMusic();
|
||||||
|
isMusicPlayed = true;
|
||||||
|
isWelcomed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function playBackgroundMusic() {
|
||||||
|
BGM.loop = true; // 循环播放
|
||||||
|
BGM.play(); // 播放BGM
|
||||||
|
BGM.volume = 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//音乐播放控制
|
||||||
|
var volumeControl = document.getElementById("volume-control");
|
||||||
|
var volumeIcon = document.getElementById("volume-icon");
|
||||||
|
|
||||||
|
|
||||||
|
//音乐暂停和播放逻辑
|
||||||
|
volumeControl.addEventListener("click", function () {
|
||||||
|
if (!isMusicPlayed) {
|
||||||
|
// Play music
|
||||||
|
BGM.play();
|
||||||
|
volumeIcon.style.animationPlayState = "running";
|
||||||
|
isMusicPlayed = true;
|
||||||
|
} else {
|
||||||
|
// Pause music
|
||||||
|
BGM.pause();
|
||||||
|
volumeIcon.style.animationPlayState = "paused";
|
||||||
|
isMusicPlayed = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================【多语言支持】============================================
|
||||||
|
|
||||||
|
|
||||||
|
var audioList = []; // 角色音频
|
||||||
|
let firstSquish = true; //第一次点击
|
||||||
|
|
||||||
|
//多语言支持
|
||||||
|
|
||||||
|
//语言属性数组
|
||||||
|
const LANGUAGES = {
|
||||||
|
//默认
|
||||||
|
"_": { fallbackLanguage: "cn" },
|
||||||
|
|
||||||
|
//中文语音、文本、海报
|
||||||
|
"cn": {
|
||||||
|
audioList: [
|
||||||
|
//0-7:默认模式 mode1
|
||||||
|
"audio/CN_voice/Duang.mp3",
|
||||||
|
"audio/CN_voice/嘿哟.mp3",
|
||||||
|
"audio/CN_voice/看我哒.mp3",
|
||||||
|
"audio/CN_voice/啦啦啦.mp3",
|
||||||
|
"audio/CN_voice/留下摩拉来.mp3",
|
||||||
|
"audio/CN_voice/魔灯显灵.mp3",
|
||||||
|
"audio/CN_voice/想午睡吗.mp3",
|
||||||
|
"audio/CN_voice/早安.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "多莉 Duang~",
|
||||||
|
"doc-title": "摩拉爱我,我爱摩拉~",
|
||||||
|
"page-descriptions": "给多莉酱写的小网站,对,就是那个<del>良心的</del>奸商的《原神》商人!",
|
||||||
|
"counter-descriptions": ["多莉已经Duang了~", "多莉已经赚了~摩拉"],
|
||||||
|
"counter-button": ["Duang~", "+1¥"],
|
||||||
|
"credits-gif": "鸣谢:Seseren_kr提供的多莉GIF图片",
|
||||||
|
"footer-repository-text": "本网站的Gitee仓库在这儿:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "鸣谢:duiqt提供的本网站基础源代码",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_cn.jpg"
|
||||||
|
},
|
||||||
|
|
||||||
|
//日文语音、文本、海报
|
||||||
|
"ja": {
|
||||||
|
audioList: [
|
||||||
|
//0-7:默认模式 mode1
|
||||||
|
"audio/CN_voice/Duang.mp3",
|
||||||
|
"audio/CN_voice/嘿哟.mp3",
|
||||||
|
"audio/CN_voice/看我哒.mp3",
|
||||||
|
"audio/CN_voice/啦啦啦.mp3",
|
||||||
|
"audio/CN_voice/留下摩拉来.mp3",
|
||||||
|
"audio/CN_voice/魔灯显灵.mp3",
|
||||||
|
"audio/CN_voice/想午睡吗.mp3",
|
||||||
|
"audio/CN_voice/早安.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "ドリーDuang",
|
||||||
|
"doc-title": "Duang~",
|
||||||
|
"page-descriptions": "このサイトはドリーのために作られた、 あの原神の <del>良心的</del> あくとく商人です",
|
||||||
|
"counter-descriptions": "Duang-数",
|
||||||
|
"counter-button": "+1$",
|
||||||
|
"credits-gif": "感謝: Seseren_kr さんが提供してくれたドリーのGIF画像",
|
||||||
|
"footer-repository-text": "こちらはこのページGitee (Mainland China) リポジトリ:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "感謝:duiqt さんが提供してくれたこのウェブサイトの基礎ソースコード",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_jp.jpg"
|
||||||
|
},
|
||||||
|
//英文语音、文本、海报
|
||||||
|
"en": {
|
||||||
|
audioList: [
|
||||||
|
//0-7:默认模式 mode1
|
||||||
|
"audio/CN_voice/Duang.mp3",
|
||||||
|
"audio/CN_voice/嘿哟.mp3",
|
||||||
|
"audio/CN_voice/看我哒.mp3",
|
||||||
|
"audio/CN_voice/啦啦啦.mp3",
|
||||||
|
"audio/CN_voice/留下摩拉来.mp3",
|
||||||
|
"audio/CN_voice/魔灯显灵.mp3",
|
||||||
|
"audio/CN_voice/想午睡吗.mp3",
|
||||||
|
"audio/CN_voice/早安.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "Welcome to DORI's Duang~",
|
||||||
|
"doc-title": "Duang~",
|
||||||
|
"page-descriptions": "The website for Dori, the <del>moral</del> profiteering Genshin Impact merchant out there.",
|
||||||
|
"counter-descriptions": "Dori has been Duang~ed for",
|
||||||
|
"counter-button": "Duang~",
|
||||||
|
"credits-gif": "Acknowledgment: GIF images of Dori provided by Seseren_kr.",
|
||||||
|
"footer-repository-text": "You can check out the Gitee repository (Mainland China) here:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "Special thanks to duiqt for providing the source code for this website.",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_en.jpg"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//设置语言选择器的文本语言
|
||||||
|
function refreshLanguageSelector(selectedLanguage) {
|
||||||
|
switch (selectedLanguage) {
|
||||||
|
case "cn":
|
||||||
|
document.getElementById("lan1").innerHTML = "🌏中文";
|
||||||
|
document.getElementById("lan2").innerHTML = "日文";
|
||||||
|
document.getElementById("lan3").innerHTML = "英文";
|
||||||
|
break;
|
||||||
|
case "ja":
|
||||||
|
document.getElementById("lan1").innerHTML = "中国語";
|
||||||
|
document.getElementById("lan2").innerHTML = "🌏日本語";
|
||||||
|
document.getElementById("lan3").innerHTML = "英語";
|
||||||
|
break;
|
||||||
|
case "en":
|
||||||
|
document.getElementById("lan1").innerHTML = "Chinese";
|
||||||
|
document.getElementById("lan2").innerHTML = "Japanese";
|
||||||
|
document.getElementById("lan3").innerHTML = "🌏English";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置模式选择器的文本语言
|
||||||
|
function refreshModeSelector(selectedLanguage) {
|
||||||
|
switch (selectedLanguage) {
|
||||||
|
case "cn":
|
||||||
|
document.getElementById("mode1").innerHTML = "默认模式";
|
||||||
|
document.getElementById("mode2").innerHTML = "只要Duang~";
|
||||||
|
// document.getElementById("mode3").innerHTML = "隐藏彩蛋";
|
||||||
|
break;
|
||||||
|
case "ja":
|
||||||
|
document.getElementById("mode1").innerHTML = "デフォルトモード";
|
||||||
|
document.getElementById("mode2").innerHTML = "Duang~だけ";
|
||||||
|
// document.getElementById("mode3").innerHTML = "ひみつ";
|
||||||
|
break;
|
||||||
|
case "en":
|
||||||
|
document.getElementById("mode1").innerHTML = "DefaultMode";
|
||||||
|
document.getElementById("mode2").innerHTML = "Just Duang";
|
||||||
|
// document.getElementById("mode3").innerHTML = "Easter egg";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//获取默认语言并赋值给语言选择框
|
||||||
|
var current_language = localStorage.getItem("lang") || "cn";
|
||||||
|
if (current_language != "cn") {
|
||||||
|
document.getElementById("language-selector").value = current_language;
|
||||||
|
};
|
||||||
|
|
||||||
|
//通过获取当前语言和对应的文本数组,遍历文本数组中的每个键值对。如果文本值是一个数组,就从数组中随机选择一个元素作为新的文本内容,并将其更新到对应的 HTML 元素中
|
||||||
|
function randomChoice(myArr) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * myArr.length);
|
||||||
|
const randomItem = myArr[randomIndex];
|
||||||
|
return randomItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
//核心函数!动态刷新动态文本内容(将新的DOM值渲染到前端)
|
||||||
|
function refreshDynamicTexts() {
|
||||||
|
let curLang = LANGUAGES[current_language];
|
||||||
|
let localTexts = curLang.texts;
|
||||||
|
Object.entries(localTexts).forEach(([textId, value]) => {
|
||||||
|
if (value instanceof Array)
|
||||||
|
if (document.getElementById(textId) != undefined)
|
||||||
|
document.getElementById(textId).innerHTML = randomChoice(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//定义函数:根据当前语言,渲染页面
|
||||||
|
function multiLangMutation() {
|
||||||
|
let curLang = LANGUAGES[current_language]; //获取当前的网站语言
|
||||||
|
let localTexts = curLang.texts; //获取当前语言的文本数组
|
||||||
|
Object.entries(localTexts).forEach(([textId, value]) => { //将各个DOM元素的值变为文本值
|
||||||
|
if (!(value instanceof Array))
|
||||||
|
if (document.getElementById(textId) != undefined)
|
||||||
|
document.getElementById(textId).innerHTML = value;
|
||||||
|
});
|
||||||
|
refreshDynamicTexts() //刷新动态文本内容(将新的DOM值渲染到前端)
|
||||||
|
document.getElementById("dori-card").src = curLang.cardImage; //动态获取klee-card在当前语言文本环境下的Dom元素并更新
|
||||||
|
|
||||||
|
var selectedLanguage = document.getElementById("language-selector").value;
|
||||||
|
refreshLanguageSelector(selectedLanguage) //更新语言选择器的文本语言
|
||||||
|
refreshModeSelector(selectedLanguage) //更新模式选择器的文本语言
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
curLang 变量获取了当前选择的网站语言对应的语言对象(假设为 LANGUAGES 全局对象中的一个属性)。
|
||||||
|
localTexts 变量获取了当前语言对象中的文本数组。
|
||||||
|
使用 Object.entries() 方法遍历 localTexts 中的键值对。
|
||||||
|
对于每一个键值对,解构赋值为 [textId, value],其中 textId 是 DOM 元素的 ID,value 是对应的文本值。
|
||||||
|
首先检查 value 是否为数组,如果不是数组,表示是单个文本值(例如字符串)。
|
||||||
|
检查当前网页是否存在具有对应 textId 的 DOM 元素(通过 document.getElementById(textId) 来判断)。
|
||||||
|
如果存在对应的 DOM 元素,则将其内部的 HTML 内容更新为 value。
|
||||||
|
这样就实现了根据当前语言选择动态更新网页中的文本内容。
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
multiLangMutation() //初始化网站语言
|
||||||
|
|
||||||
|
//通过这段代码,当语言选择器的值发生变化时,会根据选择的语言重新渲染页面的文本内容和动态图片,实现动态调整网站语言的功能。
|
||||||
|
document.getElementById("language-selector").addEventListener("change", (ev) => {
|
||||||
|
current_language = ev.target.value;
|
||||||
|
localStorage.setItem("lang", ev.target.value);
|
||||||
|
multiLangMutation();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======================================================================【按钮点击、计数器】============================================
|
||||||
|
|
||||||
|
// 初始化计数器
|
||||||
|
//本地计数器
|
||||||
|
const localCounter = document.querySelector('#local-counter'); //获取展示本地点击数的DOM元素
|
||||||
|
let localCount = localStorage.getItem('count-local-dori') || 0; //获取本地点击数的值
|
||||||
|
localCounter.textContent = localCount.toLocaleString('en-US'); //使用美式英语的格式进行格式化。这样可以确保数值以适当的方式显示,例如添加千位分隔符
|
||||||
|
|
||||||
|
|
||||||
|
let prevTime = 0;
|
||||||
|
|
||||||
|
//获取时间戳
|
||||||
|
const getTimestamp = () => Date.parse(new Date());
|
||||||
|
|
||||||
|
//点击duang的按钮事件
|
||||||
|
const counterButton = document.querySelector('#counter-button');
|
||||||
|
counterButton.addEventListener('click', (e) => {
|
||||||
|
prevTime = getTimestamp(); //当前时间
|
||||||
|
localCount++;
|
||||||
|
localStorage.setItem('count-local-dori', localCount); //缓存localCount到本地
|
||||||
|
|
||||||
|
localCounter.textContent = localCount.toLocaleString('en-US');
|
||||||
|
|
||||||
|
triggerRipple(e); //按钮的水波纹效果
|
||||||
|
playDuang(); //播放可莉语音
|
||||||
|
animateDori(); //播放可莉动画
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================================【资源缓存】========================================================
|
||||||
|
var cachedObjects = {};
|
||||||
|
function tryCachedObject(origUrl) {
|
||||||
|
// 检查对象是否已经被缓存
|
||||||
|
if (cachedObjects[origUrl]) {
|
||||||
|
return cachedObjects[origUrl];
|
||||||
|
} else {
|
||||||
|
// 开始缓存
|
||||||
|
fetch(origUrl)
|
||||||
|
.then((response) => response.blob())
|
||||||
|
.then((blob) => {
|
||||||
|
// 为对象创建一个blob URL
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
// 通过在cachedObjects对象中存储blob URL来获取缓存的对象
|
||||||
|
cachedObjects[origUrl] = blobUrl;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(`Error caching object from ${origUrl}: ${error}`);
|
||||||
|
});
|
||||||
|
return origUrl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//缓存所有资源
|
||||||
|
function cacheAllResources() {
|
||||||
|
// 缓存图片资源
|
||||||
|
for (let i = 1; i < 3; i++) {
|
||||||
|
const imageUrl = `img/animation/${i}.gif`;
|
||||||
|
tryCachedObject(imageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存中文音频资源(含通用语音资源)
|
||||||
|
const cnAudioList = LANGUAGES.cn.audioList;
|
||||||
|
cnAudioList.forEach((audioUrl) => {
|
||||||
|
tryCachedObject(audioUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 缓存日文音频资源(含通用语音资源)
|
||||||
|
const jaAudioList = LANGUAGES.ja.audioList;
|
||||||
|
jaAudioList.forEach((audioUrl) => {
|
||||||
|
tryCachedObject(audioUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
//只需要执行一次该功能
|
||||||
|
firstLoadClick = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当页面加载完成后触发缓存资源
|
||||||
|
// var firstLoadClick = true;
|
||||||
|
// window.addEventListener('click', cacheAllResources);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================【按钮点击后的动画、音频】================================================
|
||||||
|
|
||||||
|
//返回当前语言的音频数组
|
||||||
|
function getLocalAudioList() {
|
||||||
|
return LANGUAGES[current_language].audioList;
|
||||||
|
};
|
||||||
|
//从音频数组中获取一个随机的音频URL(传入一个当前模式。curMode==mode1 默认模式,cueMode==mode3)
|
||||||
|
function getRandomAudioUrl(curMode) {
|
||||||
|
var localAudioList = getLocalAudioList()
|
||||||
|
|
||||||
|
//根据模式产生符合模式的音频下标
|
||||||
|
if (curMode == "mode1") {
|
||||||
|
randomIndex = Math.floor(Math.random() * 8); //默认语音的文件是:文件下标0-8.这儿的数字就写8.
|
||||||
|
}
|
||||||
|
// if (curMode == "mode3") {
|
||||||
|
// randomIndex = Math.floor(Math.random() * 17); //文件下标0-16.这儿的数字就写14. 【这儿写彩蛋对应的audioList下标】
|
||||||
|
// }
|
||||||
|
|
||||||
|
const randomItem = localAudioList[randomIndex];
|
||||||
|
return randomItem;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//播放音频
|
||||||
|
var isFirstVoice = true;
|
||||||
|
function playDuang() {
|
||||||
|
|
||||||
|
//先获取当前的模式:1-默认;2-只哒哒哒;3-彩蛋
|
||||||
|
const modeSelectElement = document.getElementById("mode-selector");
|
||||||
|
const modeSelectedOption = modeSelectElement.options[modeSelectElement.selectedIndex];
|
||||||
|
const curMode = modeSelectedOption.id;
|
||||||
|
|
||||||
|
//要播放的音频Url
|
||||||
|
let audioUrl;
|
||||||
|
|
||||||
|
//根据当前模式获取符合模式语音的 AudioURL
|
||||||
|
switch (curMode) {
|
||||||
|
//curMode==mode1 默认模式
|
||||||
|
case "mode1": {
|
||||||
|
if (isFirstVoice == true) {//随机获取一个音频的URL,第一个必定是哒哒哒
|
||||||
|
isFirstVoice = false;
|
||||||
|
audioUrl = getLocalAudioList()[0] //First play fixed Duang
|
||||||
|
} else {
|
||||||
|
audioUrl = getRandomAudioUrl(curMode);
|
||||||
|
}
|
||||||
|
}; break;
|
||||||
|
|
||||||
|
//curMode==mode2 只哒哒哒
|
||||||
|
case "mode2": {
|
||||||
|
audioUrl = getLocalAudioList()[0]
|
||||||
|
}; break;
|
||||||
|
|
||||||
|
//cueMode==mode3 彩蛋
|
||||||
|
// case "mode3": {
|
||||||
|
// if (isFirstVoice == true) {//随机获取一个音频的URL,第一个必定是哒哒哒
|
||||||
|
// isFirstVoice = false;
|
||||||
|
// audioUrl = getLocalAudioList()[1] //First play fixed Dadada
|
||||||
|
// } else {
|
||||||
|
// audioUrl = getRandomAudioUrl(curMode);
|
||||||
|
// }
|
||||||
|
// }; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//根据音频URL从本地获取音频资源。同时将该音频缓存到本地
|
||||||
|
let audio = new Audio(tryCachedObject(audioUrl)); //【缓存貌似可以删除】
|
||||||
|
|
||||||
|
//播放音频后监听音频结束事件,并在音频播放结束时将音频元素从 DOM 中移除
|
||||||
|
audio.play();
|
||||||
|
audio.addEventListener("ended", function () {
|
||||||
|
this.remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function animateDori() {
|
||||||
|
let id = null;
|
||||||
|
|
||||||
|
const random = Math.floor(Math.random() * 2) + 1; //1-2,GIF
|
||||||
|
const elem = document.createElement("img");
|
||||||
|
elem.src = tryCachedObject(`img/animation/${random}.gif`);
|
||||||
|
|
||||||
|
//下面根据不同的窗口改变多莉动画的样式(响应式)
|
||||||
|
const screenWidth = window.innerWidth;
|
||||||
|
|
||||||
|
if (screenWidth > 768) {
|
||||||
|
elem.style.position = "absolute";
|
||||||
|
elem.style.right = "-500px";
|
||||||
|
elem.style.top = counterButton.getClientRects()[0].bottom + scrollY - 430 + "px"
|
||||||
|
elem.style.zIndex = "-10";
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
|
||||||
|
let pos = -500;
|
||||||
|
const limit = window.innerWidth + 500;
|
||||||
|
clearInterval(id);
|
||||||
|
id = setInterval(() => {
|
||||||
|
if (pos >= limit) {
|
||||||
|
clearInterval(id);
|
||||||
|
elem.remove()
|
||||||
|
} else {
|
||||||
|
pos += 20;
|
||||||
|
elem.style.right = pos + 'px';
|
||||||
|
}
|
||||||
|
}, 12);
|
||||||
|
} else {
|
||||||
|
//移动端,把动画变小、变慢一点
|
||||||
|
elem.style.position = "absolute";
|
||||||
|
elem.style.right = "-500px";
|
||||||
|
elem.style.top = counterButton.getClientRects()[0].bottom + scrollY - 180 + "px"
|
||||||
|
elem.style.zIndex = "-10";
|
||||||
|
elem.style.width = "250px"; // 设置宽度为 200px(让移动端方便观看)
|
||||||
|
elem.style.height = "auto"; // 自动计算高度,保持纵横比
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
|
||||||
|
let pos = -500;
|
||||||
|
const limit = window.innerWidth + 500;
|
||||||
|
clearInterval(id);
|
||||||
|
id = setInterval(() => {
|
||||||
|
if (pos >= limit) {
|
||||||
|
clearInterval(id);
|
||||||
|
elem.remove()
|
||||||
|
} else {
|
||||||
|
pos += 10;
|
||||||
|
elem.style.right = pos + 'px';
|
||||||
|
}
|
||||||
|
}, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//点击 counter-button 元素时,会在点击位置出现一个水波纹效果。
|
||||||
|
function triggerRipple(e) {
|
||||||
|
let ripple = document.createElement("span");
|
||||||
|
|
||||||
|
ripple.classList.add("ripple");
|
||||||
|
|
||||||
|
const counter_button = document.getElementById("counter-button");
|
||||||
|
counter_button.appendChild(ripple);
|
||||||
|
|
||||||
|
let x = e.clientX - e.target.offsetLeft;
|
||||||
|
let y = e.clientY - e.target.offsetTop;
|
||||||
|
|
||||||
|
ripple.style.left = `${x}px`;
|
||||||
|
ripple.style.top = `${y}px`;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
ripple.remove();
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================【全球计数器】======================================
|
||||||
|
//算法思路:先前的项目已经实现了永久保存本地计数。接下来要实现统计全球技术:
|
||||||
|
//1.为了节省流量,规定每一分钟自动上传一次【本次点击数】(定义一个区别于 localCount 的新变量 thisTimeCount)
|
||||||
|
//2.发送Ajax,发送 thisTimeCount 服务端返回 globalCount渲染到页面,同时将本地的 thisTimeCount 清零
|
||||||
|
|
||||||
|
|
||||||
|
var thisTimeCounts = 0; //本次轮询Ajax之前的点击数
|
||||||
|
var intervalID = setInterval(updateGlobalCount, 15000);//间隔多久上传一次,单位ms
|
||||||
|
|
||||||
|
//点击一次按钮,thisTimeCount++
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#counter-button').click(function () {
|
||||||
|
thisTimeCounts++ //本次定时轮询Ajax之前的点击数 +1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//上传数据
|
||||||
|
function updateGlobalCount() {
|
||||||
|
$.ajax({
|
||||||
|
url: './dori.php',
|
||||||
|
method: 'POST',
|
||||||
|
async: false,
|
||||||
|
data: { localcount: thisTimeCounts },
|
||||||
|
success: function(response) {
|
||||||
|
// 处理成功响应
|
||||||
|
console.log(response);
|
||||||
|
thisTimeCounts = 0;
|
||||||
|
$('#local-counter').text(localCount);
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
// 处理错误响应
|
||||||
|
console.error("请求失败: " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//首次访问网站的时候,立即获取 globalCounts并刷新 (页面加载完成后立即执行)
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
$.ajax({
|
||||||
|
url: './dori.php',
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
headers: {
|
||||||
|
'ajax-requests': 'true'
|
||||||
|
},
|
||||||
|
/*data: {
|
||||||
|
thistimecountFromFront: thisTimeCounts, //将前端的 thisTimeCount 传给后端,参数名为 thistimecountFromFront
|
||||||
|
},*/
|
||||||
|
success: function (response) {
|
||||||
|
var globalcount = response[0].globalcount;
|
||||||
|
//console.log(response);
|
||||||
|
console.log("初始化成功,globalcountsFromBackend = " + globalcount)
|
||||||
|
var globalCountElement = document.getElementById("global-counter");
|
||||||
|
globalCountElement.textContent = (globalcount).toLocaleString('en-US')
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 定时轮询后端获取 globalCounts
|
||||||
|
setInterval(function () {
|
||||||
|
$.ajax({
|
||||||
|
url: './dori.php',
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
headers: {
|
||||||
|
'ajax-requests': 'true'
|
||||||
|
},
|
||||||
|
//type: 'text',
|
||||||
|
/*data: {
|
||||||
|
thistimecountFromFront: thisTimeCounts, //将前端的 thisTimeCount 传给后端,参数名为 thistimecountFromFront
|
||||||
|
},*/
|
||||||
|
success: function (response) {
|
||||||
|
var globalcount = response[0].globalcount;
|
||||||
|
console.log("前端收到了后端返回的全球计数 = " + globalcount)
|
||||||
|
|
||||||
|
//thisTimeCounts = 0; //将前端本地点击数清零
|
||||||
|
|
||||||
|
var globalCountElement = document.getElementById("global-counter"); //获取全球计数器DOM
|
||||||
|
globalCountElement.textContent = (globalcount).toLocaleString('en-US') //更新全球计数器的值
|
||||||
|
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 5000); // 每5s执行一次
|
||||||
|
|
||||||
@@ -0,0 +1,479 @@
|
|||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
/* disable double_tap zoom on mobile devices */
|
||||||
|
-ms-touch-action: manipulation;
|
||||||
|
touch-action: manipulation;
|
||||||
|
/* strange margin-right occurs when vw<500px */
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* 底部颜色 */
|
||||||
|
background-color: rgba(233, 233, 233);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", 'Roboto', sans-serif;
|
||||||
|
font-size: 1.5em;
|
||||||
|
/* 顶部文字颜色 */
|
||||||
|
color: #441d7a;
|
||||||
|
/* 禁用右键和选中 */
|
||||||
|
-webkit-user-select: none;
|
||||||
|
/* Chrome, Safari, Opera */
|
||||||
|
-moz-user-select: none;
|
||||||
|
/* Firefox */
|
||||||
|
-ms-user-select: none;
|
||||||
|
/* Internet Explorer/Edge */
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 欢迎页面 */
|
||||||
|
#welcome-page {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(42, 21, 72, 0.8);
|
||||||
|
color: rgb(241, 241, 8);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcome-page img {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 功能区大盒子 */
|
||||||
|
.buttons-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 8888;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 播放按钮 */
|
||||||
|
.volume-control {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: rgba(71, 13, 98, 0.5);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
/* 按钮和右边按钮间隔20px */
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-control:hover {
|
||||||
|
background-color: #e5e2e2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-image: url("./img/volume_icon.png");
|
||||||
|
background-size: cover;
|
||||||
|
animation: rotate-icon 5s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate-icon {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper-background {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-image: url("img/background.gif");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 50%;
|
||||||
|
background-size: contain;
|
||||||
|
z-index: -30;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper-background-filter {
|
||||||
|
/* 背景颜色 */
|
||||||
|
background-color: rgba(192, 114, 201, 0.9);
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preload {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
margin: 2vh auto;
|
||||||
|
width: 80vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 3em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
/* 分割线 */
|
||||||
|
border-bottom: 6px dashed #f0dd4a;
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-title {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* logo */
|
||||||
|
#title-img {
|
||||||
|
height: 3.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0% {
|
||||||
|
transform: rotate(-5deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(5deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(-5deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shake {
|
||||||
|
animation: shake 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container select {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language-selector,
|
||||||
|
#mode-selector {
|
||||||
|
width: 200px;
|
||||||
|
height: 40px;
|
||||||
|
/* 选择框颜色 */
|
||||||
|
background-color: #decc43;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
text-align-last: center;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 10px;
|
||||||
|
color: rgb(38, 36, 38);
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language-selector:hover,
|
||||||
|
#mode-selector:hover {
|
||||||
|
box-shadow: 0 0 10px #decc43;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#language-selector option {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #decc43;
|
||||||
|
color: rgb(118, 114, 114);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-container {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 64px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-container>p {
|
||||||
|
text-shadow: #decc43 0 0 10px, #decc43 0 0 10px, #decc43 0 0 10px, #decc43 0 0 10px, #decc43 0 0 10px;
|
||||||
|
}
|
||||||
|
/* 全球计数器文字颜色 */
|
||||||
|
#global-counter {
|
||||||
|
color: #7a6f0a;
|
||||||
|
font-size: 4em;
|
||||||
|
text-shadow:
|
||||||
|
-1px -1px 0 black,
|
||||||
|
1px -1px 0 black,
|
||||||
|
-1px 1px 0 black,
|
||||||
|
1px 1px 0 black; /* 描边效果 */
|
||||||
|
}
|
||||||
|
/* 本地计数器文字颜色 */
|
||||||
|
#local-counter {
|
||||||
|
color: #7a6f0a;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button {
|
||||||
|
/* 动画触发按钮颜色 */
|
||||||
|
background-color: #c6b427;
|
||||||
|
border: none;
|
||||||
|
border-radius: 16px;
|
||||||
|
color: rgb(49, 7, 77);
|
||||||
|
padding: 16px 32px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 1em;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 6px 7px 40px -4px rgba(43, 42, 42, 0.2);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.1s ease-in-out, scale 0.1s cubic-bezier(0.075, 0.82, 0.165, 1);
|
||||||
|
}
|
||||||
|
/* 动画触发按钮的悬挂颜色 */
|
||||||
|
#counter-button:hover {
|
||||||
|
background-color: #f0d50d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button:active {
|
||||||
|
scale: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button span {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff50;
|
||||||
|
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
margin-top: -50px;
|
||||||
|
margin-left: -50px;
|
||||||
|
|
||||||
|
animation: ripple 1s;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ripple {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
background-color: rgb(253, 250, 244);
|
||||||
|
color: black;
|
||||||
|
padding: 16px 10vw;
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dori banner 图片样式 */
|
||||||
|
#dori-card {
|
||||||
|
min-width: 256px;
|
||||||
|
max-width: 720px;
|
||||||
|
height: auto;
|
||||||
|
border-top-left-radius: 2% 3.5%;
|
||||||
|
border-top-right-radius: 2% 3.5%;
|
||||||
|
border-bottom-left-radius: 2% 3.5%;
|
||||||
|
border-bottom-right-radius: 2% 3.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-icon {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#twitter-footer-icon {
|
||||||
|
color: #1d9bf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#github-footer-icon {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-icon-text {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #footer-repository-text {
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
@media screen and (max-width: 2240px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(20% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1920px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(25% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1512px) {
|
||||||
|
body {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1280px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(100% / 3 - 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-text {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-header-text {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-repository-text {
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1265px) {
|
||||||
|
body {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 854px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(20% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 510px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 430px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#access-via-mirror,
|
||||||
|
#access-via-pages {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 157 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 129 KiB |
@@ -0,0 +1,131 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title id="doc-title">Miaouuuu~</title><!--change-->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||||
|
<link rel="stylesheet" href="kirarastyle.css" type="text/css" /><!--change-->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<script src="https://code.iconify.design/iconify-icon/1.0.2/iconify-icon.min.js"></script>
|
||||||
|
<link href="img/favicon.ico" rel="shortcut icon">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="welcome-page">
|
||||||
|
<h2>Click to Continue</h2>
|
||||||
|
<br />
|
||||||
|
<img src="./img/welcome.gif">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--功能区-->
|
||||||
|
<div class="buttons-container">
|
||||||
|
<!-- 音乐播放按钮-->
|
||||||
|
<div id="volume-control" class="volume-control">
|
||||||
|
<i id="volume-icon" class="volume-icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--主体部分 | Main page-->
|
||||||
|
<main class="wrapper">
|
||||||
|
<div id="wrapper-background-filter"></div>
|
||||||
|
<div id="wrapper-background"></div>
|
||||||
|
<img src="img/background.gif" class="preload" />
|
||||||
|
<div id="content">
|
||||||
|
<div id="title-container">
|
||||||
|
<h1 id="page-title">Welcome to Kirara Miaouu~ </h1>
|
||||||
|
<img id="title-img" alt="img of Kirara" class="shake" src="img/favicon.png">
|
||||||
|
</div>
|
||||||
|
<div id="container">
|
||||||
|
<select id="language-selector">
|
||||||
|
<option id="lan1" value="cn" selected>Chinese</option>
|
||||||
|
<option id="lan2" value="ja">Japanese</option>
|
||||||
|
<option id="lan3" value="en">English</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="mode-selector">
|
||||||
|
<option id="mode1">Default</option>
|
||||||
|
<!-- <option id="mode2">Just Dadada</option>
|
||||||
|
<option id="mode3">Easter egg</option> -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<hr id="subtitle-seperator" />
|
||||||
|
<h2 id="page-descriptions">
|
||||||
|
The website for Kirara, the <del>annoying</del> cutest genius Genshin
|
||||||
|
Impact Cat out there.
|
||||||
|
</h2>
|
||||||
|
<div id="counter-container">
|
||||||
|
<h3 id="counter-descriptions">Kirara has been miaow~ed for</h3>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p id="global-counter">0</p>
|
||||||
|
<p id="local-counter">0</p>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<button id="counter-button">
|
||||||
|
Let Kirara miaows~!
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div id="grid">
|
||||||
|
<noscript>Your browser does not support JavaScript or JavaScript has been
|
||||||
|
disabled.<br />This website relies on JavaScript, so please enable it
|
||||||
|
or use another browser.</noscript>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- 尾部部分 | Footer -->
|
||||||
|
<div id="footer">
|
||||||
|
<img id="kirara-card" loading="lazy" src="" alt="" /> <!--由JS控制src的具体路径-->
|
||||||
|
<div id="footer-text">
|
||||||
|
|
||||||
|
<p id="footer-repository-text">
|
||||||
|
You can check out the Gitee repository here:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<!--这里填写本网站的Github地址-->
|
||||||
|
<a href="https://gitee.com/KleeGitee/Klee" target="_blank">
|
||||||
|
<span class="footer-icon-text"
|
||||||
|
id="footer-repository-text-2">Web_OF_Genshin (Gitee)</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p id="footer-repository-text3">
|
||||||
|
This website is based on the repository source code changes
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<!--source code-->
|
||||||
|
<a href="https://github.com/duiqt/herta_kuru" target="_blank"><iconify-icon icon="mdi:github" id="github-footer-icon"
|
||||||
|
class="footer-icon"></iconify-icon><span class="footer-icon-text"
|
||||||
|
id="footer-repository-text-4">SourceCode's repository</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<p id="credits-gif">Kirara gif made by</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://twitter.com/Seseren_kr" target="_blank"><iconify-icon icon="mdi:twitter"
|
||||||
|
id="twitter-footer-icon" class="footer-icon"></iconify-icon><span
|
||||||
|
class="footer-icon-text">@Seseren_kr</span></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="./kirarascript.js" async></script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
//加载数据库信息
|
||||||
|
require_once('../config.php');
|
||||||
|
// 创建连接
|
||||||
|
$conn = new mysqli($servername, $username, $password, $dbname);
|
||||||
|
// 连接成功,可以进行数据库操作
|
||||||
|
$sql = "SELECT globalcount FROM ys WHERE name = 'kirara'";
|
||||||
|
// 执行查询
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
// 处理 POST 请求
|
||||||
|
//接收前端数据
|
||||||
|
$localcount = $_POST["localcount"];
|
||||||
|
//检查查询结果
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
$globalCount = $row['globalcount'];
|
||||||
|
|
||||||
|
// 将本地计数值加给全局计数
|
||||||
|
$globalCount += $localcount;
|
||||||
|
|
||||||
|
// 更新数据库中的全局计数值
|
||||||
|
$updateSql = "UPDATE ys SET globalcount = $globalCount WHERE name = 'kirara';";
|
||||||
|
|
||||||
|
if ($conn->query($updateSql) === TRUE) {
|
||||||
|
// 更新成功
|
||||||
|
echo "更新成功";
|
||||||
|
} else {
|
||||||
|
// 更新失败
|
||||||
|
echo "更新失败: " . $conn->error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有找到全局计数值
|
||||||
|
echo "没有找到全局计数值";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回响应
|
||||||
|
//echo "这是 POST 请求的响应";
|
||||||
|
} elseif ($_SERVER["REQUEST_METHOD"] === "GET") {
|
||||||
|
// 处理 GET 请求
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
// 有数据返回
|
||||||
|
$rows = array();
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$rows[] = $row;
|
||||||
|
}
|
||||||
|
// 将查询结果转换为 JSON 格式发送回前端
|
||||||
|
echo json_encode($rows);
|
||||||
|
} else {
|
||||||
|
// 无数据返回
|
||||||
|
echo "没有数据";
|
||||||
|
}
|
||||||
|
// 返回响应
|
||||||
|
//echo "这是 GET 请求的响应";
|
||||||
|
} else {
|
||||||
|
// 不支持其他请求方法
|
||||||
|
http_response_code(405); // 返回“Method Not Allowed”状态码
|
||||||
|
echo "不支持的请求方法";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -0,0 +1,620 @@
|
|||||||
|
|
||||||
|
// 禁用右键菜单
|
||||||
|
document.addEventListener('contextmenu', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//图片摇摆
|
||||||
|
const img = document.getElementById('title-img');
|
||||||
|
// 定期执行动画
|
||||||
|
setInterval(() => {
|
||||||
|
// 添加 CSS 类来触发动画
|
||||||
|
img.classList.add('shake');
|
||||||
|
|
||||||
|
// 设置一个定时器,在一段时间后移除 CSS 类停止动画
|
||||||
|
setTimeout(() => {
|
||||||
|
img.classList.remove('shake');
|
||||||
|
}, 2500); // 动画持续时间为 2.5 秒
|
||||||
|
}, 5000); // 每隔 5 秒执行一次动画
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================================【BGM】=============================================================
|
||||||
|
// 欢迎页面淡出控制,音乐控制
|
||||||
|
var isMusicPlayed = false; // 记录音乐是否已经播放
|
||||||
|
var isWelcomed = false; //记录您是否已离开欢迎页面
|
||||||
|
var BGM = new Audio("./music/彩虹猫 (Remix) - soul light-LHPT.mp3"); //BGM
|
||||||
|
|
||||||
|
document.addEventListener("click", function (event) {
|
||||||
|
if (!isWelcomed) {
|
||||||
|
removeWelcomePageAndPlayMusic();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function removeWelcomePageAndPlayMusic() {
|
||||||
|
var welcomePage = document.getElementById("welcome-page");
|
||||||
|
welcomePage.style.opacity = 0;
|
||||||
|
setTimeout(function () {
|
||||||
|
welcomePage.style.display = "none";
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
if (!isMusicPlayed && !isWelcomed) {
|
||||||
|
playBackgroundMusic();
|
||||||
|
isMusicPlayed = true;
|
||||||
|
isWelcomed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function playBackgroundMusic() {
|
||||||
|
BGM.loop = true; // 循环播放
|
||||||
|
BGM.play(); // 播放BGM
|
||||||
|
BGM.volume = 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//音乐播放控制
|
||||||
|
var volumeControl = document.getElementById("volume-control");
|
||||||
|
var volumeIcon = document.getElementById("volume-icon");
|
||||||
|
|
||||||
|
|
||||||
|
//音乐暂停和播放逻辑
|
||||||
|
volumeControl.addEventListener("click", function () {
|
||||||
|
if (!isMusicPlayed) {
|
||||||
|
// Play music
|
||||||
|
BGM.play();
|
||||||
|
volumeIcon.style.animationPlayState = "running";
|
||||||
|
isMusicPlayed = true;
|
||||||
|
} else {
|
||||||
|
// Pause music
|
||||||
|
BGM.pause();
|
||||||
|
volumeIcon.style.animationPlayState = "paused";
|
||||||
|
isMusicPlayed = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================【多语言支持】============================================
|
||||||
|
|
||||||
|
|
||||||
|
var audioList = []; // 角色音频
|
||||||
|
let firstSquish = true; //第一次点击
|
||||||
|
|
||||||
|
//多语言支持
|
||||||
|
|
||||||
|
//语言属性数组
|
||||||
|
const LANGUAGES = {
|
||||||
|
//默认
|
||||||
|
"_": { fallbackLanguage: "cn" },
|
||||||
|
|
||||||
|
//中文语音、文本、海报
|
||||||
|
"cn": {
|
||||||
|
audioList: [
|
||||||
|
//0-5:默认模式 mode1
|
||||||
|
"audio/CN_voice/嘿咻.mp3",
|
||||||
|
"audio/CN_voice/喵.mp3",
|
||||||
|
"audio/CN_voice/喵嗷.mp3",
|
||||||
|
"audio/CN_voice/挠你哦.mp3",
|
||||||
|
"audio/CN_voice/跳跃1.mp3",
|
||||||
|
"audio/CN_voice/跳跃2.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "绮良良 喵呜~",
|
||||||
|
"doc-title": "喵喵喵~",
|
||||||
|
"page-descriptions": "给快递员绮良良写的小网站,对,就是那个<del>烦人的</del>很可爱的《原神》小猫!",
|
||||||
|
"counter-descriptions": ["绮良良已经喵了", "绮良良已经嗷呜了"],
|
||||||
|
"counter-button": ["喵呜~", "嗷呜!"],
|
||||||
|
"credits-gif": "鸣谢:Seseren_kr提供的绮良良GIF图片",
|
||||||
|
"footer-repository-text": "本网站的Gitee仓库在这儿:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "鸣谢:duiqt提供的本网站基础源代码",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_cn.jpg"
|
||||||
|
},
|
||||||
|
|
||||||
|
//日文语音、文本、海报
|
||||||
|
"ja": {
|
||||||
|
audioList: [
|
||||||
|
//0-5:默认模式 mode1
|
||||||
|
"audio/CN_voice/嘿咻.mp3",
|
||||||
|
"audio/CN_voice/喵.mp3",
|
||||||
|
"audio/CN_voice/喵嗷.mp3",
|
||||||
|
"audio/CN_voice/挠你哦.mp3",
|
||||||
|
"audio/CN_voice/跳跃1.mp3",
|
||||||
|
"audio/CN_voice/跳跃2.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "綺良々ーにゃー",
|
||||||
|
"doc-title": "にゃにゃにゃ",
|
||||||
|
"page-descriptions": "このサイトは綺良々のために作られた、 あの原神の <del>悩ましい</del> かわいいねこ。",
|
||||||
|
"counter-descriptions": "にゃー数",
|
||||||
|
"counter-button": "にゃー!",
|
||||||
|
"credits-gif": "感謝: Seseren_kr さんが提供してくれた綺良々のGIF画像",
|
||||||
|
"footer-repository-text": "こちらはこのページGitee (Mainland China) リポジトリ:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "感謝:duiqt さんが提供してくれたこのウェブサイトの基礎ソースコード",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_jp.jpg"
|
||||||
|
},
|
||||||
|
//英文语音、文本、海报
|
||||||
|
"en": {
|
||||||
|
audioList: [
|
||||||
|
//0-5:默认模式 mode1
|
||||||
|
"audio/CN_voice/嘿咻.mp3",
|
||||||
|
"audio/CN_voice/喵.mp3",
|
||||||
|
"audio/CN_voice/喵嗷.mp3",
|
||||||
|
"audio/CN_voice/挠你哦.mp3",
|
||||||
|
"audio/CN_voice/跳跃1.mp3",
|
||||||
|
"audio/CN_voice/跳跃2.mp3",
|
||||||
|
],
|
||||||
|
texts: {
|
||||||
|
"page-title": "Welcome to Kirara Miaow~ ",
|
||||||
|
"doc-title": "Miaomiaomiao~",
|
||||||
|
"page-descriptions": "The website for Kirara, an <del>annoying</del> very lovely Genshin Impact CAT out there.",
|
||||||
|
"counter-descriptions": ["The Kirara~ has been miaowed for", "Kirara has been miaow~ed for"],
|
||||||
|
"counter-button": "Miaow~",
|
||||||
|
"credits-gif": "Acknowledgment: GIF images of Kirara provided by Seseren_kr.",
|
||||||
|
"footer-repository-text": "You can check out the Gitee repository (Mainland China) here:",
|
||||||
|
"footer-repository-text-2": "原神主题网站代码仓库",
|
||||||
|
"footer-repository-text3": "Special thanks to duiqt for providing the source code for this website.",
|
||||||
|
"footer-repository-text-4": "Herta_kuru"
|
||||||
|
},
|
||||||
|
cardImage: "img/banner_en.jpg"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//设置语言选择器的文本语言
|
||||||
|
function refreshLanguageSelector(selectedLanguage) {
|
||||||
|
switch (selectedLanguage) {
|
||||||
|
case "cn":
|
||||||
|
document.getElementById("lan1").innerHTML = "🌏中文";
|
||||||
|
document.getElementById("lan2").innerHTML = "日文";
|
||||||
|
document.getElementById("lan3").innerHTML = "英文";
|
||||||
|
break;
|
||||||
|
case "ja":
|
||||||
|
document.getElementById("lan1").innerHTML = "中国語";
|
||||||
|
document.getElementById("lan2").innerHTML = "🌏日本語";
|
||||||
|
document.getElementById("lan3").innerHTML = "英語";
|
||||||
|
break;
|
||||||
|
case "en":
|
||||||
|
document.getElementById("lan1").innerHTML = "Chinese";
|
||||||
|
document.getElementById("lan2").innerHTML = "Japanese";
|
||||||
|
document.getElementById("lan3").innerHTML = "🌏English";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置模式选择器的文本语言
|
||||||
|
function refreshModeSelector(selectedLanguage) {
|
||||||
|
switch (selectedLanguage) {
|
||||||
|
case "cn":
|
||||||
|
document.getElementById("mode1").innerHTML = "默认模式";
|
||||||
|
// document.getElementById("mode2").innerHTML = "只要哒哒哒";
|
||||||
|
// document.getElementById("mode3").innerHTML = "隐藏彩蛋";
|
||||||
|
break;
|
||||||
|
case "ja":
|
||||||
|
document.getElementById("mode1").innerHTML = "デフォルトモード";
|
||||||
|
// document.getElementById("mode2").innerHTML = "ダダダだけ";
|
||||||
|
// document.getElementById("mode3").innerHTML = "ひみつ";
|
||||||
|
break;
|
||||||
|
case "en":
|
||||||
|
document.getElementById("mode1").innerHTML = "DefaultMode";
|
||||||
|
// document.getElementById("mode2").innerHTML = "Just Dadada";
|
||||||
|
// document.getElementById("mode3").innerHTML = "Easter egg";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//获取默认语言并赋值给语言选择框
|
||||||
|
var current_language = localStorage.getItem("lang") || "cn";
|
||||||
|
if (current_language != "cn") {
|
||||||
|
document.getElementById("language-selector").value = current_language;
|
||||||
|
};
|
||||||
|
|
||||||
|
//通过获取当前语言和对应的文本数组,遍历文本数组中的每个键值对。如果文本值是一个数组,就从数组中随机选择一个元素作为新的文本内容,并将其更新到对应的 HTML 元素中
|
||||||
|
function randomChoice(myArr) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * myArr.length);
|
||||||
|
const randomItem = myArr[randomIndex];
|
||||||
|
return randomItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
//核心函数!动态刷新动态文本内容(将新的DOM值渲染到前端)
|
||||||
|
function refreshDynamicTexts() {
|
||||||
|
let curLang = LANGUAGES[current_language];
|
||||||
|
let localTexts = curLang.texts;
|
||||||
|
Object.entries(localTexts).forEach(([textId, value]) => {
|
||||||
|
if (value instanceof Array)
|
||||||
|
if (document.getElementById(textId) != undefined)
|
||||||
|
document.getElementById(textId).innerHTML = randomChoice(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//定义函数:根据当前语言,渲染页面
|
||||||
|
function multiLangMutation() {
|
||||||
|
let curLang = LANGUAGES[current_language]; //获取当前的网站语言
|
||||||
|
let localTexts = curLang.texts; //获取当前语言的文本数组
|
||||||
|
Object.entries(localTexts).forEach(([textId, value]) => { //将各个DOM元素的值变为文本值
|
||||||
|
if (!(value instanceof Array))
|
||||||
|
if (document.getElementById(textId) != undefined)
|
||||||
|
document.getElementById(textId).innerHTML = value;
|
||||||
|
});
|
||||||
|
refreshDynamicTexts() //刷新动态文本内容(将新的DOM值渲染到前端)
|
||||||
|
document.getElementById("kirara-card").src = curLang.cardImage; //动态获取klee-card在当前语言文本环境下的Dom元素并更新
|
||||||
|
|
||||||
|
var selectedLanguage = document.getElementById("language-selector").value;
|
||||||
|
refreshLanguageSelector(selectedLanguage) //更新语言选择器的文本语言
|
||||||
|
refreshModeSelector(selectedLanguage) //更新模式选择器的文本语言
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
curLang 变量获取了当前选择的网站语言对应的语言对象(假设为 LANGUAGES 全局对象中的一个属性)。
|
||||||
|
localTexts 变量获取了当前语言对象中的文本数组。
|
||||||
|
使用 Object.entries() 方法遍历 localTexts 中的键值对。
|
||||||
|
对于每一个键值对,解构赋值为 [textId, value],其中 textId 是 DOM 元素的 ID,value 是对应的文本值。
|
||||||
|
首先检查 value 是否为数组,如果不是数组,表示是单个文本值(例如字符串)。
|
||||||
|
检查当前网页是否存在具有对应 textId 的 DOM 元素(通过 document.getElementById(textId) 来判断)。
|
||||||
|
如果存在对应的 DOM 元素,则将其内部的 HTML 内容更新为 value。
|
||||||
|
这样就实现了根据当前语言选择动态更新网页中的文本内容。
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
multiLangMutation() //初始化网站语言
|
||||||
|
|
||||||
|
//通过这段代码,当语言选择器的值发生变化时,会根据选择的语言重新渲染页面的文本内容和动态图片,实现动态调整网站语言的功能。
|
||||||
|
document.getElementById("language-selector").addEventListener("change", (ev) => {
|
||||||
|
current_language = ev.target.value;
|
||||||
|
localStorage.setItem("lang", ev.target.value);
|
||||||
|
multiLangMutation();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======================================================================【按钮点击、计数器】============================================
|
||||||
|
|
||||||
|
// 初始化计数器
|
||||||
|
//本地计数器
|
||||||
|
const localCounter = document.querySelector('#local-counter'); //获取展示本地点击数的DOM元素
|
||||||
|
let localCount = localStorage.getItem('count-local-kirara') || 0; //获取本地点击数的值
|
||||||
|
localCounter.textContent = localCount.toLocaleString('en-US'); //使用美式英语的格式进行格式化。这样可以确保数值以适当的方式显示,例如添加千位分隔符
|
||||||
|
|
||||||
|
|
||||||
|
let prevTime = 0;
|
||||||
|
|
||||||
|
//获取时间戳
|
||||||
|
const getTimestamp = () => Date.parse(new Date());
|
||||||
|
|
||||||
|
//点击喵呜的按钮事件
|
||||||
|
const counterButton = document.querySelector('#counter-button');
|
||||||
|
counterButton.addEventListener('click', (e) => {
|
||||||
|
prevTime = getTimestamp(); //当前时间
|
||||||
|
localCount++;
|
||||||
|
localStorage.setItem('count-local-kirara', localCount); //缓存localCount到本地
|
||||||
|
|
||||||
|
localCounter.textContent = localCount.toLocaleString('en-US');
|
||||||
|
|
||||||
|
triggerRipple(e); //按钮的水波纹效果
|
||||||
|
playMiaow(); //播放可莉语音
|
||||||
|
animateKirara(); //播放可莉动画
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================================【资源缓存】========================================================
|
||||||
|
var cachedObjects = {};
|
||||||
|
function tryCachedObject(origUrl) {
|
||||||
|
// 检查对象是否已经被缓存
|
||||||
|
if (cachedObjects[origUrl]) {
|
||||||
|
return cachedObjects[origUrl];
|
||||||
|
} else {
|
||||||
|
// 开始缓存
|
||||||
|
fetch(origUrl)
|
||||||
|
.then((response) => response.blob())
|
||||||
|
.then((blob) => {
|
||||||
|
// 为对象创建一个blob URL
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
// 通过在cachedObjects对象中存储blob URL来获取缓存的对象
|
||||||
|
cachedObjects[origUrl] = blobUrl;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(`Error caching object from ${origUrl}: ${error}`);
|
||||||
|
});
|
||||||
|
return origUrl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//缓存所有资源
|
||||||
|
function cacheAllResources() {
|
||||||
|
// 缓存图片资源
|
||||||
|
for (let i = 1; i < 3; i++) {
|
||||||
|
const imageUrl = `img/animation/${i}.gif`;
|
||||||
|
tryCachedObject(imageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存中文音频资源(含通用语音资源)
|
||||||
|
const cnAudioList = LANGUAGES.cn.audioList;
|
||||||
|
cnAudioList.forEach((audioUrl) => {
|
||||||
|
tryCachedObject(audioUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 缓存日文音频资源(含通用语音资源)
|
||||||
|
const jaAudioList = LANGUAGES.ja.audioList;
|
||||||
|
jaAudioList.forEach((audioUrl) => {
|
||||||
|
tryCachedObject(audioUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
//只需要执行一次该功能
|
||||||
|
firstLoadClick = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当页面加载完成后触发缓存资源
|
||||||
|
// var firstLoadClick = true;
|
||||||
|
// window.addEventListener('click', cacheAllResources);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================【按钮点击后的动画、音频】================================================
|
||||||
|
|
||||||
|
//返回当前语言的音频数组
|
||||||
|
function getLocalAudioList() {
|
||||||
|
return LANGUAGES[current_language].audioList;
|
||||||
|
};
|
||||||
|
//从音频数组中获取一个随机的音频URL(传入一个当前模式。curMode==mode1 默认模式,cueMode==mode3)
|
||||||
|
function getRandomAudioUrl(curMode) {
|
||||||
|
var localAudioList = getLocalAudioList()
|
||||||
|
|
||||||
|
//根据模式产生符合模式的音频下标
|
||||||
|
if (curMode == "mode1") {
|
||||||
|
randomIndex = Math.floor(Math.random() * 6); //默认语音的文件是:文件下标0-5.这儿的数字就写6.
|
||||||
|
}
|
||||||
|
// if (curMode == "mode3") {
|
||||||
|
// randomIndex = Math.floor(Math.random() * 17); //文件下标0-16.这儿的数字就写14. 【这儿写彩蛋对应的audioList下标】
|
||||||
|
// }
|
||||||
|
|
||||||
|
const randomItem = localAudioList[randomIndex];
|
||||||
|
return randomItem;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//播放音频
|
||||||
|
var isFirstVoice = true;
|
||||||
|
function playMiaow() {
|
||||||
|
|
||||||
|
//先获取当前的模式:1-默认;2-只哒哒哒;3-彩蛋
|
||||||
|
const modeSelectElement = document.getElementById("mode-selector");
|
||||||
|
const modeSelectedOption = modeSelectElement.options[modeSelectElement.selectedIndex];
|
||||||
|
const curMode = modeSelectedOption.id;
|
||||||
|
|
||||||
|
//要播放的音频Url
|
||||||
|
let audioUrl;
|
||||||
|
|
||||||
|
//根据当前模式获取符合模式语音的 AudioURL
|
||||||
|
switch (curMode) {
|
||||||
|
//curMode==mode1 默认模式
|
||||||
|
case "mode1": {
|
||||||
|
if (isFirstVoice == true) {//随机获取一个音频的URL,第一个必定是哒哒哒
|
||||||
|
isFirstVoice = false;
|
||||||
|
audioUrl = getLocalAudioList()[1] //First play fixed Dadada
|
||||||
|
} else {
|
||||||
|
audioUrl = getRandomAudioUrl(curMode);
|
||||||
|
}
|
||||||
|
}; break;
|
||||||
|
|
||||||
|
//curMode==mode2 只哒哒哒
|
||||||
|
case "mode2": {
|
||||||
|
audioUrl = getLocalAudioList()[1]
|
||||||
|
}; break;
|
||||||
|
|
||||||
|
//cueMode==mode3 彩蛋
|
||||||
|
case "mode3": {
|
||||||
|
if (isFirstVoice == true) {//随机获取一个音频的URL,第一个必定是哒哒哒
|
||||||
|
isFirstVoice = false;
|
||||||
|
audioUrl = getLocalAudioList()[1] //First play fixed Dadada
|
||||||
|
} else {
|
||||||
|
audioUrl = getRandomAudioUrl(curMode);
|
||||||
|
}
|
||||||
|
}; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//根据音频URL从本地获取音频资源。同时将该音频缓存到本地
|
||||||
|
let audio = new Audio(tryCachedObject(audioUrl)); //【缓存貌似可以删除】
|
||||||
|
|
||||||
|
//播放音频后监听音频结束事件,并在音频播放结束时将音频元素从 DOM 中移除
|
||||||
|
audio.play();
|
||||||
|
audio.addEventListener("ended", function () {
|
||||||
|
this.remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function animateKirara() {
|
||||||
|
let id = null;
|
||||||
|
|
||||||
|
const random = Math.floor(Math.random() * 1) + 1; //1-1,GIF
|
||||||
|
const elem = document.createElement("img");
|
||||||
|
elem.src = tryCachedObject(`img/animation/${random}.gif`);
|
||||||
|
|
||||||
|
//下面根据不同的窗口改变可莉动画的样式(响应式)
|
||||||
|
const screenWidth = window.innerWidth;
|
||||||
|
|
||||||
|
if (screenWidth > 768) {
|
||||||
|
elem.style.position = "absolute";
|
||||||
|
elem.style.right = "-500px";
|
||||||
|
elem.style.top = counterButton.getClientRects()[0].bottom + scrollY - 430 + "px"
|
||||||
|
elem.style.zIndex = "-10";
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
|
||||||
|
let pos = -500;
|
||||||
|
const limit = window.innerWidth + 500;
|
||||||
|
clearInterval(id);
|
||||||
|
id = setInterval(() => {
|
||||||
|
if (pos >= limit) {
|
||||||
|
clearInterval(id);
|
||||||
|
elem.remove()
|
||||||
|
} else {
|
||||||
|
pos += 20;
|
||||||
|
elem.style.right = pos + 'px';
|
||||||
|
}
|
||||||
|
}, 12);
|
||||||
|
} else {
|
||||||
|
//移动端,把动画变小、变慢一点
|
||||||
|
elem.style.position = "absolute";
|
||||||
|
elem.style.right = "-500px";
|
||||||
|
elem.style.top = counterButton.getClientRects()[0].bottom + scrollY - 180 + "px"
|
||||||
|
elem.style.zIndex = "-10";
|
||||||
|
elem.style.width = "250px"; // 设置宽度为 200px(让移动端方便观看)
|
||||||
|
elem.style.height = "auto"; // 自动计算高度,保持纵横比
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
|
||||||
|
let pos = -500;
|
||||||
|
const limit = window.innerWidth + 500;
|
||||||
|
clearInterval(id);
|
||||||
|
id = setInterval(() => {
|
||||||
|
if (pos >= limit) {
|
||||||
|
clearInterval(id);
|
||||||
|
elem.remove()
|
||||||
|
} else {
|
||||||
|
pos += 10;
|
||||||
|
elem.style.right = pos + 'px';
|
||||||
|
}
|
||||||
|
}, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//点击 counter-button 元素时,会在点击位置出现一个水波纹效果。
|
||||||
|
function triggerRipple(e) {
|
||||||
|
let ripple = document.createElement("span");
|
||||||
|
|
||||||
|
ripple.classList.add("ripple");
|
||||||
|
|
||||||
|
const counter_button = document.getElementById("counter-button");
|
||||||
|
counter_button.appendChild(ripple);
|
||||||
|
|
||||||
|
let x = e.clientX - e.target.offsetLeft;
|
||||||
|
let y = e.clientY - e.target.offsetTop;
|
||||||
|
|
||||||
|
ripple.style.left = `${x}px`;
|
||||||
|
ripple.style.top = `${y}px`;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
ripple.remove();
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================================【全球计数器】======================================
|
||||||
|
//算法思路:先前的项目已经实现了永久保存本地计数。接下来要实现统计全球技术:
|
||||||
|
//1.为了节省流量,规定每一分钟自动上传一次【本次点击数】(定义一个区别于 localCount 的新变量 thisTimeCount)
|
||||||
|
//2.发送Ajax,发送 thisTimeCount 服务端返回 globalCount渲染到页面,同时将本地的 thisTimeCount 清零
|
||||||
|
|
||||||
|
|
||||||
|
var thisTimeCounts = 0; //本次轮询Ajax之前的点击数
|
||||||
|
var intervalID = setInterval(updateGlobalCount, 15000);//间隔多久上传一次,单位ms
|
||||||
|
|
||||||
|
//点击一次按钮,thisTimeCount++
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#counter-button').click(function () {
|
||||||
|
thisTimeCounts++ //本次定时轮询Ajax之前的点击数 +1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//上传数据
|
||||||
|
function updateGlobalCount() {
|
||||||
|
$.ajax({
|
||||||
|
url: './kirara.php',
|
||||||
|
method: 'POST',
|
||||||
|
async: false,
|
||||||
|
data: { localcount: thisTimeCounts },
|
||||||
|
success: function(response) {
|
||||||
|
// 处理成功响应
|
||||||
|
console.log(response);
|
||||||
|
thisTimeCounts = 0;
|
||||||
|
$('#local-counter').text(localCount);
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
// 处理错误响应
|
||||||
|
console.error("请求失败: " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//首次访问网站的时候,立即获取 globalCounts并刷新 (页面加载完成后立即执行)
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
$.ajax({
|
||||||
|
url: './kirara.php',
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
headers: {
|
||||||
|
'ajax-requests': 'true'
|
||||||
|
},
|
||||||
|
/*data: {
|
||||||
|
thistimecountFromFront: thisTimeCounts, //将前端的 thisTimeCount 传给后端,参数名为 thistimecountFromFront
|
||||||
|
},*/
|
||||||
|
success: function (response) {
|
||||||
|
var globalcount = response[0].globalcount;
|
||||||
|
//console.log(response);
|
||||||
|
console.log("初始化成功,globalcountsFromBackend = " + globalcount)
|
||||||
|
var globalCountElement = document.getElementById("global-counter");
|
||||||
|
globalCountElement.textContent = (globalcount).toLocaleString('en-US')
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 定时轮询后端获取 globalCounts
|
||||||
|
setInterval(function () {
|
||||||
|
$.ajax({
|
||||||
|
url: './kirara.php',
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
headers: {
|
||||||
|
'ajax-requests': 'true'
|
||||||
|
},
|
||||||
|
//type: 'text',
|
||||||
|
/*data: {
|
||||||
|
thistimecountFromFront: thisTimeCounts, //将前端的 thisTimeCount 传给后端,参数名为 thistimecountFromFront
|
||||||
|
},*/
|
||||||
|
success: function (response) {
|
||||||
|
var globalcount = response[0].globalcount;
|
||||||
|
console.log("前端收到了后端返回的全球计数 = " + globalcount)
|
||||||
|
|
||||||
|
//thisTimeCounts = 0; //将前端本地点击数清零
|
||||||
|
|
||||||
|
var globalCountElement = document.getElementById("global-counter"); //获取全球计数器DOM
|
||||||
|
globalCountElement.textContent = (globalcount).toLocaleString('en-US') //更新全球计数器的值
|
||||||
|
|
||||||
|
},
|
||||||
|
error: function (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 5000); // 每5s执行一次
|
||||||
|
|
||||||
@@ -0,0 +1,479 @@
|
|||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
/* disable double_tap zoom on mobile devices */
|
||||||
|
-ms-touch-action: manipulation;
|
||||||
|
touch-action: manipulation;
|
||||||
|
/* strange margin-right occurs when vw<500px */
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* 底部颜色 */
|
||||||
|
background-color: rgba(233, 233, 233);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", 'Roboto', sans-serif;
|
||||||
|
font-size: 1.5em;
|
||||||
|
/* 顶部文字颜色 */
|
||||||
|
color: #553b07;
|
||||||
|
/* 禁用右键和选中 */
|
||||||
|
-webkit-user-select: none;
|
||||||
|
/* Chrome, Safari, Opera */
|
||||||
|
-moz-user-select: none;
|
||||||
|
/* Firefox */
|
||||||
|
-ms-user-select: none;
|
||||||
|
/* Internet Explorer/Edge */
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 欢迎页面 */
|
||||||
|
#welcome-page {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(192, 157, 69, 0.8);
|
||||||
|
color: rgb(19, 19, 19);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcome-page img {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 功能区大盒子 */
|
||||||
|
.buttons-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 8888;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 播放按钮 */
|
||||||
|
.volume-control {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: rgba(22, 21, 21, 0.5);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
/* 按钮和右边按钮间隔20px */
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-control:hover {
|
||||||
|
background-color: #e5e2e2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-image: url("./img/volume_icon.png");
|
||||||
|
background-size: cover;
|
||||||
|
animation: rotate-icon 5s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate-icon {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper-background {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-image: url("img/background.gif");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 50%;
|
||||||
|
background-size: contain;
|
||||||
|
z-index: -30;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper-background-filter {
|
||||||
|
/* 背景颜色 */
|
||||||
|
background-color: rgba(175, 162, 44, 0.9);
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preload {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
margin: 2vh auto;
|
||||||
|
width: 80vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 3em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
/* 分割线 */
|
||||||
|
border-bottom: 6px dashed rgb(68, 51, 5);
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-title {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* logo */
|
||||||
|
#title-img {
|
||||||
|
height: 3.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0% {
|
||||||
|
transform: rotate(-5deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(5deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(-5deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shake {
|
||||||
|
animation: shake 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container select {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language-selector,
|
||||||
|
#mode-selector {
|
||||||
|
width: 200px;
|
||||||
|
height: 40px;
|
||||||
|
/* 选择框颜色 */
|
||||||
|
background-color: #ebe4a3;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
text-align-last: center;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 10px;
|
||||||
|
color: rgb(38, 36, 36);
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language-selector:hover,
|
||||||
|
#mode-selector:hover {
|
||||||
|
box-shadow: 0 0 10px #756d1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#language-selector option {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #ebe4a3;
|
||||||
|
color: rgb(118, 114, 114);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-container {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 64px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-container>p {
|
||||||
|
text-shadow: #975a13 0 0 10px, #975a13 0 0 10px, #975a13 0 0 10px, #975a13 0 0 10px, #975a13 0 0 10px;
|
||||||
|
}
|
||||||
|
/* 全球计数器文字颜色 */
|
||||||
|
#global-counter {
|
||||||
|
color: #211e04;
|
||||||
|
font-size: 4em;
|
||||||
|
text-shadow:
|
||||||
|
-1px -1px 0 black,
|
||||||
|
1px -1px 0 black,
|
||||||
|
-1px 1px 0 black,
|
||||||
|
1px 1px 0 black; /* 描边效果 */
|
||||||
|
}
|
||||||
|
/* 本地计数器文字颜色 */
|
||||||
|
#local-counter {
|
||||||
|
color: #2e2c2c;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button {
|
||||||
|
/* 动画触发按钮颜色 */
|
||||||
|
background-color: #4d4813;
|
||||||
|
border: none;
|
||||||
|
border-radius: 16px;
|
||||||
|
color: rgb(236, 193, 105);
|
||||||
|
padding: 16px 32px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 1em;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 6px 7px 40px -4px rgba(43, 42, 42, 0.2);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.1s ease-in-out, scale 0.1s cubic-bezier(0.075, 0.82, 0.165, 1);
|
||||||
|
}
|
||||||
|
/* 动画触发按钮的悬挂颜色 */
|
||||||
|
#counter-button:hover {
|
||||||
|
background-color: #3a3608;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button:active {
|
||||||
|
scale: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
#counter-button span {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff50;
|
||||||
|
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
margin-top: -50px;
|
||||||
|
margin-left: -50px;
|
||||||
|
|
||||||
|
animation: ripple 1s;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ripple {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
background-color: rgb(253, 250, 244);
|
||||||
|
color: black;
|
||||||
|
padding: 16px 10vw;
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* kirara banner 图片样式 */
|
||||||
|
#kirara-card {
|
||||||
|
min-width: 256px;
|
||||||
|
max-width: 720px;
|
||||||
|
height: auto;
|
||||||
|
border-top-left-radius: 2% 3.5%;
|
||||||
|
border-top-right-radius: 2% 3.5%;
|
||||||
|
border-bottom-left-radius: 2% 3.5%;
|
||||||
|
border-bottom-right-radius: 2% 3.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-icon {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#twitter-footer-icon {
|
||||||
|
color: #1d9bf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#github-footer-icon {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-icon-text {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #footer-repository-text {
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
@media screen and (max-width: 2240px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(20% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1920px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(25% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1512px) {
|
||||||
|
body {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1280px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(100% / 3 - 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-text {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-header-text {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-repository-text {
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1265px) {
|
||||||
|
body {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 854px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(20% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 510px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
.grid-item {
|
||||||
|
width: calc(100% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 430px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subtitle-seperator {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#access-via-mirror,
|
||||||
|
#access-via-pages {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||