news 2026/9/12 10:48:01

Vant RollingText 翻滚文本组件实战指南:数字与文本翻滚动效的配置、原理与手动控制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vant RollingText 翻滚文本组件实战指南:数字与文本翻滚动效的配置、原理与手动控制

Vant RollingText 翻滚文本组件实战指南:数字与文本翻滚动效的配置、原理与手动控制

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

RollingText(翻滚文本)是 Vant 移动端组件库提供的一款文本翻滚动效组件,可以像老虎机一样翻滚数字,也可以翻滚任意等长文本,常用于大屏数据看板、金额/人数等统计数字的播报场景。本文基于当前仓库中 Vant 4.10.0 的组件实现,完整讲解 RollingText 的全部属性、实例方法、样式定制方式,并结合源码剖析其位数补零、数字序列构建、CSS 关键帧动画与实例方法暴露等底层原理,帮助你在项目中快速落地可复用的翻滚动效。

组件简介与版本要求

RollingText 组件位于 packages/vant/src/rolling-text,由RollingText.tsx(外层组件)、RollingTextItem.tsx(单个数位子组件)、index.less(样式)、types.ts(类型定义)组成,并通过 index.ts 使用withInstall封装为可全局注册的插件。

使用该组件需要将vant升级到>= 4.6.0版本(当前仓库packages/vant/package.json中的版本为4.10.0)。它基于 Vue 3 编写,依赖vue: ^3.0.0

组件支持两类翻滚内容:

  • 数字:通过start-num/target-num指定起始与目标数值,自动完成翻滚;
  • 非数字文本:通过text-list传入等长字符串数组,从第一项翻滚到最后一项。

引入组件

在应用入口通过app.use()全局注册组件,即可在模板中使用<van-rolling-text>

import { createApp } from 'vue'; import { RollingText } from 'vant'; const app = createApp(); app.use(RollingText);

注册后组件会以van-rolling-text的标签名全局可用。除全局注册外,也支持按需引入与局部注册,更多注册方式可参考 组件注册。从 index.ts 的声明可以看到,组件还会向 Vue 全局组件类型中注入VanRollingText,因此在 TypeScript 项目中可以直接获得模板内的类型提示。

代码演示与属性详解

基础用法:从起始数值翻滚到目标数值

通过start-num设置起始数值,target-num设置目标数值。RollingText 默认会在组件挂载后自动开始动画,从起始数值翻滚到目标数值:

<van-rolling-text :start-num="0" :target-num="123" />

这里有两个细节值得说明:

  1. 位数取两者较大者:从 RollingText.tsx 的源码看,数字场景下itemLengthMath.max(startNum, targetNum)的字符串长度,即start-num="0"target-num="123"时按 3 位渲染。
  2. 自动补零:起始与目标数字都会经过工具函数padZero(定义于 utils/format.ts)按itemLength补齐前导零,所以0会被渲染成000,再翻滚到123,视觉效果整齐一致。

设置翻滚方向:down 与 up

direction属性控制数字的翻滚方向,默认值为down(向下翻滚),设置为up即向上翻滚:

<van-rolling-text :start-num="0" :target-num="432" direction="up" />

对应源码中direction的类型为RollingTextDirection,取值只有'up' | 'down'(见 types.ts),通过makeStringProp('down')声明默认值。

方向在底层是如何实现的?在 RollingTextItem.tsx 中,每个数位会先根据方向构造滚动序列:

  • down(向下翻滚):将数字序列slice().reverse()反转,初始位置在序列底部(translateY(-总高度)),随后动画从底部滚回顶部,视觉上表现为数字自上而下滚落;
  • up(向上翻滚):保持序列顺序,动画从顶部滚到底部。

方向还会以 BEM 修饰类van-rolling-text-item--down/--up的形式作用于根节点,配合 index.less 中两套@keyframesvan-downvan-up)驱动位移,具体动画机制见下文“动画原理”一节。

设置各数位停止顺序:ltr 与 rtl

stop-order属性控制各个数位动画的停止先后顺序,默认ltr(先停高位,即最左边先停),设置为rtl则先从个位(最右边)停止:

