真机可用的无缝滚动公告需用 scroll-view + scroll-left 手动驱动,通过双列表拼接与临界重置实现视觉连续;禁用 swiper circular,避免 iOS 跳变与安卓卡顿;注意 white-space、inline-block、number 类型 scroll-left 及真机像素步长优化。

uni-app里用swiper做无限滚动公告,别直接套抖音逻辑
抖音式“无缝循环”在 uni-app 里不能靠单纯加 autoplay 和 circular 实现——swiper 的 circular 在 iOS 上有视觉跳变,安卓部分机型也会卡顿一帧,公告类场景下用户一眼就能察觉“闪一下”。真正要的是视觉连续、无停顿、不依赖原生 swiper 动画节奏的方案。
核心思路:用两个相同列表拼接(A+B),滚动到临界点时瞬间重置偏移量,保持视口内内容不变,人眼感知不到跳转。
- 公告数据必须是数组,建议至少 3 条以上,否则拼接后仍显单薄
- 不要用
swiper的current控制滚动,改用scroll-view+scroll-left手动驱动 - 滚动速度用
setInterval+scroll-left递增,比autoplay更可控 - 重置时机不是等滚到底,而是当
scroll-left≥ 单条公告宽度 × 原始数组长度时立刻设为 0
scroll-view 实现无缝滚动的关键参数和陷阱
uni-app 的 scroll-view 默认开启 scroll-x 后,若内容宽度不够会自动撑开,导致无法水平滚动。必须显式设置 white-space: nowrap 和子元素 display: inline-block,否则文字换行或宽度计算错乱。
从视频画面中提取文字与公式的本地 OCR 技能:支持抖音、快手、B站、YouTube 等平台视频链接下载,也支持本地视频文件;基于 ffmpeg + tesseract 纯本地处理,零 token 消耗。适用于提取烧录字幕、屏幕公式、PPT 文字、图表标注、课程讲义等。This skill should be used when the user provides a video link or local video and wants the on-screen text/formulas extra
常见错误:scroll-left 绑定的是 number 类型,但初始值写成字符串 "0",会导致后续 += 运算变成字符串拼接(如 "0" + 10 → "010")。
- 父容器必须设固定宽度(如
width: 750rpx),且scroll-view加overflow: hidden - 每个公告项用
view包裹,设display: inline-block; vertical-align: top -
scroll-left值需实时响应,推荐用watch监听或onPageScroll模拟节流更新 - 避免在
scroll-view内放rich-text或图片,它们可能触发重绘抖动
代码示例:可直接粘贴的最小可行版本
<template>
<scroll-view
class="marquee"
scroll-x
:scroll-left="scrollLeft"
:scroll-with-animation="false"
@scroll="onScroll"
>
<view class="marquee-list">
<view
v-for="(item, i) in marqueeData.concat(marqueeData)"
:key="i"
class="marquee-item"
>
{{ item.text }}
</view>
</view>
</scroll-view>
</template>
<p><script>
export default {
data() {
return {
scrollLeft: 0,
marqueeData: [
{ text: '【新品上线】uni-app 4.3 支持 Vue 3.4 响应式语法' },
{ text: '【重要通知】微信小程序基础库最低要求升至 2.28.0' },
{ text: '【限时活动】DCloud 开发者大会门票 8 折预售中' }
],
itemWidth: 0,
timer: null
}
},
mounted() {
this.initMarquee()
},
methods: {
initMarquee() {
// 实际项目中建议用 uni.createSelectorQuery()
// 这里简化:假设每条宽约 400rpx,可根据字体大小微调
this.itemWidth = 400
this.timer = setInterval(() => {
this.scrollLeft += 1
if (this.scrollLeft >= this.itemWidth * this.marqueeData.length) {
this.scrollLeft = 0
}
}, 30)
},
onScroll(e) {
// 可选:用于调试滚动位置
// console.log('scroll-left:', e.detail.scrollLeft)
}
},
beforeUnmount() {
if (this.timer) clearInterval(this.timer)
}
}
</script></p><p><style>
.marquee {
width: 750rpx;
height: 60rpx;
overflow: hidden;
}
.marquee-list {
white-space: nowrap;
}
.marquee-item {
display: inline-block;
vertical-align: top;
padding: 0 20rpx;
font-size: 24rpx;
line-height: 60rpx;
color: #ff5777;
}
</style>真机测试时最容易忽略的三个细节
模拟器跑通 ≠ 真机可用。iOS 微信、支付宝、快应用对 scroll-view 的 scroll-left 更新频率容忍度极低,稍不注意就卡住或跳回起点。
- 滚动步长别设
1,改成1.2或1.5,避免某些安卓 WebView 对整数像素渲染优化过度 - 不要在
setInterval里调用this.$forceUpdate(),它会触发整个组件重绘,直接拖慢滚动帧率 - 如果公告含图标或小图,务必用
image标签并设固定width/height,否则图片加载完成前宽度为 0,导致scroll-left计算偏移失效
滚动本身不难,难的是让不同平台都“看起来没在滚动”。多测几台低端安卓机,再看一遍 iOS 微信,基本就知道哪行样式该砍了。


















