重构提示框为模态框,优化样式和交互逻辑,增强用户体验,确保在移动设备上良好显示和操作。新增模态框的加载状态和关闭功能,提升代码可维护性。
This commit is contained in:
parent
178c2762f1
commit
c052203457
@ -40,7 +40,7 @@
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
/* 悬停提示样式 */
|
||||
/* 悬停提示样式 - 改为点击样式 */
|
||||
.chess-item, .synergy-item {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
@ -52,48 +52,160 @@
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
/* 增强提示框样式 */
|
||||
#tft-tooltip {
|
||||
transition: all 0.3s ease;
|
||||
max-height: 80vh;
|
||||
/* 模态框样式 */
|
||||
#tft-modal-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 50;
|
||||
display: none;
|
||||
backdrop-filter: blur(2px);
|
||||
animation: backdropFadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
#tft-modal-backdrop.open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#tft-modal {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 51;
|
||||
max-width: 90%;
|
||||
width: 450px;
|
||||
max-height: 85vh;
|
||||
background-color: #1f2937;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
overflow: hidden; /* 改为hidden,让滚动发生在内部容器 */
|
||||
border: 1px solid rgba(99, 102, 241, 0.3);
|
||||
animation: modalFadeIn 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
color: #f3f4f6; /* 设置模态框内默认文字颜色为浅灰色 */
|
||||
}
|
||||
|
||||
#tft-modal.open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 模态框内部包装容器 */
|
||||
.modal-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 85vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
border: 1px solid rgba(99, 102, 241, 0.3);
|
||||
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
|
||||
transform-origin: top left;
|
||||
animation: tooltipFadeIn 0.35s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(79, 70, 229, 0.4) rgba(17, 24, 39, 0.2);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@keyframes backdropFadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes modalFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -48%) scale(0.96);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
#tft-tooltip::-webkit-scrollbar {
|
||||
.modal-wrapper::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
#tft-tooltip::-webkit-scrollbar-track {
|
||||
.modal-wrapper::-webkit-scrollbar-track {
|
||||
background: rgba(17, 24, 39, 0.1);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#tft-tooltip::-webkit-scrollbar-thumb {
|
||||
.modal-wrapper::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(79, 70, 229, 0.4);
|
||||
border-radius: 3px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
#tft-tooltip::-webkit-scrollbar-thumb:hover {
|
||||
.modal-wrapper::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(79, 70, 229, 0.6);
|
||||
}
|
||||
|
||||
/* 提示框内容淡入效果 */
|
||||
#tft-tooltip .tooltip-content {
|
||||
/* 仅在滚动时显示滚动条 */
|
||||
.modal-wrapper {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.modal-wrapper::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
/* 初始隐藏滚动条 */
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-wrapper:hover::-webkit-scrollbar,
|
||||
.modal-wrapper:focus::-webkit-scrollbar,
|
||||
.modal-wrapper:active::-webkit-scrollbar {
|
||||
/* 悬停、聚焦或激活时显示滚动条 */
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 解决模态框内容加载时可能导致的布局偏移 */
|
||||
.modal-content {
|
||||
min-height: 150px; /* 设置最小高度,减少加载时的布局变化 */
|
||||
position: relative;
|
||||
/* 保持右侧边距一致,不管是否有滚动条 */
|
||||
padding: 20px;
|
||||
padding-right: 26px; /* 16px基础 + 10px给滚动条预留 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 模态框内容淡入效果 */
|
||||
#tft-modal .modal-content {
|
||||
word-break: break-word;
|
||||
opacity: 0;
|
||||
animation: contentFadeIn 0.2s ease forwards;
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
/* 模态框中的标题和文本颜色 */
|
||||
#tft-modal .font-bold {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#tft-modal .text-gray-800,
|
||||
#tft-modal .text-gray-700 {
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
#tft-modal .text-gray-500,
|
||||
#tft-modal .text-gray-400 {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
#tft-modal .text-indigo-300 {
|
||||
color: #a5b4fc;
|
||||
}
|
||||
|
||||
#tft-modal .bg-gray-700 {
|
||||
background-color: #374151;
|
||||
}
|
||||
|
||||
#tft-modal .bg-gray-600 {
|
||||
background-color: #4b5563;
|
||||
}
|
||||
|
||||
@keyframes contentFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
@ -105,23 +217,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tooltipFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-5px) scale(0.97);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 提示框中的费用标识 */
|
||||
#tft-tooltip .cost-1 { border-left: 3px solid #94a3b8; } /* 1费 - 灰色 */
|
||||
#tft-tooltip .cost-2 { border-left: 3px solid #65a30d; } /* 2费 - 绿色 */
|
||||
#tft-tooltip .cost-3 { border-left: 3px solid #2563eb; } /* 3费 - 蓝色 */
|
||||
#tft-tooltip .cost-4 { border-left: 3px solid #7e22ce; } /* 4费 - 紫色 */
|
||||
#tft-tooltip .cost-5 { border-left: 3px solid #f59e0b; } /* 5费 - 金色 */
|
||||
#tft-modal .cost-1 { border-left: 3px solid #94a3b8; } /* 1费 - 灰色 */
|
||||
#tft-modal .cost-2 { border-left: 3px solid #65a30d; } /* 2费 - 绿色 */
|
||||
#tft-modal .cost-3 { border-left: 3px solid #2563eb; } /* 3费 - 蓝色 */
|
||||
#tft-modal .cost-4 { border-left: 3px solid #7e22ce; } /* 4费 - 紫色 */
|
||||
#tft-modal .cost-5 { border-left: 3px solid #f59e0b; } /* 5费 - 金色 */
|
||||
|
||||
/* 提示框内交互元素样式 */
|
||||
.chess-item-mini, .synergy-item-mini {
|
||||
@ -147,34 +248,51 @@
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* 提示框中的各部分样式 */
|
||||
#tft-tooltip .tooltip-content {
|
||||
word-break: break-word;
|
||||
padding-top: 5px;
|
||||
padding-right: 36px; /* 为右侧关闭按钮留出空间 */
|
||||
}
|
||||
|
||||
/* 关闭按钮样式 */
|
||||
#tft-tooltip .tooltip-close-btn {
|
||||
/* 模态框关闭按钮样式 */
|
||||
#tft-modal .modal-close-btn {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background-color: #374151;
|
||||
color: #9ca3af;
|
||||
border-radius: 9999px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
opacity: 0.9;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#tft-tooltip .tooltip-close-btn:hover {
|
||||
#tft-modal .modal-close-btn:hover {
|
||||
opacity: 1;
|
||||
color: #ffffff;
|
||||
background-color: #4b5563;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* 模态框返回按钮样式 */
|
||||
#tft-modal .modal-back-btn {
|
||||
background-color: #4f46e5;
|
||||
}
|
||||
|
||||
#tft-modal .modal-back-btn:hover {
|
||||
background-color: #4338ca;
|
||||
}
|
||||
|
||||
/* 特殊介绍文本样式 */
|
||||
#tft-tooltip .skill-introduce,
|
||||
#tft-tooltip .synergy-introduce {
|
||||
#tft-modal .skill-introduce,
|
||||
#tft-modal .synergy-introduce {
|
||||
border-left: 3px solid rgba(79, 70, 229, 0.7);
|
||||
background-color: rgba(79, 70, 229, 0.1);
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
#tft-tooltip .loading-spinner {
|
||||
#tft-modal .loading-spinner {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
@ -249,90 +367,110 @@
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* 移动设备上的提示框样式优化 */
|
||||
/* 模态框额外样式 - 文字颜色优化 */
|
||||
#tft-modal .text-sm {
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
#tft-modal .text-xs {
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
#tft-modal .font-medium {
|
||||
color: #f3f4f6;
|
||||
}
|
||||
|
||||
#tft-modal .font-semibold {
|
||||
color: #f9fafb;
|
||||
}
|
||||
|
||||
/* 模态框中棋子列表项 */
|
||||
#tft-modal .chess-item-mini {
|
||||
background-color: #374151;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#tft-modal .chess-item-mini .text-sm {
|
||||
color: #f3f4f6;
|
||||
}
|
||||
|
||||
/* 模态框中羁绊列表项 */
|
||||
#tft-modal .synergy-item-mini {
|
||||
background-color: #374151;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#tft-modal .synergy-item-mini .text-sm {
|
||||
color: #f3f4f6;
|
||||
}
|
||||
|
||||
/* 移动端样式优化 */
|
||||
@media (max-width: 768px) {
|
||||
#tft-tooltip {
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid rgba(99, 102, 241, 0.5);
|
||||
max-width: calc(100vw - 40px);
|
||||
animation: mobileTooltipFadeIn 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
max-height: 70vh;
|
||||
/* 固定位置在屏幕中央 */
|
||||
position: fixed;
|
||||
top: 50% !important;
|
||||
left: 50% !important;
|
||||
transform: translate(-50%, -50%);
|
||||
margin: 0 auto;
|
||||
width: calc(100vw - 40px) !important;
|
||||
#tft-modal {
|
||||
width: 95%;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
#tft-tooltip .tooltip-close-btn {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
#tft-modal .modal-content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
#tft-tooltip .tooltip-content {
|
||||
margin-top: 10px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
/* 增大移动端触摸目标大小 */
|
||||
.chess-item-mini, .synergy-item-mini {
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* 增加右侧间距,避免文本与按钮重叠 */
|
||||
padding-right: 80px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* 移动端使用更明显的交互提示 */
|
||||
.chess-item-mini::after, .synergy-item-mini::after {
|
||||
content: '点击查看';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 10px;
|
||||
transform: translateY(-50%);
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
background-color: rgba(79, 70, 229, 0.5);
|
||||
padding: 3px 8px;
|
||||
border-radius: 10px;
|
||||
white-space: nowrap;
|
||||
z-index: 5;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 防止棋子费用与点击按钮重叠 */
|
||||
/* 移动端字体和边距调整 */
|
||||
#tft-modal .text-xs {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
#tft-modal .text-sm {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
#tft-modal .px-2 {
|
||||
padding-left: 0.4rem;
|
||||
padding-right: 0.4rem;
|
||||
}
|
||||
|
||||
#tft-modal .py-1 {
|
||||
padding-top: 0.2rem;
|
||||
padding-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
/* 为移动端优化小标签 */
|
||||
.chess-item-mini .text-xs.px-1\.5.py-0\.5.bg-gray-600.rounded {
|
||||
margin-right: 65px;
|
||||
font-size: 0.65rem;
|
||||
padding: 0.1rem 0.25rem;
|
||||
}
|
||||
|
||||
/* 防止羁绊类型与点击按钮重叠 */
|
||||
.synergy-item-mini .bg-gray-600.text-xs.px-1\.5.py-0\.5.rounded {
|
||||
margin-right: 65px;
|
||||
font-size: 0.65rem;
|
||||
padding: 0.1rem 0.25rem;
|
||||
}
|
||||
|
||||
/* 移动端提示框内部元素间距优化 */
|
||||
#tft-tooltip .mb-2 {
|
||||
margin-bottom: 10px;
|
||||
/* 移动端间距调整 */
|
||||
#tft-modal .mb-2 {
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
#tft-tooltip .mb-3 {
|
||||
margin-bottom: 15px;
|
||||
#tft-modal .mb-3 {
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
#tft-tooltip .p-2 {
|
||||
padding: 10px;
|
||||
#tft-modal .p-2 {
|
||||
padding: 0.4rem;
|
||||
}
|
||||
|
||||
/* 移动端动画效果 */
|
||||
@keyframes mobileTooltipFadeIn {
|
||||
/* 移动端动画优化 */
|
||||
@keyframes mobileModalFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -45%);
|
||||
transform: translate(-50%, -46%);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
@ -340,30 +478,36 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 提示框内部滚动优化 */
|
||||
#tft-tooltip::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
#tft-modal {
|
||||
animation: mobileModalFadeIn 0.25s ease;
|
||||
}
|
||||
|
||||
/* 移动端加载状态优化 */
|
||||
#tft-tooltip .loading-spinner .animate-spin {
|
||||
height: 45px;
|
||||
width: 45px;
|
||||
border-width: 3px;
|
||||
/* 移动端滚动条优化 */
|
||||
#tft-modal::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
#tft-tooltip .loading-spinner .text-xs {
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
/* 移动端加载动画优化 */
|
||||
#tft-modal .loading-spinner .animate-spin {
|
||||
height: 8vw;
|
||||
width: 8vw;
|
||||
border-width: 2px;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
/* 移动端表格布局优化 */
|
||||
#tft-tooltip .grid.grid-cols-2 {
|
||||
#tft-modal .loading-spinner .text-xs {
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
|
||||
/* 移动端网格布局优化 */
|
||||
#tft-modal .grid.grid-cols-2 {
|
||||
grid-template-columns: 1fr;
|
||||
grid-gap: 0.3rem;
|
||||
}
|
||||
|
||||
/* 改进相关棋子列表显示 */
|
||||
#tft-tooltip .grid.grid-cols-2.gap-1.mt-1 {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
#tft-modal .grid.grid-cols-2.gap-1.mt-1 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
}
|
@ -658,59 +658,57 @@ function toggleActiveChessVisibility(showOnlyActive) {
|
||||
let tooltipHistory = [];
|
||||
|
||||
/**
|
||||
* 创建提示框
|
||||
* 创建模态框
|
||||
*/
|
||||
function createTooltip() {
|
||||
// 如果已经存在提示框,不重复创建
|
||||
if ($('#tft-tooltip').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tooltip = $(`
|
||||
<div id="tft-tooltip" class="fixed z-50 hidden bg-gray-800 text-white rounded-lg p-4 shadow-lg border border-gray-700 w-80">
|
||||
<div class="tooltip-content pt-2"></div>
|
||||
<div class="loading-spinner absolute inset-0 flex items-center justify-center bg-gray-800 bg-opacity-90 hidden rounded-lg">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="animate-spin rounded-full h-10 w-10 border-b-2 border-t-2 border-indigo-500 mb-2"></div>
|
||||
<div class="text-xs text-indigo-300">加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="tooltip-close-btn absolute top-3 right-3 text-gray-400 hover:text-white bg-gray-700 hover:bg-gray-600 rounded-full w-8 h-8 flex items-center justify-center shadow-md z-20">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
`);
|
||||
|
||||
// 添加到页面
|
||||
$('body').append(tooltip);
|
||||
// 已经在HTML中创建了模态框结构,不需要动态创建
|
||||
// 为模态框按钮绑定事件
|
||||
const modal = $('#tft-modal');
|
||||
const modalBackdrop = $('#tft-modal-backdrop');
|
||||
|
||||
// 绑定关闭按钮事件
|
||||
tooltip.find('.tooltip-close-btn').on('click', function(e) {
|
||||
modal.find('.modal-close-btn').on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
tooltip.addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
// 重置历史记录
|
||||
tooltipHistory = [];
|
||||
closeModal();
|
||||
});
|
||||
|
||||
// 防止点击提示框本身触发关闭
|
||||
tooltip.on('click', function(e) {
|
||||
// 点击背景关闭模态框
|
||||
modalBackdrop.on('click', function() {
|
||||
closeModal();
|
||||
});
|
||||
|
||||
// 防止点击模态框本身触发关闭
|
||||
modal.on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示提示的返回按钮(重构为返回功能)
|
||||
* @param {jQuery} tooltipContent 提示内容元素
|
||||
* 关闭模态框
|
||||
*/
|
||||
function showTooltipBackButton(tooltipContent) {
|
||||
const tooltip = tooltipContent.closest('#tft-tooltip');
|
||||
function closeModal() {
|
||||
$('#tft-modal').removeClass('open');
|
||||
$('#tft-modal-backdrop').removeClass('open');
|
||||
currentHoveredId = null;
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
// 重置历史记录
|
||||
tooltipHistory = [];
|
||||
|
||||
// 重置滚动位置
|
||||
setTimeout(() => {
|
||||
$('.modal-wrapper').scrollTop(0);
|
||||
}, 300); // 等待模态框关闭动画完成
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示模态框的返回按钮(重构为返回功能)
|
||||
* @param {jQuery} modalContent 模态框内容元素
|
||||
*/
|
||||
function showTooltipBackButton(modalContent) {
|
||||
const modal = $('#tft-modal');
|
||||
|
||||
// 获取关闭按钮
|
||||
const closeButton = tooltip.find('.tooltip-close-btn');
|
||||
const closeButton = modal.find('.modal-close-btn');
|
||||
|
||||
// 如果历史记录中有内容,则显示返回功能
|
||||
if (tooltipHistory.length > 0) {
|
||||
@ -731,37 +729,44 @@ function showTooltipBackButton(tooltipContent) {
|
||||
// 弹出上一个提示内容
|
||||
const prevItem = tooltipHistory.pop();
|
||||
if (prevItem) {
|
||||
// 滚动到顶部
|
||||
$('.modal-wrapper').scrollTop(0);
|
||||
|
||||
// 恢复ID和内容
|
||||
currentHoveredId = prevItem.id;
|
||||
tooltipContent.html(prevItem.content);
|
||||
|
||||
// 使用淡入效果显示内容
|
||||
modalContent.fadeOut(100, function() {
|
||||
$(this).html(prevItem.content).fadeIn(100);
|
||||
|
||||
// 如果仍有历史记录,保持返回按钮
|
||||
if (tooltipHistory.length > 0) {
|
||||
showTooltipBackButton(tooltipContent);
|
||||
showTooltipBackButton(modalContent);
|
||||
} else {
|
||||
// 没有更多历史,切换回关闭按钮
|
||||
resetCloseButton(closeButton, tooltip);
|
||||
resetCloseButton(closeButton);
|
||||
}
|
||||
|
||||
// 重新绑定事件处理程序
|
||||
bindTooltipInteractions(tooltipContent);
|
||||
bindTooltipInteractions(modalContent);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 使用返回样式
|
||||
closeButton.removeClass('bg-gray-700 hover:bg-gray-600').addClass('bg-indigo-600 hover:bg-indigo-700');
|
||||
closeButton.removeClass('bg-gray-700 hover:bg-gray-600')
|
||||
.addClass('modal-back-btn');
|
||||
} else {
|
||||
// 没有历史,重置为关闭按钮
|
||||
resetCloseButton(closeButton, tooltip);
|
||||
resetCloseButton(closeButton);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置为关闭按钮
|
||||
* @param {jQuery} closeButton 按钮元素
|
||||
* @param {jQuery} tooltip 提示框元素
|
||||
*/
|
||||
function resetCloseButton(closeButton, tooltip) {
|
||||
function resetCloseButton(closeButton) {
|
||||
// 修改按钮图标为关闭图标
|
||||
closeButton.html(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
@ -775,75 +780,83 @@ function resetCloseButton(closeButton, tooltip) {
|
||||
// 绑定关闭按钮事件
|
||||
closeButton.on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
tooltip.addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
// 重置历史记录
|
||||
tooltipHistory = [];
|
||||
closeModal();
|
||||
});
|
||||
|
||||
// 使用关闭样式
|
||||
closeButton.removeClass('bg-indigo-600 hover:bg-indigo-700').addClass('bg-gray-700 hover:bg-gray-600');
|
||||
closeButton.removeClass('modal-back-btn');
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定提示内容中的交互事件
|
||||
* @param {jQuery} tooltipContent 提示内容元素
|
||||
* 绑定模态框内容中的交互事件
|
||||
* @param {jQuery} modalContent 模态框内容元素
|
||||
*/
|
||||
function bindTooltipInteractions(tooltipContent) {
|
||||
function bindTooltipInteractions(modalContent) {
|
||||
// 为羁绊小标签添加点击事件,显示对应的羁绊详情
|
||||
tooltipContent.find('.synergy-item-mini').on('click', function(e) {
|
||||
modalContent.find('.synergy-item-mini').on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
const synergyId = $(this).data('synergy-id');
|
||||
if (synergyId && synergyId !== currentHoveredId) {
|
||||
// 保存当前的提示内容到历史记录
|
||||
tooltipHistory.push({
|
||||
id: currentHoveredId,
|
||||
content: tooltipContent.html()
|
||||
content: modalContent.html()
|
||||
});
|
||||
|
||||
// 更新当前悬停ID并显示新的提示
|
||||
currentHoveredId = synergyId;
|
||||
showSynergyTooltipContent(synergyId, this, tooltipContent);
|
||||
showSynergyTooltipContent(synergyId, this, modalContent);
|
||||
}
|
||||
});
|
||||
|
||||
// 为棋子小标签添加点击事件,显示对应的棋子详情
|
||||
tooltipContent.find('.chess-item-mini').on('click', function(e) {
|
||||
modalContent.find('.chess-item-mini').on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
const chessId = $(this).data('chess-id');
|
||||
if (chessId && chessId !== currentHoveredId) {
|
||||
// 保存当前的提示内容到历史记录
|
||||
tooltipHistory.push({
|
||||
id: currentHoveredId,
|
||||
content: tooltipContent.html()
|
||||
content: modalContent.html()
|
||||
});
|
||||
|
||||
// 更新当前悬停ID并显示新的提示
|
||||
currentHoveredId = chessId;
|
||||
showChessTooltipContent(chessId, this, tooltipContent);
|
||||
showChessTooltipContent(chessId, this, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示棋子提示内容(不重新创建提示框)
|
||||
* 显示棋子提示内容(在模态框中显示)
|
||||
* @param {string} chessId 棋子ID
|
||||
* @param {Element} element 触发元素
|
||||
* @param {jQuery} tooltipContent 提示内容元素
|
||||
* @param {jQuery} modalContent 模态框内容元素
|
||||
*/
|
||||
function showChessTooltipContent(chessId, element, tooltipContent) {
|
||||
const tooltip = tooltipContent.closest('#tft-tooltip');
|
||||
const loadingSpinner = tooltip.find('.loading-spinner');
|
||||
function showChessTooltipContent(chessId, element, modalContent) {
|
||||
const modal = $('#tft-modal');
|
||||
const loadingSpinner = modal.find('.loading-spinner');
|
||||
const isMobile = window.matchMedia("(max-width: 768px)").matches ||
|
||||
('ontouchstart' in window) ||
|
||||
(navigator.maxTouchPoints > 0);
|
||||
|
||||
// 先定位提示框但不显示
|
||||
positionTooltip(tooltip, element);
|
||||
// 先打开模态框,再加载内容,这样可以避免滚动条突然出现
|
||||
$('#tft-modal').addClass('open');
|
||||
$('#tft-modal-backdrop').addClass('open');
|
||||
|
||||
// 重置内容并显示加载中
|
||||
tooltipContent.empty();
|
||||
// 滚动到顶部
|
||||
$('.modal-wrapper').scrollTop(0);
|
||||
|
||||
// 重置内容并显示加载中 - 添加占位符内容以维持高度
|
||||
modalContent.empty();
|
||||
modalContent.html(`
|
||||
<div class="min-h-[400px] flex items-center justify-center">
|
||||
<div class="text-center text-gray-400">
|
||||
<div class="text-lg mb-2">加载中...</div>
|
||||
<div class="text-sm">正在获取棋子信息</div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
loadingSpinner.removeClass('hidden');
|
||||
|
||||
// 获取棋子详情
|
||||
@ -855,9 +868,9 @@ function showChessTooltipContent(chessId, element, tooltipContent) {
|
||||
let content = `
|
||||
<div class="mb-2 flex items-center justify-between pl-10">
|
||||
<div>
|
||||
<span class="font-bold text-lg">${details.name}</span>
|
||||
<span class="font-bold text-lg text-white">${details.name}</span>
|
||||
${details.title ? `<span class="text-xs text-gray-300 ml-1">${details.title}</span>` : ''}
|
||||
<span class="ml-2 px-2 py-1 bg-yellow-600 rounded-full text-xs">${details.cost}费</span>
|
||||
<span class="ml-2 px-2 py-1 bg-yellow-600 rounded-full text-xs text-white">${details.cost}费</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -890,70 +903,70 @@ function showChessTooltipContent(chessId, element, tooltipContent) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">生命值:</span>
|
||||
<span class="text-sm ml-1">${details.life}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.life}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.attack) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">攻击力:</span>
|
||||
<span class="text-sm ml-1">${details.attack}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.attack}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.attackSpeed) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">攻速:</span>
|
||||
<span class="text-sm ml-1">${details.attackSpeed}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.attackSpeed}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.attackRange) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">攻击范围:</span>
|
||||
<span class="text-sm ml-1">${details.attackRange}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.attackRange}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.armor) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">护甲:</span>
|
||||
<span class="text-sm ml-1">${details.armor}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.armor}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.spellBlock) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">魔抗:</span>
|
||||
<span class="text-sm ml-1">${details.spellBlock}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.spellBlock}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.crit) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">暴击率:</span>
|
||||
<span class="text-sm ml-1">${details.crit}%</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.crit}%</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.magic) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">法力值:</span>
|
||||
<span class="text-sm ml-1">${details.magic}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.magic}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.startMagic) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">初始法力值:</span>
|
||||
<span class="text-sm ml-1">${details.startMagic}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.startMagic}</span>
|
||||
</div>`;
|
||||
}
|
||||
if (details.attackMag) {
|
||||
content += `
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs text-gray-400">法术强度倍率:</span>
|
||||
<span class="text-sm ml-1">${details.attackMag}</span>
|
||||
<span class="text-sm text-gray-200 ml-1">${details.attackMag}</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@ -967,7 +980,7 @@ function showChessTooltipContent(chessId, element, tooltipContent) {
|
||||
<div class="mb-3 bg-gray-700 p-2 rounded">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="font-semibold text-indigo-300">${details.skill_name}</div>
|
||||
${details.skill_mana ? `<span class="bg-blue-600 text-xs px-2 py-0.5 rounded">${details.skill_mana}法力</span>` : ''}
|
||||
${details.skill_mana ? `<span class="bg-blue-600 text-xs px-2 py-0.5 rounded text-white">${details.skill_mana}法力</span>` : ''}
|
||||
</div>
|
||||
${details.skill_type ? `<div class="text-xs text-blue-300 mt-1">${details.skill_type}</div>` : ''}
|
||||
|
||||
@ -1002,265 +1015,323 @@ function showChessTooltipContent(chessId, element, tooltipContent) {
|
||||
details.synergies.forEach(synergy => {
|
||||
content += `
|
||||
<div class="text-sm mb-1 px-2 py-1 bg-gray-700 rounded flex items-center justify-between synergy-item-mini" data-synergy-id="${synergy.id}">
|
||||
<span class="flex-grow">${synergy.name}</span>
|
||||
<span class="bg-gray-600 text-xs px-1.5 py-0.5 rounded">${synergyTypes[synergy.type] || synergy.type}</span>
|
||||
<span class="flex-grow text-gray-200">${synergy.name}</span>
|
||||
<span class="bg-gray-600 text-xs px-1.5 py-0.5 rounded text-gray-300">${synergyTypes[synergy.type] || synergy.type}</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
// 隐藏加载中状态
|
||||
// 使用淡入效果更新内容,避免内容突然变化
|
||||
setTimeout(() => {
|
||||
// 隐藏加载动画
|
||||
loadingSpinner.addClass('hidden');
|
||||
|
||||
// 设置内容并显示提示框
|
||||
tooltipContent.html(content);
|
||||
// 模拟内容加载完成的淡入效果
|
||||
modalContent.fadeOut(100, function() {
|
||||
$(this).html(content).fadeIn(150);
|
||||
|
||||
// 显示返回按钮
|
||||
showTooltipBackButton(tooltipContent);
|
||||
// 显示返回按钮(如果有历史记录)
|
||||
showTooltipBackButton(modalContent);
|
||||
|
||||
// 绑定交互事件
|
||||
bindTooltipInteractions(tooltipContent);
|
||||
|
||||
// 所有内容准备好后显示提示框
|
||||
tooltip.removeClass('hidden');
|
||||
} else {
|
||||
// 处理错误
|
||||
tooltipContent.html(`<div class="text-red-400">获取详情失败</div>`);
|
||||
loadingSpinner.addClass('hidden');
|
||||
tooltip.removeClass('hidden');
|
||||
bindTooltipInteractions(modalContent);
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
}).catch(error => {
|
||||
// 处理错误
|
||||
tooltipContent.html(`<div class="text-red-400">请求出错</div>`);
|
||||
setTimeout(() => {
|
||||
loadingSpinner.addClass('hidden');
|
||||
tooltip.removeClass('hidden');
|
||||
modalContent.html(`<div class="text-red-400 p-4">请求出错: ${error.message || '未知错误'}</div>`);
|
||||
modalContent.fadeIn(150);
|
||||
}, 100);
|
||||
|
||||
console.error('获取棋子详情失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示羁绊提示内容(不重新创建提示框)
|
||||
* 显示羁绊提示内容(在模态框中显示)
|
||||
* @param {string} synergyId 羁绊ID
|
||||
* @param {Element} element 触发元素
|
||||
* @param {jQuery} tooltipContent 提示内容元素
|
||||
* @param {jQuery} modalContent 模态框内容元素
|
||||
*/
|
||||
function showSynergyTooltipContent(synergyId, element, tooltipContent) {
|
||||
const tooltip = tooltipContent.closest('#tft-tooltip');
|
||||
const loadingSpinner = tooltip.find('.loading-spinner');
|
||||
const isMobile = window.matchMedia("(max-width: 768px)").matches ||
|
||||
('ontouchstart' in window) ||
|
||||
(navigator.maxTouchPoints > 0);
|
||||
function showSynergyTooltipContent(synergyId, element, modalContent) {
|
||||
const modal = $('#tft-modal');
|
||||
const loadingSpinner = modal.find('.loading-spinner');
|
||||
|
||||
// 先定位提示框但不显示
|
||||
positionTooltip(tooltip, element);
|
||||
// 先打开模态框,再加载内容,这样可以避免滚动条突然出现
|
||||
$('#tft-modal').addClass('open');
|
||||
$('#tft-modal-backdrop').addClass('open');
|
||||
|
||||
// 显示加载中
|
||||
tooltipContent.empty();
|
||||
// 滚动到顶部
|
||||
$('.modal-wrapper').scrollTop(0);
|
||||
|
||||
// 重置内容并显示加载中 - 添加占位符内容以维持高度
|
||||
modalContent.empty();
|
||||
modalContent.html(`
|
||||
<div class="min-h-[400px] flex items-center justify-center">
|
||||
<div class="text-center text-gray-400">
|
||||
<div class="text-lg mb-2">加载中...</div>
|
||||
<div class="text-sm">正在获取羁绊信息</div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
loadingSpinner.removeClass('hidden');
|
||||
|
||||
// 获取羁绊详情
|
||||
fetchItemDetails('synergy', synergyId).then(response => {
|
||||
if (response.status === 'success') {
|
||||
const details = response.details;
|
||||
console.log("羁绊详情:", details); // 调试用,查看响应数据结构
|
||||
|
||||
// 构建提示内容,添加左侧内边距给返回按钮留出空间
|
||||
// 构建提示内容
|
||||
let content = `
|
||||
<div class="mb-2 pl-10">
|
||||
<span class="font-bold text-lg">${details.name}</span>
|
||||
<span class="ml-2 px-2 py-1 bg-indigo-600 rounded-full text-xs">
|
||||
${details.type === 'job' ? '职业' : '特质'}
|
||||
</span>
|
||||
<div class="mb-2 flex items-center pl-10">
|
||||
<div>
|
||||
<span class="font-bold text-lg text-white">${details.name}</span>
|
||||
<span class="text-xs text-gray-300 ml-1">${details.type === 'job' ? '职业' : '种族'}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 羁绊介绍 - 优先使用 introduce 字段
|
||||
// 羁绊介绍
|
||||
if (details.introduce) {
|
||||
content += `
|
||||
<div class="mb-3 text-sm italic text-gray-300 bg-gray-700 p-2 rounded font-medium synergy-introduce">
|
||||
<div class="mb-3 text-sm italic text-gray-300 bg-gray-700 p-2 rounded synergy-introduce">
|
||||
${details.introduce}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// 羁绊描述作为补充信息 - 如果有额外的描述信息
|
||||
if (details.description && details.description !== details.introduce) {
|
||||
content += `<div class="mb-3 text-sm text-gray-300">${details.description}</div>`;
|
||||
// 羁绊激活条件
|
||||
if (details.levels && details.levels.length > 0) {
|
||||
content += `<div class="mb-3"><div class="text-sm text-indigo-300 font-semibold mb-1">激活条件:</div>`;
|
||||
|
||||
// 添加激活条件卡片
|
||||
details.levels.forEach(level => {
|
||||
// 检查激活数量可能的字段名
|
||||
let activateCount = null;
|
||||
if (level.level) {
|
||||
activateCount = level.level;
|
||||
} else if (level.count) {
|
||||
activateCount = level.count;
|
||||
} else if (level.num) {
|
||||
activateCount = level.num;
|
||||
} else if (level.number) {
|
||||
activateCount = level.number;
|
||||
}
|
||||
|
||||
// 等级效果
|
||||
if (details.levels && details.levels.length > 0) {
|
||||
content += `<div class="text-sm font-semibold text-indigo-300 mb-1">等级效果:</div>`;
|
||||
|
||||
// 按等级排序
|
||||
const sortedLevels = [...details.levels].sort((a, b) => {
|
||||
return parseInt(a.level) - parseInt(b.level);
|
||||
});
|
||||
|
||||
sortedLevels.forEach(levelInfo => {
|
||||
content += `
|
||||
<div class="mb-2 bg-gray-700 p-2 rounded">
|
||||
<div class="text-xs text-yellow-400 font-medium">${levelInfo.level}人口:</div>
|
||||
<div class="text-sm mt-1">${levelInfo.effect}</div>
|
||||
<div class="bg-gray-700 p-2 mb-2 rounded flex flex-wrap">
|
||||
<div class="w-full flex items-center justify-between mb-1">
|
||||
<span class="text-yellow-400 font-semibold">${activateCount}个</span>
|
||||
<span class="text-xs bg-indigo-900 text-indigo-200 px-2 py-0.5 rounded">
|
||||
${level.level ? `等级 ${level.level}` : ''}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm text-white">${level.effect}</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
content += `</div>`;
|
||||
}
|
||||
|
||||
// 相关棋子
|
||||
if (details.related_chess && details.related_chess.length > 0) {
|
||||
content += `<div class="text-sm font-semibold text-indigo-300 mt-4 mb-1">相关棋子 (${details.related_chess.length}):</div>`;
|
||||
content += `<div class="text-sm text-indigo-300 font-semibold mb-1">相关棋子:</div>`;
|
||||
|
||||
// 按费用排序
|
||||
const sortedChess = [...details.related_chess].sort((a, b) => {
|
||||
return parseInt(a.cost) - parseInt(b.cost);
|
||||
// 根据费用对棋子进行分组
|
||||
const chessByPrice = {};
|
||||
details.related_chess.forEach(chess => {
|
||||
const price = chess.cost || 0;
|
||||
if (!chessByPrice[price]) {
|
||||
chessByPrice[price] = [];
|
||||
}
|
||||
chessByPrice[price].push(chess);
|
||||
});
|
||||
|
||||
// 保持两列布局,因为棋子卡片较小
|
||||
content += `<div class="grid grid-cols-2 gap-1 mt-1">`;
|
||||
sortedChess.forEach(chess => {
|
||||
const costClass = `cost-${chess.cost}`;
|
||||
// 按费用从低到高排序并添加棋子
|
||||
Object.keys(chessByPrice).sort((a, b) => Number(a) - Number(b)).forEach(price => {
|
||||
const priceChess = chessByPrice[price];
|
||||
|
||||
content += `<div class="mb-2">`;
|
||||
content += `<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-1">`;
|
||||
|
||||
priceChess.forEach(chess => {
|
||||
content += `
|
||||
<div class="bg-gray-700 rounded p-1 flex items-center ${costClass} chess-item-mini" data-chess-id="${chess.id}">
|
||||
<span class="text-sm flex-grow truncate">${chess.name}</span>
|
||||
<span class="text-xs px-1.5 py-0.5 bg-gray-600 rounded">${chess.cost}费</span>
|
||||
<div class="bg-gray-700 p-1 rounded flex items-center chess-item-mini" data-chess-id="${chess.id}">
|
||||
<div class="bg-yellow-600 text-xs rounded px-1 text-white">${chess.cost}</div>
|
||||
<span class="ml-1 text-sm text-gray-200 truncate">${chess.name}</span>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
content += `</div>`;
|
||||
|
||||
content += `</div></div>`;
|
||||
});
|
||||
}
|
||||
|
||||
// 隐藏加载中状态
|
||||
// 隐藏加载动画并更新内容
|
||||
setTimeout(() => {
|
||||
loadingSpinner.addClass('hidden');
|
||||
|
||||
// 设置内容并显示提示框
|
||||
tooltipContent.html(content);
|
||||
// 模拟内容加载完成的淡入效果
|
||||
modalContent.fadeOut(100, function() {
|
||||
$(this).html(content).fadeIn(150);
|
||||
|
||||
// 显示返回按钮
|
||||
showTooltipBackButton(tooltipContent);
|
||||
// 显示返回按钮(如果有历史记录)
|
||||
showTooltipBackButton(modalContent);
|
||||
|
||||
// 绑定交互事件
|
||||
bindTooltipInteractions(tooltipContent);
|
||||
|
||||
// 所有内容准备好后显示提示框
|
||||
tooltip.removeClass('hidden');
|
||||
} else {
|
||||
// 处理错误
|
||||
tooltipContent.html(`<div class="text-red-400">获取详情失败</div>`);
|
||||
loadingSpinner.addClass('hidden');
|
||||
tooltip.removeClass('hidden');
|
||||
// 绑定棋子点击事件
|
||||
bindTooltipInteractions(modalContent);
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
}).catch(error => {
|
||||
// 处理错误
|
||||
tooltipContent.html(`<div class="text-red-400">请求出错</div>`);
|
||||
setTimeout(() => {
|
||||
loadingSpinner.addClass('hidden');
|
||||
tooltip.removeClass('hidden');
|
||||
modalContent.html(`<div class="text-red-400 p-4">请求出错: ${error.message || '未知错误'}</div>`);
|
||||
modalContent.fadeIn(150);
|
||||
}, 100);
|
||||
|
||||
console.error('获取羁绊详情失败:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示棋子悬停提示
|
||||
* 显示棋子模态框
|
||||
* @param {string} chessId 棋子ID
|
||||
* @param {Element} element 触发元素
|
||||
*/
|
||||
function showChessTooltip(chessId, element) {
|
||||
const tooltip = $('#tft-tooltip');
|
||||
const tooltipContent = tooltip.find('.tooltip-content');
|
||||
const loadingSpinner = tooltip.find('.loading-spinner');
|
||||
|
||||
// 先隐藏提示框,在数据加载完成后再显示
|
||||
tooltip.addClass('hidden');
|
||||
const modal = $('#tft-modal');
|
||||
const modalContent = modal.find('.modal-content');
|
||||
const loadingSpinner = modal.find('.loading-spinner');
|
||||
|
||||
// 重置历史记录
|
||||
tooltipHistory = [];
|
||||
|
||||
// 使用共享方法显示内容
|
||||
showChessTooltipContent(chessId, element, tooltipContent);
|
||||
showChessTooltipContent(chessId, element, modalContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示羁绊悬停提示
|
||||
* 显示羁绊模态框
|
||||
* @param {string} synergyId 羁绊ID
|
||||
* @param {Element} element 触发元素
|
||||
*/
|
||||
function showSynergyTooltip(synergyId, element) {
|
||||
const tooltip = $('#tft-tooltip');
|
||||
const tooltipContent = tooltip.find('.tooltip-content');
|
||||
const loadingSpinner = tooltip.find('.loading-spinner');
|
||||
|
||||
// 先隐藏提示框,在数据加载完成后再显示
|
||||
tooltip.addClass('hidden');
|
||||
const modal = $('#tft-modal');
|
||||
const modalContent = modal.find('.modal-content');
|
||||
const loadingSpinner = modal.find('.loading-spinner');
|
||||
|
||||
// 重置历史记录
|
||||
tooltipHistory = [];
|
||||
|
||||
// 使用共享方法显示内容
|
||||
showSynergyTooltipContent(synergyId, element, tooltipContent);
|
||||
showSynergyTooltipContent(synergyId, element, modalContent);
|
||||
}
|
||||
|
||||
// 存储当前悬停元素ID
|
||||
let currentHoveredId = null;
|
||||
|
||||
/**
|
||||
* 定位提示框
|
||||
* @param {jQuery} tooltip 提示元素
|
||||
* @param {Element} element 触发元素
|
||||
* 初始化模态框交互
|
||||
*/
|
||||
function positionTooltip(tooltip, element) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
function initTooltips() {
|
||||
// 初始化模态框
|
||||
createTooltip();
|
||||
|
||||
// 检测是否为移动设备
|
||||
const isMobile = window.matchMedia("(max-width: 768px)").matches ||
|
||||
('ontouchstart' in window) ||
|
||||
(navigator.maxTouchPoints > 0);
|
||||
|
||||
// 移动设备始终居中显示
|
||||
if (isMobile) {
|
||||
// 移动设备上使用CSS定位在屏幕中央
|
||||
// 样式表中已经设置了固定位置,这里不需要设置left和top
|
||||
tooltip.css({
|
||||
// 重置定位,让CSS的固定定位生效
|
||||
transform: '',
|
||||
maxHeight: `${window.innerHeight * 0.7}px`,
|
||||
zIndex: 1000
|
||||
// 处理棋子触发事件 - 统一使用点击事件
|
||||
$(document).on('click', '.chess-item', function(e) {
|
||||
// 避免在点击移除按钮时显示提示
|
||||
if ($(e.target).closest('.remove-chess').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
// 如果已经点击过同一个元素,则关闭模态框
|
||||
if (currentHoveredId === $(this).data('chess-id') && $('#tft-modal').hasClass('open')) {
|
||||
closeModal();
|
||||
return;
|
||||
}
|
||||
|
||||
const chessId = $(this).data('chess-id');
|
||||
if (chessId) {
|
||||
// 关闭之前可能打开的提示
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
|
||||
currentHoveredId = chessId;
|
||||
showChessTooltip(chessId, this);
|
||||
|
||||
// 添加活跃状态
|
||||
$(this).addClass('tooltip-active');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 桌面设备的定位逻辑
|
||||
const tooltipWidth = 320; // 提示框宽度
|
||||
|
||||
// 计算水平位置,优先显示在右侧
|
||||
let left = rect.right + 10;
|
||||
if (left + tooltipWidth > window.innerWidth) {
|
||||
// 右侧空间不足,显示在左侧
|
||||
left = rect.left - tooltipWidth - 10;
|
||||
// 如果左侧也没有足够空间
|
||||
if (left < 0) {
|
||||
left = Math.max(10, (window.innerWidth - tooltipWidth) / 2); // 居中显示
|
||||
}
|
||||
// 处理羁绊触发事件 - 统一使用点击事件
|
||||
$(document).on('click', '.synergy-item', function(e) {
|
||||
// 避免在点击移除按钮时显示提示
|
||||
if ($(e.target).closest('.remove-synergy').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算垂直位置,考虑提示框不超出屏幕
|
||||
let top = rect.top;
|
||||
const tooltipHeight = Math.min(500, window.innerHeight * 0.8); // 预估高度
|
||||
e.stopPropagation();
|
||||
|
||||
if (top + tooltipHeight > window.innerHeight) {
|
||||
// 尝试显示在元素上方
|
||||
top = Math.max(10, rect.top - tooltipHeight);
|
||||
// 如果已经点击过同一个元素,则关闭模态框
|
||||
if (currentHoveredId === $(this).data('synergy-id') && $('#tft-modal').hasClass('open')) {
|
||||
closeModal();
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置位置
|
||||
tooltip.css({
|
||||
left: `${left}px`,
|
||||
top: `${top}px`,
|
||||
width: 'auto',
|
||||
maxHeight: `${window.innerHeight - 20}px` // 防止溢出屏幕
|
||||
const synergyId = $(this).data('synergy-id');
|
||||
if (synergyId) {
|
||||
// 关闭之前可能打开的提示
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
|
||||
currentHoveredId = synergyId;
|
||||
showSynergyTooltip(synergyId, this);
|
||||
|
||||
// 添加活跃状态
|
||||
$(this).addClass('tooltip-active');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 防抖函数
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return function(...args) {
|
||||
const context = this;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => func.apply(context, args), wait);
|
||||
};
|
||||
// 点击文档其它位置关闭模态框
|
||||
$(document).on('click', function(e) {
|
||||
if (!$(e.target).closest('#tft-modal, .chess-item, .synergy-item').length) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// ESC键关闭模态框
|
||||
$(document).on('keydown', function(e) {
|
||||
if (e.key === 'Escape' && $('#tft-modal').hasClass('open')) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// 处理点击事件,避免与模态框冲突
|
||||
$(document).on('click', '.remove-chess, .remove-synergy', function(e) {
|
||||
e.stopPropagation();
|
||||
closeModal();
|
||||
});
|
||||
|
||||
// 处理窗口滚动时隐藏模态框
|
||||
$(window).on('scroll', function() {
|
||||
if ($('#tft-modal').hasClass('open')) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1296,152 +1367,3 @@ function fetchItemDetails(type, id) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 存储当前悬停元素ID
|
||||
let currentHoveredId = null;
|
||||
|
||||
/**
|
||||
* 初始化悬停提示
|
||||
*/
|
||||
function initTooltips() {
|
||||
// 创建提示框
|
||||
createTooltip();
|
||||
|
||||
const tooltipElement = $('#tft-tooltip');
|
||||
|
||||
// 检测是否为移动设备
|
||||
const isMobile = window.matchMedia("(max-width: 768px)").matches ||
|
||||
('ontouchstart' in window) ||
|
||||
(navigator.maxTouchPoints > 0);
|
||||
|
||||
// 点击文档其它位置关闭提示框
|
||||
$(document).on('click touchend', function(e) {
|
||||
if (!$(e.target).closest('#tft-tooltip, .chess-item, .synergy-item').length) {
|
||||
tooltipElement.addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
}
|
||||
});
|
||||
|
||||
// 处理棋子触发事件
|
||||
$(document).on(isMobile ? 'click' : 'mouseenter', '.chess-item', function(e) {
|
||||
// 避免在点击移除按钮时显示提示
|
||||
if ($(e.target).closest('.remove-chess').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 在移动设备上点击时阻止冒泡
|
||||
if (isMobile) {
|
||||
e.stopPropagation();
|
||||
// 如果已经点击过同一个元素,则关闭提示
|
||||
if (currentHoveredId === $(this).data('chess-id') && tooltipElement.is(':visible')) {
|
||||
tooltipElement.addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
$(this).removeClass('tooltip-active');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const chessId = $(this).data('chess-id');
|
||||
if (chessId) {
|
||||
// 关闭之前可能打开的提示
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
|
||||
currentHoveredId = chessId;
|
||||
|
||||
// 在移动设备上直接显示,非移动设备使用防抖
|
||||
if (isMobile) {
|
||||
showChessTooltip(chessId, this);
|
||||
} else {
|
||||
// 使用防抖函数延迟显示提示
|
||||
debounce((id, element) => {
|
||||
if (currentHoveredId === id) {
|
||||
showChessTooltip(id, element);
|
||||
}
|
||||
}, 50)(chessId, this);
|
||||
}
|
||||
|
||||
// 添加活跃状态
|
||||
$(this).addClass('tooltip-active');
|
||||
}
|
||||
});
|
||||
|
||||
// 处理羁绊触发事件
|
||||
$(document).on(isMobile ? 'click' : 'mouseenter', '.synergy-item', function(e) {
|
||||
// 避免在点击移除按钮时显示提示
|
||||
if ($(e.target).closest('.remove-synergy').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 在移动设备上点击时阻止冒泡
|
||||
if (isMobile) {
|
||||
e.stopPropagation();
|
||||
// 如果已经点击过同一个元素,则关闭提示
|
||||
if (currentHoveredId === $(this).data('synergy-id') && tooltipElement.is(':visible')) {
|
||||
tooltipElement.addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
$(this).removeClass('tooltip-active');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const synergyId = $(this).data('synergy-id');
|
||||
if (synergyId) {
|
||||
// 关闭之前可能打开的提示
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
|
||||
currentHoveredId = synergyId;
|
||||
|
||||
// 在移动设备上直接显示,非移动设备使用防抖
|
||||
if (isMobile) {
|
||||
showSynergyTooltip(synergyId, this);
|
||||
} else {
|
||||
// 使用防抖函数延迟显示提示
|
||||
debounce((id, element) => {
|
||||
if (currentHoveredId === id) {
|
||||
showSynergyTooltip(id, element);
|
||||
}
|
||||
}, 50)(synergyId, this);
|
||||
}
|
||||
|
||||
// 添加活跃状态
|
||||
$(this).addClass('tooltip-active');
|
||||
}
|
||||
});
|
||||
|
||||
// 非移动设备的鼠标离开事件
|
||||
if (!isMobile) {
|
||||
$(document).on('mouseleave', '.chess-item, .synergy-item', function() {
|
||||
currentHoveredId = null;
|
||||
// 移除活跃状态
|
||||
$(this).removeClass('tooltip-active');
|
||||
|
||||
// 检查鼠标是否在提示框上
|
||||
if (!tooltipElement.is(':hover')) {
|
||||
tooltipElement.addClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// 避免提示框本身触发悬停事件
|
||||
tooltipElement.on('mouseenter', function() {
|
||||
// 保持显示
|
||||
}).on('mouseleave', function() {
|
||||
$(this).addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
$('.tooltip-active').removeClass('tooltip-active');
|
||||
});
|
||||
}
|
||||
|
||||
// 处理点击事件,避免与提示框冲突
|
||||
$(document).on('click', '.remove-chess, .remove-synergy', function(e) {
|
||||
e.stopPropagation();
|
||||
tooltipElement.addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
});
|
||||
|
||||
// 处理窗口滚动时隐藏提示
|
||||
$(window).on('scroll', function() {
|
||||
tooltipElement.addClass('hidden');
|
||||
currentHoveredId = null;
|
||||
});
|
||||
}
|
@ -140,6 +140,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详情模态框 -->
|
||||
<div id="tft-modal-backdrop"></div>
|
||||
<div id="tft-modal">
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal-content"></div>
|
||||
<div class="loading-spinner absolute inset-0 flex items-center justify-center bg-gray-800 bg-opacity-90 hidden rounded-lg">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="animate-spin rounded-full h-10 w-10 border-b-2 border-t-2 border-indigo-500 mb-2"></div>
|
||||
<div class="text-xs text-indigo-300">加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="modal-close-btn">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<h1 class="text-3xl font-bold text-center text-indigo-600 mb-8">云顶之弈阵容推荐器</h1>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user