<van-rolling-text :start-num="0" :target-num="54321" stop-order="rtl" />

其实现逻辑在 RollingText.tsx 的getDelay函数中:每一位数都有一个独立的动画延迟,延迟值由该位索引和总位数共同决定——

  • ltrdelay = 0.2 * ii为从左到右的位数索引,第 0 位是最高位),高位延迟最短、最先开始也最先停止;
  • rtldelay = 0.2 * (len - 1 - i),最右侧的个位延迟最短,最先停止。

也就是说,“停止顺序”本质上是每位数 0.2 秒的错峰延迟,最终所有位数在各自的动画周期内完成翻转,形成依次停定的层叠视觉效果。

翻转非数字内容:text-list

text-list属性用于翻转非数字内容。组件会从数组的第一项翻滚到最后一项。使用该模式有两点约束:数组长度必须大于等于 2,且每一项的长度必须一致

<van-rolling-text :text-list="textList" :duration="1" />
import { ref } from 'vue'; export default { setup() { const textList = ref([ 'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee', 'fffff', 'ggggg', ]); return { textList }; }, };

源码层面的处理方式(见 RollingText.tsx):

  • 只要textList是长度大于 0 的数组,组件即进入isCustomType(自定义文本)模式;
  • itemLengthtextList[0].length(即每个字符串的长度),每个字符串的同一索引位会组成一列可翻滚内容:getTextArrByIdx(idx)遍历数组,取出每项的第idx个字符,作为该数位的滚动序列;
  • 由于每一位的滚动内容是整列的字符,因此要求所有字符串长度一致,否则短字符串的越界索引会取到undefined,破坏渲染。

自定义样式:CSS 变量与 height 属性

RollingText 提供了若干 CSS 变量用于主题定制,也支持直接修改组件样式。此外,height属性(默认40,单位px)用于设置单个数位的高度,在数字较大时可适当调大:

