不推荐用 scroll-view 做横向跑马灯,因其不支持无缝循环且 iOS 易卡顿;应优先采用 CSS 动画+双份文案拼接,配合动态 duration 计算与多端适配策略。

uni-app 中用 scroll-view 实现文字超出自动滚动(跑马灯)
直接结论:不推荐用 scroll-view 做横向跑马灯,它默认不支持「无缝循环滚动」,且在 iOS 上容易卡顿、跳帧;真要硬上,必须手动控制 scroll-left + 定时器 + 重置逻辑,但兼容性差、维护成本高。
更稳妥的做法是用原生 CSS 动画 + 重复文本拼接,配合 white-space: nowrap 和 animation 控制位移。关键点在于让动画结束时视觉上「看不出断点」。
- 必须复制两份文案(如
"公告内容公告内容"),否则滚动到末尾会留白 - 动画时长要和内容长度匹配:
animation-duration越长,滚动越慢;建议动态计算(例如每 10px 内容对应 1s) - H5 端可用
@keyframes,但小程序端(微信/支付宝/uni-app)需注意:微信基础库 2.23.0+ 才支持animation-fill-mode: forwards,低版本需 fallback 到 JS 定时滚动
uni-app 跑马灯组件中如何判断文字是否溢出容器
不能靠 offsetWidth > clientWidth 直接测——因为 uni-app 的 view 在不同平台渲染时机不一致,onReady 阶段 DOM 可能还没完全挂载,尤其在 v-for 渲染多个跑马灯时容易误判。
推荐做法:用 uni.createSelectorQuery() 延迟到下一帧再查尺寸,并加防抖。
- 在
mounted后调用setTimeout(() => { ... }, 0)或nextTick(Vue 2)/nextTick(Vue 3)确保节点已渲染 - 查询目标元素时,务必指定
in(this),否则跨组件查不到(尤其用了scoped样式) - 示例关键代码:
const query = uni.createSelectorQuery().in(this); query.select('.marquee-text').boundingClientRect(); query.exec(res => { const rect = res[0]; if (rect && rect.width > rect.right - rect.left) { this.isOverflow = true; } });
微信小程序里跑马灯突然停住或闪退的常见原因
不是代码逻辑错,大概率是微信原生限制触发了性能保护:当一个页面内同时运行多个 animation 或频繁修改 style 的 translateX,iOS 微信会主动降帧甚至中断动画。
- 避免在
v-for中每个 item 都独立跑马灯,改用单个容器 + 多行文本拼接(用\n换行 +white-space: pre-line) - 禁用
transform: translateX()的硬件加速(即不要加will-change: transform),反而更稳——微信底层对强制 GPU 加速的处理不一致 - 如果用了自定义字体(
@font-face),首次加载时文字宽度会变化,导致滚动错位,建议等fontLoaded事件后再启动动画(需自行监听)
uni-app 跑马灯组件如何适配多端(H5 / 微信 / App)
核心矛盾在于:H5 支持完整 CSS 动画属性,小程序只支持子集,App(基于 WebView)又依赖底层 Chromium 版本。没有一套写法能通吃,必须分端处理。
- H5 端优先用
@keyframes + animation,支持infinite linear,最省资源 - 微信/支付宝小程序用
animationAPI(uni.createAnimation),但注意:它不支持「无限循环」,必须手动onAnimationEnd重播,且每次重播要export新实例 - App 端若发现滚动卡顿,可降级为 JS 定时器 +
scroll-left(仅限scroll-view),但要设scroll-with-animation="false"关闭自带动画,否则叠加导致撕裂 - 统一入口建议封装成
Marquee.vue,通过uni.getSystemInfoSync().platform判断平台后动态启用对应实现
实际最难的不是滚动本身,而是让「滚动看起来自然」——比如用户快速切后台再切回来,动画不能跳帧或重头开始;还有长文案在窄屏上滚动速度该不该变;这些细节没标准答案,得靠真实设备反复测。











