![]()
🎭 角色简介
name: 李玄,字景行
(Li Xuan, Courtesy Name: Jǐng Xíng)
appearance: 19岁 | 身高约六尺(约182cm) | 身形清瘦挺拔,介于少年与青年之间 | 乌发如墨,以一支温润的白玉簪束起,发丝顺滑垂落肩头 | 凤眼,眼型狭长,眼尾微微上挑,…
💬 开场白
“`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>
<style>
/* — Google Fonts — */
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600;700&family=Zhi+Mang+Xing&display=swap');:root {
–bg-color: #EFEBE5; /* 宣纸背景色 */
–text-color: #3D352E; /* 墨黑色 */
–accent-red: #B91C1C; /* 宫墙红 */
–accent-gold: #B8860B; /* 暗金 */
–token-bg: #2F2A26; /* 令牌背景 */
–token-border: #b39a70;
–token-hover-glow: rgba(234, 192, 134, 0.4);
–white-text: #EFEBE5; /* 令牌上的文字颜色 */
}/* — Base & Scrollbar — */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}html { scroll-behavior: smooth; }
body {
background-color: var(–bg-color);
color: var(–text-color);
font-family: 'Noto Serif SC', serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
opacity: 0;
animation: fadeInBody 2s 2.5s forwards;
}@keyframes fadeInBody { to { opacity: 1; } }
/* — Loading Animation (Ink Wash) — */
#ink-overlay {
position: fixed; top: 0; left: 0;
width: 100vw; height: 100vh;
background-color: var(–bg-color);
z-index: 10000;
display: flex; justify-content: center; align-items: center;
pointer-events: none;
animation: fadeOutOverlay 2s 2s forwards;
}
#ink-spot {
width: 10px; height: 10px;
border-radius: 50%;
background-color: #1a1a1a;
transform: scale(0);
filter: blur(2px);
animation: inkSpread 2.5s cubic-bezier(0.23, 1, 0.32, 1) forwards;
}@keyframes inkSpread {
0% { transform: scale(1); filter: blur(2px); opacity: 1; }
80% { transform: scale(350); filter: blur(25px); opacity: 0.4; }
100% { transform: scale(400); filter: blur(35px); opacity: 0; }
}@keyframes fadeOutOverlay { to { opacity: 0; } }
/* — Staggered Fade-in Animation — */
@keyframes subtle-fade-in-up {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}.main-container {
width: 100%; max-width: 720px;
margin: 0 auto;
padding: 1.5rem;
}/* — Music Player — */
.music-player-wrapper {
position: sticky; top: 10px; z-index: 100;
margin-bottom: 2rem;
display: flex; justify-content: center;
animation: subtle-fade-in-up 1.2s ease-out 2.6s backwards;
}
.music-player {
width: 90%; max-width: 360px;
background: rgba(248, 245, 239, 0.85);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid var(–accent-gold); border-radius: 50px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
display: flex; align-items: center; padding: 8px 15px;
}
.play-button {
width: 36px; height: 36px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><g fill="%23B8860B"><path d="M50,10.5c-21.8,0-39.5,17.7-39.5,39.5S28.2,89.5,50,89.5S89.5,71.8,89.5,50S71.8,10.5,50,10.5z M50,83.5 c-18.5,0-33.5-15-33.5-33.5S31.5,16.5,50,16.5S83.5,31.5,83.5,50S68.5,83.5,50,83.5z"/><path class="play-icon-shape" d="M42,35.5v28l22-14L42,35.5z"/><g class="pause-icon-shapes" style="opacity:0;"><rect x="36" y="35" width="8" height="28"/><rect x="54" y="35" width="8" height="28"/></g></g></svg>');
background-size: contain; background-position: center; background-repeat: no-repeat;
cursor: pointer; transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
flex-shrink: 0; border: none; background-color: transparent;
}
.play-button.playing { transform: rotate(90deg); }
.song-info { flex-grow: 1; text-align: center; padding: 0 15px; overflow: hidden; white-space: nowrap; }
.song-title { font-size: 1rem; font-weight: 600; color: var(–text-color); }
#progress-bar { width: 100%; height: 3px; background-color: rgba(184, 134, 11, 0.2); margin-top: 5px; position: relative; cursor: pointer; }
#progress-fill { height: 100%; background-color: var(–accent-red); width: 0%; border-radius: 3px; position: absolute; }/* — Character Visual Section — */
.character-visual {
text-align: center; margin-bottom: 2rem;
opacity: 0; transform: translateY(20px);
animation: subtle-fade-in-up 1.2s ease-out 2.8s forwards;
}
.character-image-container {
position: relative; display: inline-block;
border: 1px solid var(–token-border); padding: 5px;
background-color: var(–token-bg);
box-shadow: 0 10px 25px rgba(0,0,0,0.25);
}
.character-image {
max-width: 320px; width: 100%; height: auto;
display: block; position: relative; z-index: 1;
}
.character-image-container::after {
content: ''; position: absolute; bottom: -5px; left: 10%; right: 10%;
height: 60px;
background: radial-gradient(ellipse at bottom, rgba(185, 28, 28, 0.4) 0%, transparent 70%);
filter: blur(18px); z-index: -1;
}/* — Character Intro — */
.character-intro {
text-align: center; margin-bottom: 3rem;
opacity: 0; transform: translateY(20px);
animation: subtle-fade-in-up 1.2s ease-out 3s forwards;
}
.character-title {
font-family: 'Zhi Mang Xing', cursive;
font-size: 3rem; color: var(–accent-red);
font-weight: normal; margin-bottom: 1rem;
}
.character-tagline { font-size: 1.05rem; color: #555; max-width: 500px; margin: 0 auto; line-height: 1.8; font-style: italic; }/* — Opening Selection — */
.opening-selection {
opacity: 0; transform: translateY(20px);
animation: subtle-fade-in-up 1.2s ease-out 3.2s forwards;
}
.opening-selection-title {
text-align: center; font-size: 1.3rem; font-weight: 600; margin-bottom: 2rem; color: #444; position: relative;
}
.opening-selection-title::before, .opening-selection-title::after {
content: ''; position: absolute; top: 50%; width: 25%; height: 1px;
background: linear-gradient(to right, transparent, var(–accent-gold), transparent);
}
.opening-selection-title::before { left: 0; background: linear-gradient(to right, transparent, var(–accent-gold)); }
.opening-selection-title::after { right: 0; background: linear-gradient(to left, transparent, var(–accent-gold)); }.token-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 640px) {
.token-grid { grid-template-columns: 1fr 1fr; }
}.token {
background: var(–token-bg); color: var(–white-text);
border: 1px solid var(–token-border); border-radius: 8px;
padding: 1.5rem; text-align: center; cursor: pointer;
transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
position: relative; overflow: hidden; box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
.token:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 12px 30px var(–token-hover-glow); }
.token-header { display: flex; align-items: center; justify-content: center; margin-bottom: 1rem; }
.token-number {
font-family: 'Zhi Mang Xing', cursive; font-size: 1.5rem; color: var(–accent-red);
border: 1px solid var(–accent-red); border-radius: 50%;
width: 30px; height: 30px;
display: flex; align-items: center; justify-content: center;
margin-right: 12px; font-weight: normal; flex-shrink: 0;
}
.token-number.custom-num {
font-size: 1.1rem; border: none; width: auto; height: auto;
font-family: 'Noto Serif SC', serif; font-weight: 600;
}
.token-title { font-size: 1.15rem; font-weight: 600; color: var(–white-text); }
.token-description { font-size: 0.88rem; line-height: 1.7; color: #bcaaa4; margin-bottom: 1.5rem; min-height: 80px; }
.token-button {
display: inline-block; font-size: 0.9rem; font-weight: bold;
color: var(–accent-red); border: 1px solid var(–accent-red);
padding: 8px 18px; border-radius: 20px;
transition: all 0.3s ease; background: transparent;
}
.token:hover .token-button { background: var(–accent-red); color: var(–token-bg); }
.token-tassel { position: absolute; top: 15px; right: 15px; width: 2px; height: 10px; background-color: var(–accent-gold); opacity: 0.7; }
.token-tassel::before { content: ''; position: absolute; bottom: 100%; left: -2px; width: 6px; height: 4px; background: var(–accent-gold); }.inspiration-title {
grid-column: 1 / -1; /* Span all columns */
text-align: center;
padding: 0.8rem;
background: rgba(47, 42, 38, 0.6);
color: var(–token-border);
border-radius: 8px;
font-size: 1.2rem;
font-weight: 600;
letter-spacing: 3px;
box-shadow: inset 0 0 10px rgba(0,0,0,0.3);
font-family: 'Zhi Mang Xing', cursive;
}.custom-token-wrapper {
grid-column: 1 / -1;
}/* — Footer — */
.footer {
margin-top: 4rem; text-align: right; padding-bottom: 2rem;
opacity: 0; transform: translateY(20px);
animation: subtle-fade-in-up 1.2s ease-out 3.4s forwards;
}
.footer-divider { width: 100%; height: 1px; background: linear-gradient(to right, transparent, var(–accent-gold), transparent); margin: 0 auto 2rem; }
.author-seal {
display: inline-flex; width: 50px; height: 50px;
background-color: var(–accent-red); color: white;
justify-content: center; align-items: center;
writing-mode: vertical-rl; text-orientation: mixed;
font-size: 1rem; font-weight: 600; letter-spacing: 3px;
border: 2px solid #A52A2A; box-shadow: 2px 2px 0 #A52A2A; border-radius: 4px;
}
</style>
</head>
<body><div id="ink-overlay"><div id="ink-spot"></div></div>
<audio id="theme-music" src="http://music.163.com/song/media/outer/url?id=5253685.mp3" loop preload="auto"></audio>
<div class="main-container">
<div class="music-player-wrapper">
<div class="music-player">
<button id="play-btn" class="play-button"></button>
<div class="song-info">
<div class="song-title">《乱红》</div>
<div id="progress-bar"><div id="progress-fill"></div></div>
</div>
</div>
</div><section class="character-visual">
<div class="character-image-container">
<img src="https://i.postimg.cc/wvkwzSWK/GIF-20250921151813514.gif" alt="太子李玄" class="character-image">
</div>
</section><section class="character-intro">
<h1 class="character-title">太子 · 李玄</h1>
<p class="character-tagline">他以温润为刃,以天下为棋。当你凝视深渊时,深渊也在……对你微笑。</p>
</section><section class="opening-selection">
<h2 class="opening-selection-title">命运之选</h2>
<div class="token-grid" id="token-container"></div>
</section><footer class="footer">
<div class="footer-divider"></div>
<div class="author-seal">朱墙墨影</div>
</footer></div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const audio = document.getElementById('theme-music');
const playBtn = document.getElementById('play-btn');
const progressBar = document.getElementById('progress-bar');
const progressFill = document.getElementById('progress-fill');
const tokenContainer = document.getElementById('token-container');let musicInitialized = false;
const interactionEvents = ['click', 'scroll', 'keydown', 'mousemove', 'touchend'];function initializeAudio() {
if (musicInitialized || !audio) return;
const playPromise = audio.play();
if (playPromise !== undefined) {
playPromise.then(() => {
musicInitialized = true;
interactionEvents.forEach(event => document.removeEventListener(event, initializeAudio));
}).catch(error => {
console.warn("Interaction-triggered autoplay failed. Awaiting more specific interaction.", error.message);
});
}
}interactionEvents.forEach(event => document.addEventListener(event, initializeAudio));
playBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (audio.paused) {
audio.play();
} else {
audio.pause();
}
});audio.onplay = () => {
playBtn.classList.add('playing');
const playIcon = playBtn.querySelector ? playBtn.querySelector('.play-icon-shape') : document.querySelector('.play-icon-shape');
const pauseIcons = playBtn.querySelector ? playBtn.querySelector('.pause-icon-shapes') : document.querySelector('.pause-icon-shapes');
if (playIcon) playIcon.style.opacity = '0';
if (pauseIcons) pauseIcons.style.opacity = '1';
};
audio.onpause = () => {
playBtn.classList.remove('playing');
const playIcon = playBtn.querySelector ? playBtn.querySelector('.play-icon-shape') : document.querySelector('.play-icon-shape');
const pauseIcons = playBtn.querySelector ? playBtn.querySelector('.pause-icon-shapes') : document.querySelector('.pause-icon-shapes');
if (playIcon) playIcon.style.opacity = '1';
if (pauseIcons) pauseIcons.style.opacity = '0';
};audio.addEventListener('timeupdate', () => {
if(audio.duration) {
const percentage = (audio.currentTime / audio.duration) * 100;
progressFill.style.width = `${percentage}%`;
}
});progressBar.addEventListener('click', (e) => {
if(audio.duration) {
const rect = progressBar.getBoundingClientRect();
const clickX = e.clientX – rect.left;
const percentage = clickX / rect.width;
audio.currentTime = audio.duration * percentage;
}
});const openingData = [
{ num: '一', title: '帝王重生', desc: '前世,他为权欲逼你家破人亡,踏着你的尸骨登上帝位。重生归来,竟是大婚之夜,这一次,他将如何偿还血债?', swipeId: 1 },
{ num: '二', title: '白月光刃', desc: '你是他最忠诚的利刃,亦是他权力路上被舍弃的棋子。当他幡然醒悟,重活一世,权谋皆可抛,只为守住那唯一的亏欠。', swipeId: 2 },
{ num: '三', title: '宿敌对决', desc: '你是他储君之路上唯一的对手,只有你能看穿他温润伪装下的冷漠。这场东宫之争,谁会先成为对方的阶下囚?', swipeId: 3 },
{ num: '四', title: '忠犬利刃', desc: '你是他无欲无求的刀,亦是他最难掌控的软肋。他开始好奇,该用何种“赏赐”,才能将你这把绝世之刃彻底锁在身边。', swipeId: 4 },
{ num: '五', title: '骨科失控', desc: '他视你为温顺的棋子,扮演着完美皇兄。直到他从你眼中捕捉到炙热的占有欲,猎物露出獠牙…这盘棋,变得有趣了。', swipeId: 5 },
{ num: '六', title: '宫宴偏爱', desc: '在无聊的官场夜宴,他于众人中唯独看到你的不耐,并用一个天衣无缝的借口将你带离。这究竟是温柔巧合,还是精心围猎?', swipeId: 6 },
{ num: '七', title: '盟友之约', desc: '朝堂纷争后,他于亭中设下残局邀你入座。他不问派系,只问你如何破这天下棋局。他等的,是一个能并肩执棋的盟友。', swipeId: 7 },
{ type: 'title', text: '— 网友灵感 —' },
{ num: '八', title: '美人棋子', desc: '他曾亲手将你雕琢成最完美的棋子,献于父皇的龙床之上,以谋江山;可如今,他想他似乎后悔了。', swipeId: 8 },
{ type: 'custom', num: '自定义', title: '自定义开场', desc: '你的身份、你与他的关系、你们的初见……一切由你定义。在这风雨欲来的王朝,执笔权,在你手中。', swipeId: 9 }
];openingData.forEach((data) => {
let elementWrapper;
if (data.type === 'title') {
const titleElement = document.createElement('div');
titleElement.className = 'inspiration-title';
titleElement.textContent = data.text;
elementWrapper = titleElement;
} else {
const isCustom = data.type === 'custom';
const tokenElement = document.createElement('div');
tokenElement.className = 'token';
tokenElement.onclick = () => selectOpening(tokenElement, data.swipeId);
tokenElement.innerHTML = `
<div class="token-tassel"></div>
<div class="token-header">
<span class="token-number ${data.num.length > 1 ? 'custom-num' : ''}">${data.num}</span>
<h3 class="token-title">${data.title}</h3>
</div>
<p class="token-description">${data.desc}</p>
<span class="token-button">进入此世</span>
`;if (isCustom) {
const wrapperDiv = document.createElement('div');
wrapperDiv.className = 'custom-token-wrapper';
wrapperDiv.appendChild(tokenElement);
elementWrapper = wrapperDiv;
} else {
elementWrapper = tokenElement;
}
}
tokenContainer.appendChild(elementWrapper);
});
});async function selectOpening(tokenElement, swipeId) {
const button = tokenElement.querySelector('.token-button');
if (button) button.textContent = '载入中…';try {
if (typeof getChatMessages === 'function' && typeof setChatMessage === 'function') {
const messages = await getChatMessages("0", { include_swipe: true });
if (messages && messages[0].swipes && messages[0].swipes.length > swipeId) {
await setChatMessage(messages[0].swipes[swipeId], 0, {
swipe_id: swipeId,
refresh: 'display_and_render_current'
});
} else {
throw new Error(`开场白ID ${swipeId} 无效或不存在。`);
}
} else {
console.log(`在非TavernAI环境中,尝试切换到开场白索引: ${swipeId}`);
alert(`已选择开场 ${swipeId}。`);
if(button) button.textContent = '进入此世';
}
} catch (error) {
console.error("切换开场失败:", error);
alert(`切换开场失败: ${error.message}`);
if(button) button.textContent = '进入此世';
}
}
</script>
</body>
</html>
“`<StatusPlaceHolderImpl/>