diff --git a/src/web/static/css/style.css b/src/web/static/css/style.css index 7deef8e..565c02d 100644 --- a/src/web/static/css/style.css +++ b/src/web/static/css/style.css @@ -204,4 +204,67 @@ border-left: 3px solid #4f46e5; padding-left: 5px; border-radius: 4px; +} + +/* 移动设备上的提示框样式优化 */ +@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.2s ease-out; + } + + #tft-tooltip .close-tooltip { + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(79, 70, 229, 0.2); + border-radius: 50%; + opacity: 0.9; + } + + #tft-tooltip .tooltip-content { + margin-top: 5px; + padding-right: 15px; + } + + /* 增大移动端触摸目标大小 */ + .chess-item-mini, .synergy-item-mini { + padding: 10px; + margin-bottom: 8px; + } + + /* 移动端使用更明显的交互提示 */ + .chess-item-mini::after, .synergy-item-mini::after { + content: '点击查看'; + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); + color: rgba(99, 102, 241, 0.8); + font-size: 10px; + opacity: 0.8; + } + + /* 提示框返回按钮优化 */ + .tooltip-back-button { + width: 36px; + height: 36px; + opacity: 0.9; + background-color: rgba(79, 70, 229, 0.8); + } + + @keyframes mobileTooltipFadeIn { + from { + opacity: 0; + transform: translateY(10px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } + } } \ No newline at end of file diff --git a/src/web/static/js/main.js b/src/web/static/js/main.js index 8434f62..8ff5c43 100644 --- a/src/web/static/js/main.js +++ b/src/web/static/js/main.js @@ -658,20 +658,43 @@ function toggleActiveChessVisibility(showOnlyActive) { let tooltipHistory = []; /** - * 创建悬停提示 + * 创建提示框 */ function createTooltip() { - // 创建提示元素 - if ($('#tft-tooltip').length === 0) { - $('body').append(` - - `); + // 如果已经存在提示框,不重复创建 + if ($('#tft-tooltip').length) { + return; } + + const tooltip = $(` + + `); + + // 添加到页面 + $('body').append(tooltip); + + // 绑定关闭按钮事件 + tooltip.find('.close-tooltip').on('click', function(e) { + e.stopPropagation(); + tooltip.addClass('hidden'); + currentHoveredId = null; + $('.tooltip-active').removeClass('tooltip-active'); + }); + + // 防止点击提示框本身触发关闭 + tooltip.on('click', function(e) { + e.stopPropagation(); + }); } /** @@ -1069,34 +1092,65 @@ function showSynergyTooltip(synergyId, element) { */ function positionTooltip(tooltip, element) { const rect = element.getBoundingClientRect(); - const tooltipWidth = 320; // 提示框宽度 + const isMobile = window.matchMedia("(max-width: 768px)").matches || + ('ontouchstart' in window) || + (navigator.maxTouchPoints > 0); - // 计算水平位置,优先显示在右侧 - 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); // 居中显示 + // 移动设备优先考虑居中显示 + if (isMobile) { + const tooltipWidth = Math.min(320, window.innerWidth - 40); // 在小屏幕上适当缩小 + let left = Math.max(20, (window.innerWidth - tooltipWidth) / 2); + + // 移动设备上优先显示在元素下方,占据更多空间 + let top = rect.bottom + 10; + + // 如果元素已经在视窗下方,则显示在元素上方 + if (top > window.innerHeight / 2) { + top = Math.max(20, rect.top - 300); // 预留足够空间显示内容 } + + // 设置最大高度,确保提示框不会占满整个屏幕 + const maxHeight = window.innerHeight - top - 20; + + tooltip.css({ + left: `${left}px`, + top: `${top}px`, + width: `${tooltipWidth}px`, + maxHeight: `${maxHeight}px`, + zIndex: 1000 // 确保在移动设备上能覆盖其他元素 + }); + } 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); // 居中显示 + } + } + + // 计算垂直位置,考虑提示框不超出屏幕 + let top = rect.top; + const tooltipHeight = Math.min(500, window.innerHeight * 0.8); // 预估高度 + + if (top + tooltipHeight > window.innerHeight) { + // 尝试显示在元素上方 + top = Math.max(10, rect.top - tooltipHeight); + } + + // 设置位置 + tooltip.css({ + left: `${left}px`, + top: `${top}px`, + width: 'auto', + maxHeight: `${window.innerHeight - 20}px` // 防止溢出屏幕 + }); } - - // 计算垂直位置,考虑提示框不超出屏幕 - let top = rect.top; - const tooltipHeight = Math.min(500, window.innerHeight * 0.8); // 预估高度 - - if (top + tooltipHeight > window.innerHeight) { - // 尝试显示在元素上方 - top = Math.max(10, rect.top - tooltipHeight); - } - - // 设置位置 - tooltip.css({ - left: `${left}px`, - top: `${top}px`, - maxHeight: `${window.innerHeight - 20}px` // 防止溢出屏幕 - }); } // 防抖函数 @@ -1155,72 +1209,128 @@ function initTooltips() { const tooltipElement = $('#tft-tooltip'); - // 棋子悬停事件 - 使用防抖 - const debouncedShowChessTooltip = debounce((chessId, element) => { - if (currentHoveredId === chessId) { - showChessTooltip(chessId, element); - } - }, 50); + // 检测是否为移动设备 + const isMobile = window.matchMedia("(max-width: 768px)").matches || + ('ontouchstart' in window) || + (navigator.maxTouchPoints > 0); - $(document).on('mouseenter', '.chess-item', function(e) { + // 点击文档其它位置关闭提示框 + $(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; - debouncedShowChessTooltip(chessId, this); + + // 在移动设备上直接显示,非移动设备使用防抖 + if (isMobile) { + showChessTooltip(chessId, this); + } else { + // 使用防抖函数延迟显示提示 + debounce((id, element) => { + if (currentHoveredId === id) { + showChessTooltip(id, element); + } + }, 50)(chessId, this); + } // 添加活跃状态 $(this).addClass('tooltip-active'); } }); - // 羁绊悬停事件 - 使用防抖 - const debouncedShowSynergyTooltip = debounce((synergyId, element) => { - if (currentHoveredId === synergyId) { - showSynergyTooltip(synergyId, element); - } - }, 50); - - $(document).on('mouseenter', '.synergy-item', function(e) { + // 处理羁绊触发事件 + $(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; - debouncedShowSynergyTooltip(synergyId, this); + + // 在移动设备上直接显示,非移动设备使用防抖 + if (isMobile) { + showSynergyTooltip(synergyId, this); + } else { + // 使用防抖函数延迟显示提示 + debounce((id, element) => { + if (currentHoveredId === id) { + showSynergyTooltip(id, element); + } + }, 50)(synergyId, this); + } // 添加活跃状态 $(this).addClass('tooltip-active'); } }); - // 离开时隐藏提示 - $(document).on('mouseleave', '.chess-item, .synergy-item', function() { - currentHoveredId = null; - // 移除活跃状态 - $(this).removeClass('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'); + } + }); - // 检查鼠标是否在提示框上 - if (!tooltipElement.is(':hover')) { - tooltipElement.addClass('hidden'); - } - }); - - // 避免提示框本身触发悬停事件 - tooltipElement.on('mouseenter', function() { - // 保持显示 - }).on('mouseleave', function() { - $(this).addClass('hidden'); - currentHoveredId = null; - $('.tooltip-active').removeClass('tooltip-active'); - }); + // 避免提示框本身触发悬停事件 + 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) {