Range Slider Tooltip悬停Thumb时消失及居中问题求助
解决方案:Range Slider Tooltip 始终显示并居中于滑块顶部
问题分析
- Tooltip悬停消失:代码中给滑块thumb绑定了
mouseout事件,当鼠标从thumb移到Tooltip上时会触发该事件,导致Tooltip被隐藏;同时你需要Tooltip始终可见,这些事件监听完全多余。 - Tooltip无法居中:当前代码仅将Tooltip的左边缘对齐thumb的左边缘,未考虑Tooltip自身宽度,导致无法居中。
修改步骤
1. 移除多余的鼠标事件监听
删除以下代码块:
thumbLeft.addEventListener("mouseover", function() { tooltipLeft.style.display = "block"; }); thumbLeft.addEventListener("mouseout", function() { tooltipLeft.style.display = "none"; }); thumbRight.addEventListener("mouseover", function() { tooltipRight.style.display = "block"; }); thumbRight.addEventListener("mouseout", function() { tooltipRight.style.display = "none"; });
2. 调整Tooltip的CSS样式
更新.tooltip的CSS,添加水平居中的变换:
.tooltip { position: absolute; display: none; background-color: #1C64F2; color: #FFFFFF; padding: var(--05, 2px) var(--2, 8px); border-radius: 5px; font-size: 12px; white-space: nowrap; opacity: 1; transform: translateX(-50%); /* 添加这行实现水平居中 */ }
3. 修正Tooltip位置计算逻辑
更新updateTooltipPosition函数,让Tooltip精准居中于thumb顶部:
function updateTooltipPosition() { var thumbLeftPosition = thumbLeft.getBoundingClientRect(); var thumbRightPosition = thumbRight.getBoundingClientRect(); // 获取父容器的偏移量,避免滚动时位置偏移 var containerOffset = document.querySelector('.middle').getBoundingClientRect(); tooltipLeft.style.display = "block"; // 左Tooltip:left设置为thumb中心,top设置为thumb顶部上方 tooltipLeft.style.left = (thumbLeftPosition.left - containerOffset.left + thumbLeftPosition.width / 2) + "px"; tooltipLeft.style.top = (thumbLeftPosition.top - containerOffset.top - tooltipLeft.offsetHeight - 5) + "px"; tooltipLeft.innerHTML = PriceMinSlider.value; tooltipRight.style.display = "block"; // 右Tooltip:同样设置为thumb中心和顶部上方 tooltipRight.style.left = (thumbRightPosition.left - containerOffset.left + thumbRightPosition.width / 2) + "px"; tooltipRight.style.top = (thumbRightPosition.top - containerOffset.top - tooltipRight.offsetHeight - 5) + "px"; tooltipRight.innerHTML = PriceMaxSlider.value; }
注:添加容器偏移量计算是为了避免页面滚动时Tooltip位置出现偏差,因为
getBoundingClientRect()返回的是相对于视口的位置,减去容器的视口偏移后得到相对于父容器的位置,更准确。
完整修改后的代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"> <link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'> <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <style> .middle { position: relative; width: 100%; max-width: 500px; } .slider { position: relative; z-index: 1; height: var(--2, 8px); } .slider>.track { position: absolute; z-index: 1; left: 0; right: 0; top: 0; bottom: 0; border-radius: 5px; background-color: #E5E7EB; } .slider>.range { position: absolute; z-index: 2; left: 25%; right: 25%; top: 0; bottom: 0; border-radius: 5px; background-color: #1C64F2; } .slider>.thumb { position: absolute; z-index: 3; width: 22px; height: 22px; background-color: #FFFFFF; border-radius: 50%; box-shadow: 0 0 0 0 rgba(98, 0, 238, .1); transition: box-shadow .3s ease-in-out; stroke-width: 1px; stroke: var(--gray-200, #E5E7EB); filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.08)); } .slider>.thumb.left { left: 25%; transform: translate(-15px, -10px); } .slider>.thumb.right { right: 25%; transform: translate(15px, -10px); } input[type=range] { position: absolute; pointer-events: none; -webkit-appearance: none; z-index: 2; height: 10px; width: 100%; opacity: 0; } input[type=range]::-webkit-slider-thumb { pointer-events: all; width: 22px; height: 22px; border-radius: 0; border: 0 none; background-color: red; -webkit-appearance: none; } .tooltip { position: absolute; display: none; background-color: #1C64F2; color: #FFFFFF; padding: var(--05, 2px) var(--2, 8px); border-radius: 5px; font-size: 12px; white-space: nowrap; opacity: 1; transform: translateX(-50%); /* 添加水平居中变换 */ } </style> </head> <body> <div class="price-range-section mt-5"> <label for="Price Range">Price Range</label> <div class="middle"> <div class="multi-range-slider"> <input type="range" id="price-min-slider" min="0" max="100" value="25"> <input type="range" id="price-max-slider" min="0" max="100" value="75"> <div class="slider"> <div class="track"></div> <div class="range"></div> <div class="thumb left"></div> <div class="thumb right"></div> </div> <!-- Tooltips --> <div class="tooltip" id="tooltip-left"></div> <div class="tooltip" id="tooltip-right"></div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> <script> var PriceMinSlider = document.getElementById("price-min-slider"); var PriceMaxSlider = document.getElementById("price-max-slider"); var thumbLeft = document.querySelector(".slider > .thumb.left"); var thumbRight = document.querySelector(".slider > .thumb.right"); var range = document.querySelector(".slider > .range"); var tooltipLeft = document.getElementById("tooltip-left"); var tooltipRight = document.getElementById("tooltip-right"); function setLeftValue() { var _this = PriceMinSlider, min = parseInt(_this.min), max = parseInt(_this.max); _this.value = Math.min(parseInt(_this.value), parseInt(PriceMaxSlider.value) - 1); var percent = ((_this.value - min) / (max - min)) * 100; thumbLeft.style.left = percent + "%"; range.style.left = percent + "%"; updateTooltipPosition(); } setLeftValue(); function setRightValue() { var _this = PriceMaxSlider, min = parseInt(_this.min), max = parseInt(_this.max); _this.value = Math.max(parseInt(_this.value), parseInt(PriceMinSlider.value) + 1); var percent = ((_this.value - min) / (max - min)) * 100; thumbRight.style.right = (100 - percent) + "%"; range.style.right = (100 - percent) + "%"; updateTooltipPosition(); } setRightValue(); function updateTooltipPosition() { var thumbLeftPosition = thumbLeft.getBoundingClientRect(); var thumbRightPosition = thumbRight.getBoundingClientRect(); // 获取父容器的视口偏移量 var containerOffset = document.querySelector('.middle').getBoundingClientRect(); tooltipLeft.style.display = "block"; // 计算相对于父容器的left和top,确保居中且在顶部 tooltipLeft.style.left = (thumbLeftPosition.left - containerOffset.left + thumbLeftPosition.width / 2) + "px"; tooltipLeft.style.top = (thumbLeftPosition.top - containerOffset.top - tooltipLeft.offsetHeight - 5) + "px"; tooltipLeft.innerHTML = PriceMinSlider.value; tooltipRight.style.display = "block"; tooltipRight.style.left = (thumbRightPosition.left - containerOffset.left + thumbRightPosition.width / 2) + "px"; tooltipRight.style.top = (thumbRightPosition.top - containerOffset.top - tooltipRight.offsetHeight - 5) + "px"; tooltipRight.innerHTML = PriceMaxSlider.value; } PriceMinSlider.addEventListener("input", setLeftValue); PriceMaxSlider.addEventListener("input", setRightValue); PriceMinSlider.addEventListener("mousedown", function() { thumbLeft.classList.add("active"); }); PriceMinSlider.addEventListener("mouseup", function() { thumbLeft.classList.remove("active"); }); PriceMaxSlider.addEventListener("mousedown", function() { thumbRight.classList.add("active"); }); PriceMaxSlider.addEventListener("mouseup", function() { thumbRight.classList.remove("active"); }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者Rejuan hossain
相关产品推荐
相关产品推荐

