![]()
💬 开场白
“`html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>恐怖世界选择器</title>
</head>
<body>
<style>
/* 引入外部字体 */
@import url('https://fonts.googleapis.com/css2?family=DotGothic16&family=Shippori+Mincho:wght@400;700&display=swap');/* — 变量定义 — */
:root {
–font-jp-serif: 'Shippori Mincho', serif; /* 日式明朝体,用于标题和正文 */
–font-jp-pixel: 'DotGothic16', sans-serif; /* 像素风字体,用于按钮和标签 */
–bg-color: #1a1a1a; /* 深邃的黑色背景 */
–main-container-bg: #100c0c; /* 主容器背景,略带血色 */
–text-color: #a9a9a9; /* 主要文本颜色,陈旧的灰色 */
–primary-color: #b71c1c; /* 主题色,干涸的血红色 */
–primary-color-light: #d32f2f;
–border-color: #424242; /* 边框颜色 */
–shadow-color: rgba(183, 28, 28, 0.4); /* 阴影颜色 */
}/* — 整体布局 — */
.horror-selector-container {
font-family: var(–font-jp-serif);
background-color: var(–main-container-bg);
color: var(–text-color);
width: 100%;
max-width: 800px;
margin: 20px auto;
border: 1px solid var(–border-color);
border-radius: 4px;
box-shadow: 0 0 25px var(–shadow-color), inset 0 0 10px rgba(0,0,0,0.5);
padding: 25px;
position: relative;
overflow: hidden; /* 隐藏漂浮物溢出部分 */
}/* — 漂浮物装饰 — */
.floating-elements {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none; /* 让装饰物不影响点击 */
z-index: 0;
}.floating-elements .particle {
position: absolute;
color: var(–primary-color);
opacity: 0.3;
font-size: 1.2rem;
animation: float 20s infinite linear;
}
/* 为每个漂浮物设置不同的动画延迟和位置 */
.particle-1 { top: 20%; left: 10%; animation-delay: -2s; }
.particle-2 { top: 50%; left: 80%; animation-delay: -5s; font-size: 1.5rem; }
.particle-3 { top: 80%; left: 25%; animation-delay: -10s; }
.particle-4 { top: 10%; left: 90%; animation-delay: -15s; }
.particle-5 { top: 90%; left: 5%; animation-delay: -8s; font-size: 1rem; }
.particle-6 { top: 5%; left: 40%; animation-delay: -12s; }@keyframes float {
0% { transform: translateY(0px) translateX(0px) rotate(0deg); }
50% { transform: translateY(-20px) translateX(10px) rotate(180deg); opacity: 0.6; }
100% { transform: translateY(0px) translateX(0px) rotate(360deg); }
}/* — 标签页切换 — */
.tab-container {
display: flex;
border-bottom: 2px solid var(–primary-color);
margin-bottom: 25px;
position: relative;
z-index: 1;
}.tab-button {
font-family: var(–font-jp-pixel);
padding: 10px 20px;
cursor: pointer;
background: transparent;
border: none;
color: var(–text-color);
font-size: 1.1rem;
position: relative;
transition: color 0.3s ease;
}.tab-button.active {
color: #fff;
text-shadow: 0 0 8px var(–primary-color);
}.tab-button::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 100%;
height: 2px;
background-color: #fff;
transform: scaleX(0);
transition: transform 0.3s ease;
}.tab-button.active::after {
transform: scaleX(1);
}.tab-content {
display: none;
animation: fadeIn 0.6s;
position: relative;
z-index: 1;
}.tab-content.active {
display: block;
}@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}/* — 内容区域样式 — */
.content-wrapper {
border: 1px dashed var(–border-color);
padding: 20px;
background-color: rgba(0,0,0,0.2);
}.section-title {
font-family: var(–font-jp-pixel);
font-size: 1.5rem;
font-weight: 700;
color: #f5f5f5;
margin-bottom: 15px;
text-align: center;
letter-spacing: 2px;
border-bottom: 1px solid var(–border-color);
padding-bottom: 10px;
}/* — 按钮样式 — */
.horror-btn {
font-family: var(–font-jp-pixel);
background-color: transparent;
border: 1px solid var(–primary-color);
color: var(–primary-color);
padding: 12px 25px;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
display: block;
width: 100%;
margin-top: 15px;
text-align: center;
}.horror-btn:hover {
background-color: var(–primary-color);
color: var(–main-container-bg);
box-shadow: 0 0 15px var(–shadow-color);
}.horror-btn:disabled {
border-color: var(–border-color);
color: var(–border-color);
cursor: not-allowed;
background-color: transparent;
}
.horror-btn:disabled:hover {
box-shadow: none;
}/* — 随机选择器样式 — */
.random-selector .step, .custom-selector .step {
margin-bottom: 20px;
}
.step-label {
display: block;
margin-bottom: 10px;
font-size: 1.1rem;
color: #e0e0e0;
}
.result-display {
background-color: #000;
border: 1px solid var(–border-color);
padding: 10px;
min-height: 24px;
text-align: center;
font-family: var(–font-jp-pixel);
color: var(–primary-color-light);
transition: all 0.3s ease;
}/* — 自定义输入样式 — */
.custom-input {
width: 100%;
background: #000;
border: 1px solid var(–border-color);
color: var(–text-color);
padding: 10px;
font-family: var(–font-jp-serif);
font-size: 1rem;
box-sizing: border-box;
transition: border-color 0.3s, box-shadow 0.3s;
}
.custom-input:focus {
outline: none;
border-color: var(–primary-color);
box-shadow: 0 0 8px var(–shadow-color);
}/* — 互动气泡 — */
.feedback-bubble {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(183, 28, 28, 0.9);
color: #fff;
padding: 10px 20px;
border-radius: 20px;
font-family: var(–font-jp-pixel);
z-index: 1000;
opacity: 0;
transition: opacity 0.5s, transform 0.5s;
pointer-events: none;
}
.feedback-bubble.show {
opacity: 1;
transform: translateX(-50%) translateY(-20px);
}</style>
<div class="horror-selector-container">
<!– 漂浮的装饰性汉字 –>
<div class="floating-elements">
<span class="particle particle-1">呪</span>
<span class="particle particle-2">怨</span>
<span class="particle particle-3">死</span>
<span class="particle particle-4">怪</span>
<span class="particle particle-5">霊</span>
<span class="particle particle-6">忌</span>
</div><!– 标签页切换按钮 –>
<div class="tab-container">
<button class="tab-button active" onclick="switchTab(event, 'random')">【 運命ノ選択 】</button>
<button class="tab-button" onclick="switchTab(event, 'custom')">【 禁忌ノ創造 】</button>
</div><!– 标签页内容:随机选择 –>
<div id="random" class="tab-content active">
<div class="content-wrapper random-selector">
<div class="section-title">運命の選択</div>
<!– 步骤一:选择分类 –>
<div class="step">
<label class="step-label">壱:怪異の種類 (怪异的种类)</label>
<button id="random-category-btn" class="horror-btn" onclick="randomizeCategory()">▷ 分類を無作為に選ぶ (随机选择分类)</button>
<div id="category-result" class="result-display"></div>
</div>
<!– 步骤二:随机IP –>
<div class="step">
<label class="step-label">弐:恐怖の源 (恐怖之源)</label>
<button id="random-selection-btn" class="horror-btn" onclick="randomizeSelection()" disabled>▷ 源を無作為に選ぶ (随机选择源头)</button>
<div id="selection-result" class="result-display"></div>
</div>
<!– 步骤三:选择恐怖等级 –>
<div class="step">
<label class="step-label">参:恐怖の深度 (恐怖的深度)</label>
<button id="random-level-btn" class="horror-btn" onclick="randomizeLevel()" disabled>▷ 深度を無作為に選ぶ (随机选择深度)</button>
<div id="level-result" class="result-display"></div>
</div>
</div>
</div><!– 标签页内容:自定义 –>
<div id="custom" class="tab-content">
<div class="content-wrapper custom-selector">
<div class="section-title">禁忌の創造</div>
<!– 输入一 –>
<div class="step">
<label class="step-label">要素・壱:</label>
<input type="text" id="custom-input-1" class="custom-input" placeholder="例:廃病院 (废弃医院)">
</div>
<!– 输入二 –>
<div class="step">
<label class="step-label">要素・弐:</label>
<input type="text" id="custom-input-2" class="custom-input" placeholder="例:人形 (人偶)">
</div>
<!– 输入三 –>
<div class="step">
<label class="step-label">要素・参:</label>
<input type="text" id="custom-input-3" class="custom-input" placeholder="例:鏡 (镜子)">
</div>
</div>
</div><!– 最终提交按钮 –>
<button id="submit-btn" class="horror-btn" onclick="enterWorld()" disabled>世界へ入る (进入世界)</button><!– 互动反馈气泡 –>
<div id="feedback-bubble" class="feedback-bubble"></div>
</div><script>
// — 数据存储 —
const horrorData = {
"映画": ["午夜凶铃", "咒怨", "鬼来电", "鬼水怪谈", "灵异咒", "感染", "怪谈", "切肤之爱", "回路", "预言", "裂口女", "轮回", "东瀛鬼咒", "富江", "东京大学恐怖故事", "嗤う虫", "事故物件ゾク 恐い间取り", "人偶之家", "双生", "暗黑童话", "禁忌之爱", "咒术回战:怀玉篇", "再见了,橡果兄弟!", "贞子3D", "鬼女魔咒", "感染列岛", "寄生兽", "告白", "楢山节考"],
"都市伝説": ["裂口女", "如月车站", "厕所里的花子", "八尺大人", "骨女", "雪女", "无耳芳一", "黑少女", "赤舌", "青鬼", "吸血女", "飞头蛮", "桥姬", "二口女", "野槌蛇", "高女", "犬神", "狐仙", "古币", "隧道怪谈", "二宫金次郎铜像怪谈", "二十二号置物柜怪谈", "二重身", "人面犬", "地下体育馆的幽灵", "四角落的怪谈", "四点四十四分的怪谈", "红纸、蓝纸", "无头骑士"],
"妖怪と鬼": ["裂口女", "雪女", "二口女", "络新妇", "酒吞童子", "九尾妖狐玉藻前", "崇德上皇", "滑头鬼", "猫又", "青坊主", "天狗", "大太法师", "木灵", "山姥", "山童", "一目小僧", "鵺", "手长足长", "河童", "牛鬼", "濡女", "海坊主", "舟幽灵", "桥姬", "川姬", "产女", "大首", "赤舌", "镰鼬"]
};
const levels = ["微恐", "中恐", "重恐"];
const categories = Object.keys(horrorData);
let currentMode = 'random';
let selections = { category: null, selection: null, level: null };// — 交互逻辑 —
// 标签页切换
function switchTab(evt, mode) {
currentMode = mode;
const tabContents = document.getElementsByClassName("tab-content");
for (let i = 0; i < tabContents.length; i++) {
tabContents[i].classList.remove("active");
}
const tabButtons = document.getElementsByClassName("tab-button");
for (let i = 0; i < tabButtons.length; i++) {
tabButtons[i].classList.remove("active");
}
document.getElementById(mode).classList.add("active");
evt.currentTarget.classList.add("active");
updateSubmitButtonState(); // 切换时更新提交按钮状态
}// 随机选择分类
function randomizeCategory() {
const categoryResult = document.getElementById('category-result');
const randomCategory = categories[Math.floor(Math.random() * categories.length)];
selections.category = randomCategory;
categoryResult.textContent = randomCategory;
showFeedback(`分類が選ばれました:${randomCategory}`);
// 启用下一步按钮
document.getElementById('random-selection-btn').disabled = false;
// 重置后续选择
resetSelection(false, true, true);
}// 随机选择IP
function randomizeSelection() {
if (!selections.category) return;
const selectionResult = document.getElementById('selection-result');
const list = horrorData[selections.category];
const randomSelection = list[Math.floor(Math.random() * list.length)];
selections.selection = randomSelection;
selectionResult.textContent = randomSelection;
showFeedback(`源が選ばれました:${randomSelection}`);
// 启用下一步按钮
document.getElementById('random-level-btn').disabled = false;
// 重置后续选择
resetSelection(false, false, true);
}// 随机选择恐怖等级
function randomizeLevel() {
const levelResult = document.getElementById('level-result');
const randomLevel = levels[Math.floor(Math.random() * levels.length)];
selections.level = randomLevel;
levelResult.textContent = randomLevel;
showFeedback(`深度が選ばれました:${randomLevel}`);
updateSubmitButtonState();
}// 重置选择
function resetSelection(cat, sel, lvl) {
if (cat) {
selections.category = null;
document.getElementById('category-result').textContent = '';
document.getElementById('random-selection-btn').disabled = true;
}
if (sel) {
selections.selection = null;
document.getElementById('selection-result').textContent = '';
document.getElementById('random-level-btn').disabled = true;
}
if (lvl) {
selections.level = null;
document.getElementById('level-result').textContent = '';
}
updateSubmitButtonState();
}// 更新提交按钮状态
function updateSubmitButtonState() {
const submitBtn = document.getElementById('submit-btn');
if (currentMode === 'random') {
submitBtn.disabled = !(selections.category && selections.selection && selections.level);
} else { // custom mode
const input1 = document.getElementById('custom-input-1').value.trim();
const input2 = document.getElementById('custom-input-2').value.trim();
const input3 = document.getElementById('custom-input-3').value.trim();
submitBtn.disabled = !(input1 || input2 || input3);
}
}
// 为自定义输入框添加监听,以便实时更新按钮状态
document.getElementById('custom-input-1').addEventListener('input', updateSubmitButtonState);
document.getElementById('custom-input-2').addEventListener('input', updateSubmitButtonState);
document.getElementById('custom-input-3').addEventListener('input', updateSubmitButtonState);// 进入世界
function enterWorld() {
let payload = {};
if (currentMode === 'random') {
payload = {
mode: 'random',
category: selections.category,
selection: selections.selection,
level: selections.level
};
} else {
payload = {
mode: 'custom',
custom_input_1: document.getElementById('custom-input-1').value.trim(),
custom_input_2: document.getElementById('custom-input-2').value.trim(),
custom_input_3: document.getElementById('custom-input-3').value.trim()
};
}const payloadJson = JSON.stringify(payload);
const command = `/send 进入世界 ${payloadJson} | /trigger`;if (typeof triggerSlash === 'function') {
showFeedback("世界への扉が開いています…");
triggerSlash(command);
} else {
console.warn("SillyTavern's triggerSlash function is not available.");
alert("命令已生成,请查看控制台。");
console.log(command);
}
}// 显示互动反馈气泡
function showFeedback(message) {
const bubble = document.getElementById('feedback-bubble');
bubble.textContent = message;
bubble.classList.add('show');
setTimeout(() => {
bubble.classList.remove('show');
}, 2000);
}</script>
</body>
</html>
“`