Ant Design Image 多图预览顶部进度:用 countRender 自定义“当前图 / 总数”指示器
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design
本文以 ant-design 仓库中Image.PreviewGroup的多图预览顶部进度能力为主线,讲解如何在多图预览模式下把顶部默认的“当前 / 总数”计数替换为自定义内容(文本、图标或任意 ReactNode),并延伸到受控切换、语义化自定义与底层源码原理。读完本文,你将能在自己的 React 项目中快速实现类似“第 3 / 共 12 张”的业务化预览进度 UI。
一、功能背景:多图预览时的顶部进度从哪里来
在 antd 中,多个Image组件被包裹进Image.PreviewGroup后,点击任意缩略图即可进入全屏预览,并可通过左右箭头在多张图片之间切换。此时预览层顶部会展示一个“当前进度/总数”指示区域——它标识用户当前浏览到第几张、一共几张,也就是多图预览顶部进度。相关 Demo 被收录在 preview-group-top-progress.md,官方英文描述为:
The progress is displayed at the top of the multi-image preview, and customization is supported。
即该指示器默认展示在预览顶部,并且允许自定义。自定义的入口就是PreviewGroup的preview配置对象中的countRender回调。
需要区分两个容易混淆的概念:
- 多图切换进度(本文主题):标识“当前第几张/总张数”,由
countRender定制,配置在Image.PreviewGroup的preview上; - 单图加载进度:图片加载百分比/加载动画,由
Image/preview配置中的progress定制(支持boolean | ImageProgressConfig,可传{ percent }或render),其底层 UI 实现在 Progress.tsx(内部包含progressbarARIA 语义与--progress-percentCSS 变量)。前者切换、后者加载,二者不可混为一谈。
二、最小可运行示例:复刻官方 Demo
官方 Demo 源码见 preview-group-top-progress.tsx,核心只有一行配置:
import React from 'react'; import { Image } from 'antd'; const App: React.FC = () => ( <Image.PreviewGroup preview={{ countRender: (current, total) => `Current ${current} / Total ${total}` }} > <Image alt="svg image" width={150} src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" /> <Image width={150} alt="svg image" src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg" /> <Image width={150} alt="svg image" src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" /> </Image.PreviewGroup> ); export default App;要点拆解:
- 预览必须分组:只有把多个
Image放进Image.PreviewGroup,切换与顶部进度才会生效;单独使用的Image只具备单图预览。 preview不是布尔值而是配置对象:这里的preview={{ countRender: ... }}传入的是PreviewGroupType配置对象,countRender是其一个可选字段。countRender的签名:(current: number, total: number) => React.ReactNode——current为当前展示图片的序号,total为组内图片总数。返回值会替换预览顶部默认的进度文本。- 缩略图点击即可触发预览:Demo 中每张缩略图
width={150},点击后即进入全屏预览并展示自定义文本。
将该代码粘贴进一个基于 antd 的 React 项目(需引入 antd 样式与 React)即可运行:打开预览后,顶部进度会显示Current 1 / Total 3这类自定义文案而非默认计数。
三、countRender 参数说明与进阶用法
countRender的完整类型定义可从组件文档 index.en-US.md 与 index.zh-CN.md 的PreviewGroupTypeAPI 表中找到:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
countRender | 自定义预览计数渲染内容 | (current: number, total: number) => React.ReactNode | - |
由此可以看出几个实用点:
1. 返回值不限于字符串。既然返回React.ReactNode,你可以自由返回 JSX,比如带强调色的当前序号、加图标,或按业务拼接中文文案:
<Image.PreviewGroup preview={{ countRender: (current, total) => ( <span className="custom-count"> <strong>{current}</strong> <span> / </span> {total} </span> ), }} > {/* ...images... */} </Image.PreviewGroup>2. 进度文案应与业务状态联动。current会在用户点击左右箭头或(配合受控模式)程序切换图片时实时更新,因此无需自己额外监听即可获得最新序号——这是官方推荐的多图场景做法。
3. 属于preview配置对象的一部分。除了countRender,同一配置对象还支持current(当前预览索引,可实现受控切换)、open/onOpenChange、onChange(切换图片回调(current, prevCurrent) => void)、movable、focusTrap、getContainer、toolbarRender(已废弃,请用actionsRender)等字段,可组合使用。
四、与“受控切换 + 计数进度”组合的实战场景
官方 Demo preview-group-visible.md 与 controlled-preview.tsx 展示了更贴近业务的组合方式:外部维护当前展示索引,将点击行为与预览打开状态绑定。结合countRender可构成完整的“相册模式”:
import React, { useState } from 'react'; import { Image } from 'antd'; const App: React.FC = () => { const [visible, setVisible] = useState(false); const [current, setCurrent] = useState(0); const images = [ 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg', 'https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg', 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', ]; return ( <Image.PreviewGroup preview={{ visible, current, countRender: (cur, total) => `第 ${cur} 张 / 共 ${total} 张`, onChange: (cur) => setCurrent(cur), onOpenChange: (open) => setVisible(open), }} > {images.map((src, index) => ( <Image key={src} width={150} src={src} onClick={() => { setCurrent(index); setVisible(true); }} /> ))} </Image.PreviewGroup> ); }; export default App;这样便实现了“从指定缩略图进入预览、顶部进度实时同步、序号受控可回写”的完整闭环。onChange(current, prevCurrent)还能用于埋点记录用户从第几张切到第几张。
五、源码级解析:countRender 如何在 PreviewGroup 中流转
在 ant-design 仓库中,多图预览的对外入口是 PreviewGroup.tsx。从源码结构可以看出内部机制:
InternalPreviewGroup接收preview(boolean | GroupPreviewConfig)等 props,其接口类型定义在第 49-54 行,preview字段来源于对底层@rc-component/image的PreviewGroupProps的扩展(第 35-47 行的RcPreviewGroupProps与OriginPreviewConfig);- 通过
usePreviewConfig、useMergedPreviewConfig两个 hook(位于 hooks 目录)对当前组件传入的preview与来自ConfigProvider的preview上下文进行归一化与合并(第 84-109 行),countRender作为配置对象的一环随mergedPreview一并下传; - 最终整体透传给底层
RcImage.PreviewGroup(第 148-157 行),并同步注入previewPrefixCls、方向敏感的左右箭头icons(RTL 场景自动交换箭头方向,见第 90-97 行)以及合并后的classNames/styles。
也就是说,countRender并不在 ant-design 侧做额外计算,而是将用户的定制回调原样传给渲染预览 UI 的底层库,由底层在进度渲染处调用并输出用户返回的节点。这也是它 API 保持轻量、只收(current, total)两个入参的原因。
此外,仓库的测试快照 demo-extend.test.ts.snap 中记录了renders components/image/demo/preview-group-top-progress.tsx extend context correctly的渲染结果:三张缩略图各自以ant-image结构(role="button"、tabindex="0"、style="width: 150px")出现在预览组上下文中,可以作为该 Demo 在测试环境中正常渲染、三图归属同一PreviewGroup的自动化验证依据。
六、语义化与无障碍注意点
在自定义顶部进度时,建议保持内容的可读性,因为预览层整体承担了无障碍语义:
- 多图预览的缩略图具备
role="button"、aria-label与可聚焦的tabindex,可被键盘触发(可对照快照中的ant-image结构); - 预览内部的图片加载进度 UI(Progress.tsx)在无百分比阶段会输出
role="status"+aria-live="polite"的屏幕阅读器提示区,有百分比时输出role="progressbar"+aria-valuemin/valuemax/valuenow。这说明 antd 对“进度”类信息有完整的无障碍约定,自定义countRender文案时也应尽量避免纯装饰性内容。
七、小结
多图预览顶部进度是Image.PreviewGroup中一个“配置轻、体验影响直接”的能力:
- 通过
preview.countRender即可将顶部“当前 / 总数”替换成任意文本或 JSX; - 与
current、visible、onChange、onOpenChange组合可实现完全受控的相册/图片查看器; - 源码层面,PreviewGroup.tsx 只负责把
preview配置(含countRender)合并透传给底层渲染,接入成本极低。
官方同类示例还提供 preview-group.tsx(纯onChange监听切换)、preview-imgInfo.tsx(在渲染函数中获取图片信息)等,可将它们与本 Demo 组合使用,覆盖绝大多数多图预览的定制诉求。
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考