做一个公告栏,要求在首页顶部横向滚一条通知。用 setInterval 每 30 毫秒改一次 translateX,H5 上看着还行,打包到小程序里帧率掉到个位数,安卓机还闪。问题不在写法对不对,是数据驱动的方式不适合高频动画。

纵向滚动优先用 swiper

一条一条往上翻的那种跑马灯,直接用 swiper 组件,vertical 设 true,autoplay 开起来,circular 打开循环,interval 给 3000。三行公告放三个 swiper-item,翻页动画交给原生组件做,性能没问题,也不会在后台被降频卡住。

这种方案在小程序、App、H5 上表现一致,维护成本最低。缺点是只能整条翻,做不了连续滚动的效果。

要连续滚动就用 CSS 动画

思路是把内容渲染两份首尾相接,容器宽度由内容决定,整体用 transform 平移一份内容的宽度,动画结束瞬间复位,视觉上看不出接缝。

animation: marquee 12s linear infinite;

关键帧里只写 transform,left 和 margin 会触发重排,安卓低端机上很容易卡。时长按内容长度算,不要写死 10 秒,长文案会滚得飞快。

  • 宽度用 px 或 auto,rpx 在不同屏宽下换算比例不同,接缝处会跳一下。
  • 动画元素加 will-change transform,部分机型能提到合成层。
  • 页面隐藏时用 v-if 或 CSS 暂停动画,小程序切后台回来动画会重置,看着像卡了一帧。

别在这些地方栽跟头

用 setData 高频更新是实现跑马灯最常见也最糟的方式,每次 setData 都要跨线程通信,几十毫秒一次直接拖垮渲染。真要 JS 控制,用 requestAnimationFrame 改 transform 值,并且确认平台支持。

内容里带富文本标签时,先把标签转成纯文本再渲染,跑马灯里的链接点不到,还可能撑破高度。字号统一,别让外层 line-height 影响垂直居中。

做之前先想清楚是翻页还是连续滚。翻页用 swiper 十几行搞定,连续滚才需要上 CSS 动画,两套方案别混着写。