<van-rolling-text class="my-rolling-text" :height="54" :start-num="12345" :target-num="54321" />
.my-rolling-text { --van-rolling-text-background: #1989fa; --van-rolling-text-color: white; --van-rolling-text-font-size: 24px; --van-rolling-text-gap: 6px; --van-rolling-text-item-border-radius: 5px; --van-rolling-text-item-width: 40px; }

样式变量在 index.less 中以:root/:host声明默认值。height的底层作用体现在两处(见 RollingTextItem.tsx):

  • 作为单项的line-height,控制每个数字占位的高度;
  • 参与计算总位移:translatePx = -(height * (序列长度 - 1)),位移距离随高度线性放大,确保无论高度多少,翻滚终态都能精准停在目标数字上。

手动控制:start 与 reset

默认组件自动播放动画,但通过auto-start属性(默认true)可以关闭自动播放,再通过 ref 获取组件实例调用startreset方法手动控制动画:

<van-rolling-text ref="rollingTextRef" :start-num="0" :target-num="54321" :auto-start="false" /> <van-grid clickable :column-num="3"> <van-grid-item icon="play-circle-o" :text="start" @click="start" /> <van-grid-item icon="replay" :text="reset" @click="reset" /> </van-grid>
import { ref } from 'vue'; export default { setup() { const rollingTextRef = ref(null); const start = () => { rollingTextRef.value.start(); }; const reset = () => { rollingTextRef.value.reset(); }; return { rollingTextRef, start, reset }; }, };

从 RollingText.tsx 的源码可以看到内部状态与联动逻辑:

  • 内部维护rolling响应式标记,初始值等于props.autoStart,它决定了子组件是否挂上--animate动画类;
  • start()仅将rolling置为true
  • reset()先将rolling置为false(移除动画类、回到初始位置),如果auto-starttrue,则通过raf(requestAnimationFrame,来自@vant/use)在下一帧重新触发start(),实现“重置后自动重播”的效果;
  • 同时组件watchauto-start的变化:当属性从false变为true时会立即调用start()
  • 两个方法通过useExpose(见 composables/use-expose.ts)挂载到组件实例的proxy上对外暴露。

这些行为均有对应的单元测试覆盖(见 rolling-text/test/index.spec.ts):包括auto-starttrue/false时动画类是否存在、调用start()后动画类出现、调用reset()后动画类消失,以及auto-starttrue时调用reset()后动画会重新启动(测试中通过await later(50)等待下一帧验证)。这些测试同样可以作为你在项目中验证滚动行为的参考范式。

API 参考

Props

参数说明类型默认值
start-num起始数值number0
target-num目标数值number-
text-list内容数组,用于翻转非数字内容string[][]
duration动画时长,单位为秒number2
direction文本翻滚方向,值为downupstringdown
auto-start是否自动开始动画booleantrue
stop-order各个数位动画停止先后顺序,值为ltrrtlstringltr
height数字高度,单位为pxnumber40

上述默认值与 RollingText.tsx 中rollingTextProps的声明完全一致:startNumdurationheight使用makeNumberProp声明数字类型默认值,autoStart使用truthProp声明布尔truetextList使用makeArrayProp声明数组默认值[]。其中target-num无默认值,数字场景下为必填项(源码中通过非空断言props.targetNum!使用)。

方法

通过 ref 可以获取到 RollingText 实例并调用实例方法,实例方法获取方式可参考 组件实例方法。

方法名说明参数返回值
start开始动画--
reset重置动画--

类型定义

组件导出以下类型定义:

import type { RollingTextProps, RollingTextInstance, RollingTextDirection, RollingTextStopOrder, } from 'vant';

RollingTextInstance是组件实例的类型,在手动控制场景下可用于类型安全的 ref,用法如下:

import { ref } from 'vue'; import type { RollingTextInstance } from 'vant'; const rollingTextRef = ref<RollingTextInstance>(); rollingTextRef.value?.start();

从 types.ts 可以看到这些类型的完整定义:RollingTextDirection = 'up' | 'down'RollingTextStopOrder = 'ltr' | 'rtl'RollingTextExpose = { start: () => void; reset: () => void },而RollingTextInstanceComponentPublicInstance<RollingTextProps, RollingTextExpose>,因此rollingTextRef.value上能同时获得 props 与start/reset方法的完整类型提示。

主题定制:样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法可参考 ConfigProvider 组件(ConfigProvider 可用于全局批量配置主题变量)。

名称默认值描述
--van-rolling-text-backgroundinherit单个数位背景色
--van-rolling-text-colorvar(--van-text-color)数字颜色
--van-rolling-text-font-sizevar(--van-font-size-md)字体大小
--van-rolling-text-gap0px数位之间的间隔
--van-rolling-text-item-width15px单个数位宽度
--van-rolling-text-item-border-radius0px单个数位边框圆角

这些变量在 index.less 中统一声明默认值:背景色默认inherit继承外层,文字颜色默认跟随主题的--van-text-color,字体大小默认跟随--van-font-size-md--van-rolling-text-gap通过数位项的margin-right实现数位间距(最后一位会移除margin-right),--van-rolling-text-item-width--van-rolling-text-item-border-radius分别控制单个数位的宽度与圆角;同时类型定义中也导出了RollingTextThemeVars,可在 TypeScript 中约束主题变量名。对应主题变量同样已在RollingTextThemeVars中声明(见 types.ts)。

动画原理深度剖析

理解 RollingText 的底层机制,有助于你预判它在复杂业务下的表现(例如异步数据变化、动画中途重触发等)。

数字滚动序列的构建

对于数字场景,每个数位需要一列“可滚动数字”。在 RollingText.tsx 的getFigureArr中,该序列由三段拼接而成:

  1. 从起始位数字start递增到9
  2. 完整的09循环CIRCLE_NUM次(源码常量CIRCLE_NUM = 2,即默认滚动两圈);
  3. 0递增到目标位数字target

例如起始个位为0、目标个位为3,该位序列即为0,1,...,9,0,1,...,9(×2),0,1,2,3CIRCLE_NUM决定了翻滚的“圈数”,是营造真实滚动感的关键参数;位移总高度即由这一列数字的数量乘以height得出。

CSS 关键帧与位移驱动

单个数位的渲染结构(见 RollingTextItem.tsx)为:

van-rolling-text-item(外层,overflow: hidden 视窗) └── van-rolling-text-item__box(滚动容器,挂 --animate 触发动画) └── 若干 van-rolling-text-item__item(单个数字,line-height = height)

滚动容器通过行内样式注入三个 CSS 自定义属性(见 RollingTextItem.tsx):

  • --van-translate:目标位移(-(height * (序列长度 - 1)));
  • --van-duration:动画时长(duration秒);
  • --van-delay:该位延迟(stop-order计算出的错峰延迟)。

动画由 index.less 中.van-rolling-text-item__box--animate触发的animation驱动:animation: van-up var(--van-duration) ease-in-out var(--van-delay),且animation-iteration-count: 1(只播放一次)、animation-fill-mode: both(结束后保持终态)。

两套关键帧对应两个翻滚方向:

  • @keyframes van-up:从translateY(0)过渡到translateY(var(--van-translate)),配合未反转的序列,呈现数字向上滚动;
  • @keyframes van-down:从translateY(var(--van-translate))过渡到translateY(0),配合反转后的序列,呈现数字向下滚动。

为什么“非数字文本”也能滚动

非数字模式复用了完全相同的动画管线:getTextArrByIdx构造出的字符序列同样交给RollingTextItem,每个字符占据height高的格子,通过相同的--van-translate位移完成整列翻滚。这也是“非数字翻转”与“数字翻转”在代码层面仅差一个序列构造函数的根本原因。

适用场景与注意事项

RollingText 适合以下场景:

  • 大屏/统计页面的数字播报(播放量、订单量、金额等),配合duration调节节奏;
  • 需要循环展示的短文本切换,通过text-list+auto-start手动触发;
  • 数据变化时重新翻滚,可结合reset()auto-start的组合行为实现“重置后自动重播”。

使用时注意几点:

  1. text-list模式要求数组长度 ≥ 2 且每项等长;
  2. target-num在数字模式下必须提供(类型为非可选,源码中使用非空断言);
  3. 数字位数以start-num/target-num中较大者为准,较小的数值会被padZero补零;
  4. 动画默认自动播放,需要等待用户操作或异步数据就绪时,记得设置:auto-start="false"并配合实例方法触发;
  5. 所有主题变量均可通过 CSS 变量覆盖,也可借助 ConfigProvider 进行全局主题统一管理。

完整的可运行演示可参考 rolling-text/demo/index.vue,其中覆盖了基础用法、双向翻滚、个位先停、非数字文本、自定义样式与手动控制六种场景,并配合按钮触发动画,是快速上手本组件的最佳样例。

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 10:46:08

基于Matlab的动态系统故障诊断与容错控制实践

1. 项目概述动态系统的故障诊断和容错控制是现代控制工程中的关键技术&#xff0c;尤其在航空航天、工业自动化、汽车电子等安全关键领域具有重要应用价值。本项目基于Matlab平台&#xff0c;研究如何实时检测系统异常并自动调整控制策略&#xff0c;确保系统在部分组件失效时仍…

作者头像 李华
网站建设 2026/9/12 10:46:03

二重积分的几何本质与工程应用解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 10:44:07

细粒度情感分析技术解析与应用实践

1. 情感分析技术演进与细粒度需求情感分析技术从早期的简单二元分类&#xff08;正面/负面&#xff09;发展到如今的细粒度分析&#xff0c;背后是商业智能和用户体验优化的强烈需求。传统的情感分析就像用黑白相机拍摄风景&#xff0c;只能识别"好"或"坏"…

作者头像 李华
网站建设 2026/9/12 10:43:34

UiPath金融自动化中重复元素识别的6种解决方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 10:43:24

LLM落地的四大护栏:从幻觉防控到可信交付

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 10:40:54

高校房屋管理系统:Java+MySQL实现智能分房与全生命周期管理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华