HTML/CSS/JS文本左右滚动条故障:无法实现滚动效果求助
文本滚动条组件无法实现左右滚动的问题修复
我正在使用HTML、CSS和JavaScript开发一款文本滚动条组件,但遇到了技术问题:该滚动条无法实现左右滚动效果。以下是对应的实现代码:
JavaScript代码
document.addEventListener("DOMContentLoaded", function() { var element = document.getElementById("text-roller"); var text_roller = new TextRoller(element); text_roller.start(); }); var TextRoller = (function() { //Helper functions function getWidth(element) { var rect = element.getBoundingClientRect(); return rect.right - rect.left; } function TextRoller(box, speed = 20) { var inner_element = box.children && box.children[0] || null; if (!inner_element) throw "No child node found"; inner_element.style.position = "relative"; this.position = 0; this.speed = speed; this.box_width = getWidth(box); this.inner_element_width = getWidth(inner_element); this.box = box; this.inner_element = inner_element.cloneNode(true); setUpChildrens.call(this); } //Private functions function refreshWidths() { this.box_width = getWidth(this.box); this.inner_element_width = getWidth(this.box.children[0]); } function calculateNumElements() { return 1; } function setUpChildrens() { var qty = calculateNumElements.call(this); if (qty > this.box.children.length) { for (var i = this.box.children.length; i < qty; i++) this.box.appendChild(this.inner_element.cloneNode(true)); } else if (qty < this.box.children.length) { for (var i = qty; i < this.box.children.length; i++) this.box.removeChild(this.box.lastChild); } } function nextFrame(delta) { var self = this; refreshWidths.call(this); setUpChildrens.call(this); Array.prototype.forEach.call(this.box.children, function(el) { el.style.left = -self.position + "px"; }); this.position += this.speed * delta / 300; if (this.position >= this.inner_element_width) this.position = this.position % this.inner_element_width; } TextRoller.prototype = { start: function() { this._running = true; var self = this; var last_time = null; var loop_func = function() { if (!self._running) return; var now = Date.now(); var delta = last_time === null ? 0 : now - last_time; nextFrame.call(self, delta); last_time = now; window.requestAnimationFrame(loop_func); }; window.requestAnimationFrame(loop_func); }, stop: function() { this._running = false; } }; return TextRoller; })();
CSS代码
#text-roller { padding: 20px; position: relative; background-color: #88191d; color: black; white-space: nowrap; overflow: hidden; } .swiper-wrapper { display: -webkit-inline-box; text-align: center; } .swiper-wrapper div h2 { color: white !important; }
HTML代码
<div id="text-roller"> <div class="swiper-pointer-events"> <div class="swiper-wrapper"> <div style="width: 4% ;"> <h2>Interaction</h2> </div> <div style="width: 4% ;"> <h2>Element</h2> </div> <div style="width: 6% ;"> <h2>DIgital SOlution</h2> </div> <div style="width: 4% ;"> <h2>Strategy</h2> </div> <div style="width: 4% ;"> <h2>Branding</h2> </div> <div style="width: 4% ;"> <h2>Agency</h2> </div> <div style="width: 4% ;"> <h2>Interaction</h2> </div> <div style="width: 6% ;"> <h2>DIgital SOlution</h2> </div> <div style="width: 4% ;"> <h2>Development</h2> </div> <div style="width: 4% ;"> <h2>Studio</h2> </div> <div style="width: 4% ;"> <h2>Strategy</h2> </div> <div style="width: 4% ;"> <h2>Branding</h2> </div> <div style="width: 4% ;"> <h2>Agency</h2> </div> <div style="width: 4% ;"> <h2>typhography</h2> </div> <div style="width: 4% ;"> <h2>Design</h2> </div> <div style="width: 4% ;"> <h2>Interaction</h2> </div> <div style="width: 4% ;"> <h2>Element</h2> </div> <div style="width: 6% ;"> <h2>DIgital SOlution</h2> </div> <div style="width: 4% ;"> <h2>Strategy</h2> </div> <div style="width: 4% ;"> <h2>Branding</h2> </div> <div style="width: 4% ;"> <h2>Agency</h2> </div> <div style="width: 4% ;"> <h2>Interaction</h2> </div> <div style="width: 6% ;"> <h2>DIgital SOlution</h2> </div> <div style="width: 4% ;"> <h2>Development</h2> </div> <div style="width: 4% ;"> <h2>Studio</h2> </div> <div style="width: 4% ;"> <h2>Strategy</h2> </div> <div style="width: 4% ;"> <h2>Branding</h2> </div> <div style="width: 4% ;"> <h2>Agency</h2> </div> <div style="width: 4% ;"> <h2>typhography</h2> </div> <div style="width: 4% ;"> <h2>Design</h2> </div> <div style="width: 4% ;"> <h2>Interaction</h2> </div> </div> </div> </div>
问题分析与修复方案
核心问题
- 滚动目标错误:当前代码操作的是
#text-roller的直接子元素.swiper-pointer-events,但实际需要滚动的是内部的.swiper-wrapper——所有文本项都在这个容器里。 - 容器宽度计算错误:
inner_element_width获取的是.swiper-pointer-events的宽度,而非.swiper-wrapper的总宽度,导致滚动重置逻辑失效。 - 无限滚动元素数量不足:
calculateNumElements固定返回1,无法实现无缝滚动的循环效果。
修复步骤
1. 修正滚动目标元素
在TextRoller构造函数中,直接定位到实际需要滚动的.swiper-wrapper:
function TextRoller(box, speed = 20) { // 找到内部的swiper-wrapper作为滚动容器 var inner_element = box.querySelector('.swiper-wrapper') || null; if (!inner_element) throw "No swiper-wrapper found"; inner_element.style.position = "relative"; this.position = 0; this.speed = speed; this.box_width = getWidth(box); this.inner_element_width = getWidth(inner_element); this.box = box; this.inner_element = inner_element.cloneNode(true); setUpChildrens.call(this); }
2. 调整无限滚动元素数量计算
修改calculateNumElements,确保至少有2个副本实现无缝循环:
function calculateNumElements() { // 计算需要多少个副本才能覆盖容器宽度+一个完整内容宽度,实现无缝滚动 return Math.ceil((this.box_width + this.inner_element_width) / this.inner_element_width); }
3. 优化滚动逻辑
移除nextFrame中不必要的重复调用,并调整滚动重置逻辑:
function nextFrame(delta) { var self = this; Array.prototype.forEach.call(this.box.querySelectorAll('.swiper-wrapper'), function(el) { el.style.left = -self.position + "px"; }); this.position += this.speed * delta / 300; if (this.position >= this.inner_element_width) { // 滚动过一个完整宽度后,重置位置实现循环 this.position -= this.inner_element_width; } }
4. 调整CSS样式
确保.swiper-pointer-events不会限制子元素宽度:
.swiper-pointer-events { width: fit-content; }
修复后效果
修改后,文本容器会持续向左滚动,当第一个副本完全移出视野后,第二个副本会无缝衔接,实现无限循环的左右滚动效果。
内容的提问来源于stack exchange,提问作者Noman Laghari
相关产品推荐
相关产品推荐

