Files
084_sort/sinner-gallery.html
2026-04-10 20:17:38 +08:00

593 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>罪人立绘排列</title>
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* 继承index.html的样式并添加展示页面特定样式 */
:root {
--primary-color: #ff4d4d;
--secondary-color: #ffd700;
--bg-color: #121212;
--text-color: #e0e0e0;
--panel-bg: #1e1e1e;
}
body {
font-family: 'Noto Serif SC', serif;
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
overflow-x: hidden;
user-select: none;
}
.page-header {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(30, 30, 30, 0.8);
border-bottom: 1px solid var(--secondary-color);
}
.page-title {
font-size: 1.8rem;
color: var(--secondary-color);
margin: 0;
}
.back-btn {
background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%);
border: 2px solid var(--secondary-color);
color: var(--secondary-color);
padding: 0.5rem 1.5rem;
font-family: 'Noto Serif SC', serif;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
clip-path: polygon(10% 0, 100% 0, 100% 90%, 90% 100%, 0 100%, 0 10%);
}
.back-btn:hover {
background: var(--secondary-color);
color: #000;
}
.gallery-container {
flex: 1;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.sinner-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
width: 100%;
max-width: 1200px;
margin-top: 20px;
}
.sinner-card {
background-color: rgba(30, 30, 30, 0.8);
border: 2px solid rgba(255, 215, 0, 0.3);
border-radius: 10px;
overflow: hidden;
transition: all 0.3s ease;
cursor: pointer;
position: relative;
}
.sinner-card:hover {
transform: translateY(-5px);
border-color: var(--secondary-color);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
}
.sinner-card-img {
width: 100%;
height: 300px;
object-fit: contain;
background-color: rgba(0, 0, 0, 0.3);
padding: 10px;
}
.sinner-card-info {
padding: 15px;
text-align: center;
}
.sinner-name {
font-size: 1.2rem;
color: var(--secondary-color);
margin: 0;
}
.sinner-source {
font-size: 0.9rem;
color: var(--text-color);
margin-top: 5px;
}
/* 罪人立绘排序界面 */
.sorting-container {
display: none;
flex-direction: column;
width: 100%;
height: 100%;
padding: 20px;
}
.sorting-container.active {
display: flex;
}
.sorting-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.sorting-title {
font-size: 1.5rem;
color: var(--secondary-color);
}
.sorting-content {
display: flex;
flex: 1;
gap: 20px;
overflow: hidden;
}
.sorting-left {
flex: 2;
display: flex;
flex-direction: column;
gap: 20px;
overflow-y: auto;
}
.sorting-right {
flex: 1;
background-color: rgba(30, 30, 30, 0.8);
border: 2px solid rgba(255, 215, 0, 0.3);
border-radius: 10px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.sorting-right-header {
padding: 15px;
border-bottom: 1px solid rgba(255, 215, 0, 0.3);
text-align: center;
color: var(--secondary-color);
font-size: 1.2rem;
}
.sorting-right-content {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
overflow: auto;
}
.sorting-right-image {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.sorting-categories {
display: flex;
flex-direction: column;
gap: 15px;
}
.sorting-category {
background-color: rgba(30, 30, 30, 0.8);
border: 2px solid rgba(255, 215, 0, 0.3);
border-radius: 10px;
padding: 15px;
min-height: 150px;
transition: all 0.3s ease;
}
.sorting-category.drag-over {
border-color: var(--secondary-color);
background-color: rgba(255, 215, 0, 0.1);
}
.sorting-category-title {
font-size: 1.2rem;
color: var(--secondary-color);
margin-bottom: 10px;
text-align: center;
}
.sorting-category-content {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.sorting-images {
display: flex;
flex-wrap: wrap;
gap: 10px;
padding: 15px;
background-color: rgba(30, 30, 30, 0.5);
border-radius: 10px;
}
.sorting-image {
width: 80px;
height: 80px;
object-fit: cover;
border: 2px solid rgba(255, 215, 0, 0.3);
border-radius: 5px;
cursor: grab;
transition: all 0.3s ease;
}
.sorting-image:hover {
border-color: var(--secondary-color);
transform: scale(1.05);
}
.sorting-image:active {
cursor: grabbing;
}
.sorting-image.dragging {
opacity: 0.5;
}
.sorting-image-small {
width: 80px;
height: 80px;
object-fit: cover;
border: 2px solid rgba(255, 215, 0, 0.3);
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.sorting-image-small:hover {
border-color: var(--secondary-color);
transform: scale(1.05);
}
/* 响应式设计 */
@media (max-width: 768px) {
.sinner-cards {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.sinner-card-img {
height: 200px;
}
.sorting-content {
flex-direction: column;
}
.sorting-left {
flex: 1;
}
.sorting-right {
height: 300px;
}
}
</style>
</head>
<body>
<div class="page-header">
<h1 class="page-title">罪人立绘排列</h1>
<button class="back-btn" onclick="window.location.href='index.html'">
<i class="fas fa-arrow-left"></i> 返回
</button>
</div>
<div class="gallery-container">
<div class="sinner-cards" id="sinner-cards">
<!-- 罪人卡片将通过JavaScript动态生成 -->
</div>
</div>
<!-- 罪人立绘排序界面 -->
<div class="sorting-container" id="sorting-container">
<div class="sorting-header">
<h2 class="sorting-title" id="sorting-title">罪人立绘排序</h2>
<button class="back-btn" onclick="closeSorting()">
<i class="fas fa-arrow-left"></i> 返回
</button>
</div>
<div class="sorting-content">
<div class="sorting-left">
<div class="sorting-categories">
<div class="sorting-category" data-category="夯">
<div class="sorting-category-title"></div>
<div class="sorting-category-content"></div>
</div>
<div class="sorting-category" data-category="顶级">
<div class="sorting-category-title">顶级</div>
<div class="sorting-category-content"></div>
</div>
<div class="sorting-category" data-category="人上人">
<div class="sorting-category-title">人上人</div>
<div class="sorting-category-content"></div>
</div>
<div class="sorting-category" data-category="npc">
<div class="sorting-category-title">NPC</div>
<div class="sorting-category-content"></div>
</div>
</div>
<div class="sorting-images" id="sorting-images">
<!-- 罪人立绘将通过JavaScript动态生成 -->
</div>
</div>
<div class="sorting-right">
<div class="sorting-right-header">立绘预览</div>
<div class="sorting-right-content">
<img src="" alt="" class="sorting-right-image" id="sorting-right-image">
</div>
</div>
</div>
</div>
<script>
// 罪人数据与matching-game.html保持一致
const gameData = [
{ id: 1, sinner: "李箱", source: "《李箱》", imgName: "yisang", egoImgName: "yi_sang_ego" },
{ id: 2, sinner: "浮士德", source: "《浮士德》", imgName: "faust", egoImgName: "faust_ego" },
{ id: 3, sinner: "堂吉诃德", source: "《堂吉诃德》", imgName: "don_quixote", egoImgName: "don_quixote_ego" },
{ id: 4, sinner: "良秀", source: "《地狱变》", imgName: "yoshihide", egoImgName: "yoshihide_ego" },
{ id: 5, sinner: "默尔索", source: "《局外人》", imgName: "meursault", egoImgName: "meursault_ego" },
{ id: 6, sinner: "鸿璐", source: "《红楼梦》", imgName: "honglu", egoImgName: "honglu_ego" },
{ id: 7, sinner: "希斯克利夫", source: "《呼啸山庄》", imgName: "heathcliff", egoImgName: "heathcliff_ego" },
{ id: 8, sinner: "以实玛利", source: "《白鲸》", imgName: "ishmael", egoImgName: "ishmael_ego" },
{ id: 9, sinner: "罗佳", source: "《罪与罚》", imgName: "rodya", egoImgName: "rodya_ego" },
{ id: 11, sinner: "辛克莱", source: "《德米安》", imgName: "sinclair", egoImgName: "sinclair_ego" },
{ id: 12, sinner: "奥提斯", source: "《奥德修斯》", imgName: "outis", egoImgName: "outis_ego" },
{ id: 13, sinner: "格里高尔", source: "《变形记》", imgName: "gregor", egoImgName: "gregor_ego" },
];
// 初始化页面
function initPage() {
// 生成罪人卡片
generateSinnerCards();
}
// 生成罪人卡片
function generateSinnerCards() {
const sinnerCards = document.getElementById('sinner-cards');
sinnerCards.innerHTML = '';
gameData.forEach(sinner => {
const card = document.createElement('div');
card.className = 'sinner-card';
card.dataset.id = sinner.id;
const img = document.createElement('img');
img.src = `images/sinners/${sinner.imgName}.png`;
img.alt = sinner.sinner;
img.className = 'sinner-card-img';
// 如果图片加载失败,显示默认图标
img.onerror = function() {
this.style.display = 'none';
const icon = document.createElement('i');
icon.className = 'fas fa-user';
icon.style.fontSize = '100px';
icon.style.color = 'var(--secondary-color)';
this.parentNode.insertBefore(icon, this);
};
const info = document.createElement('div');
info.className = 'sinner-card-info';
const name = document.createElement('h3');
name.className = 'sinner-name';
name.textContent = sinner.sinner;
const source = document.createElement('div');
source.className = 'sinner-source';
source.textContent = sinner.source;
info.appendChild(name);
info.appendChild(source);
card.appendChild(img);
card.appendChild(info);
// 添加点击事件,打开立绘排序界面
card.addEventListener('click', () => openSorting(sinner));
sinnerCards.appendChild(card);
});
}
// 打开立绘排序界面
function openSorting(sinner) {
const sortingContainer = document.getElementById('sorting-container');
const sortingTitle = document.getElementById('sorting-title');
const sortingImages = document.getElementById('sorting-images');
// 隐藏罪人卡片,显示排序界面
document.querySelector('.gallery-container').style.display = 'none';
sortingContainer.classList.add('active');
// 设置标题
sortingTitle.textContent = `${sinner.sinner} 立绘排序`;
// 清空之前的立绘
sortingImages.innerHTML = '';
// 清空分类中的立绘
document.querySelectorAll('.sorting-category-content').forEach(content => {
content.innerHTML = '';
});
// 加载罪人的所有人格立绘
loadSinnerPersonalities(sinner);
}
// 加载罪人的所有人格立绘
async function loadSinnerPersonalities(sinner) {
const sortingImages = document.getElementById('sorting-images');
try {
// 加载 JSON 索引文件
const response = await fetch('images/sinner_images.json');
const sinnerData = await response.json();
// 查找当前罪人的图片数据
const currentSinner = sinnerData.find(item => item.name === sinner.imgName);
if (currentSinner && currentSinner.images && currentSinner.images.length > 0) {
// 为每个人格立绘创建可拖动的图片元素
currentSinner.images.forEach((personality, index) => {
const img = document.createElement('img');
img.src = personality.path;
img.alt = personality.name;
img.className = 'sorting-image';
img.dataset.id = index + 1;
img.dataset.name = personality.name;
img.draggable = true;
// 如果图片加载失败,显示默认图标
img.onerror = function() {
this.style.display = 'none';
const icon = document.createElement('i');
icon.className = 'fas fa-user';
icon.style.fontSize = '80px';
icon.style.color = 'var(--secondary-color)';
this.parentNode.insertBefore(icon, this);
};
// 添加拖动事件
img.addEventListener('dragstart', handleDragStart);
img.addEventListener('dragend', handleDragEnd);
// 添加点击事件,在右侧显示完整图片
img.addEventListener('click', () => showFullImage(personality.path));
sortingImages.appendChild(img);
});
} else {
// 如果没有找到图片,显示提示信息
const errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.textContent = `未找到 ${sinner.sinner} 的立绘图片`;
sortingImages.appendChild(errorMsg);
}
} catch (error) {
console.error('加载立绘失败:', error);
// 显示错误提示
const errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.textContent = '无法加载立绘,请检查图片路径';
sortingImages.appendChild(errorMsg);
}
}
// 显示完整图片
function showFullImage(imgSrc) {
const fullImage = document.getElementById('sorting-right-image');
fullImage.src = imgSrc;
}
// 处理拖动开始
function handleDragStart(e) {
this.classList.add('dragging');
e.dataTransfer.setData('text/plain', this.dataset.id);
e.dataTransfer.effectAllowed = 'move';
}
// 处理拖动结束
function handleDragEnd(e) {
this.classList.remove('dragging');
}
// 为分类区域添加拖放事件
document.querySelectorAll('.sorting-category').forEach(category => {
category.addEventListener('dragover', handleDragOver);
category.addEventListener('dragleave', handleDragLeave);
category.addEventListener('drop', handleDrop);
});
// 处理拖动悬停
function handleDragOver(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
this.classList.add('drag-over');
}
// 处理拖动离开
function handleDragLeave(e) {
this.classList.remove('drag-over');
}
// 处理放置
function handleDrop(e) {
e.preventDefault();
this.classList.remove('drag-over');
const id = e.dataTransfer.getData('text/plain');
const draggedElement = document.querySelector(`.sorting-image[data-id="${id}"]`);
if (draggedElement) {
// 将图片从原位置移动到新位置
const categoryContent = this.querySelector('.sorting-category-content');
// 创建一个新图片元素
const newImg = document.createElement('img');
newImg.src = draggedElement.src;
newImg.alt = draggedElement.alt;
newImg.className = 'sorting-image-small';
newImg.dataset.id = draggedElement.dataset.id;
newImg.dataset.name = draggedElement.dataset.name;
// 添加点击事件,在右侧显示完整图片
newImg.addEventListener('click', () => showFullImage(draggedElement.src));
// 将新图片添加到分类中
categoryContent.appendChild(newImg);
// 从原位置移除图片
draggedElement.remove();
}
}
// 关闭排序界面
function closeSorting() {
const sortingContainer = document.getElementById('sorting-container');
// 显示罪人卡片,隐藏排序界面
document.querySelector('.gallery-container').style.display = 'flex';
sortingContainer.classList.remove('active');
}
// 初始化页面
initPage();
</script>
</body>
</html>