Ant Design Image 组件完全指南:加载占位、容错回退与可定制图片预览(Preview)
作为一套面向企业级应用的前端组件库,antd 的 Image 组件承担着"展示可预览图片"这一基础而高频的职责:它不止是 <img> 标签的封装,还内置了渐进式加载占位、加载失败容错、单图/多图全屏预览(支持缩放、旋转、拖拽、翻转)以及语义化 DOM 定制等一整套图片交互能力。本篇指南将完全围绕 components/image/index.en-US.md 展开,从基础用法到 placeholder/fallback 两种加载策略,再到 preview 与 Image.PreviewGroup 的全部配置项、受控预览、工具栏与预览内容自定义,最后结合 Image 组件的源码结构(入口、hooks、Progress 渲染层)与语义化 DOM 深入剖析其内部原理,帮助你在实际项目中按需选用每一份能力。
使用场景(When To Use)
按照官方文档的定位,Image 适合在两类场景中使用:
- 需要展示图片时,使用基础形态的
<Image />,它具备优雅的悬浮遮罩与点击预览能力; - 大图加载或加载失败容错场景,例如需要展示"加载进度/渐变占位",或希望在图片资源出错时优雅降级,而不是出现破碎的图标。
从实现上看,Image 组件在 index.tsx 中对 @rc-component/image 做了二次封装:统一前缀 class、合并 ConfigProvider 的上下文配置、接入语义化 classNames/styles 与组件 Token,并扩展了 placeholder(进度占位)与 cover(悬浮预览遮罩)等上层能力。
快速上手:从一张图到一组图
最简单的用法只需要 src、width 与描述性 alt 即可(参见 demo/basic.tsx):
import React from 'react';
import { Image } from 'antd';
const App: React.FC = () => (
<Image
width={200}
alt="basic"
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
);
export default App;
默认情况下,鼠标悬浮在图片上会显示一层"眼睛"样式的预览遮罩(cover),点击后即进入全屏 Preview。当多张图片需要联动预览(左右切换、显示总数与当前序号)时,使用 Image.PreviewGroup 包裹即可(参见 demo/preview-group.tsx):
import React from 'react';
import { Image } from 'antd';
const App: React.FC = () => (
<Image.PreviewGroup
preview={{
onChange: (current, prev) => console.log(`current index: ${current}, prev index: ${prev}`),
}}
>
<Image width={200} alt="svg image" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" />
<Image width={200} alt="svg image" src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg" />
</Image.PreviewGroup>
);
Image.PreviewGroup 在 PreviewGroup.tsx 中被实现为 InternalPreviewGroup,并通过 Image.PreviewGroup = PreviewGroup 挂载到 Image 上(index.tsx)。预览的旋转/缩放/翻转等默认图标(icons)也定义在此文件内,且它会根据 ConfigProvider 的 direction 自动在 RTL 模式下对调左右切换箭头。
加载体验优化:placeholder 与渐进式加载
文档明确指出 placeholder 有双重能力:既可以渲染 ReactNode,也可以传配置对象来控制进度 UI。对应地,placeholder 的 Type 为 ReactNode | { progress?: boolean | ImageProgressConfig }。
ReactNode 形式的占位
直接把任意 ReactNode 传给 placeholder,图片加载期间就会渲染该节点。官方示例 demo/placeholder.tsx 展示了把一张半透明模糊层作为占位的方式:
<Image
width={200}
height={200}
src="...原图URL..."
placeholder={
<div
style={{
width: '100%',
height: '100%',
background: 'rgba(255, 255, 255, 0.3)',
backdropFilter: 'blur(10px)',
}}
/>
}
/>
进度型占位(Progress Placeholder)
当希望模仿"AI 生图 / 大图渐进加载"这类带进度反馈的场景时,改用配置对象:
placeholder={{ progress: true }}:显示带有水彩墨迹流动动画的渐变占位,不展示百分比;placeholder={{ progress: { percent: 50 } }}:显示当前进度条与50%文本;placeholder={{ progress: { percent, render } }}:用render自定义整个进度内容的展示。
一个完整的"生成式加载"示例(改写自官方 demo)长这样:
const [percent, setPercent] = useState(0);
<Image
width={200}
height={200}
placeholder={{
progress: {
percent: Math.round(percent),
render: (progress, p) => (
<>
{progress}
<div style={{ marginTop: 8 }}>Generating {p}%</div>
</>
),
},
}}
/>
render 的函数签名为 (progress: React.ReactNode, percent: number) => React.ReactNode:第一个参数是内置的进度条 UI,第二个参数是当前百分比,你可以自由组合。
源码级原理解析:配置化与 ReactNode 两种形态的区分,由 hooks/usePlaceholderConfig.ts 中的 isPlaceholderConfig 完成——只有"普通对象且不是合法 React 元素"才会被当作进度配置解析。真正的进度渲染层在 Progress.tsx:
- 当传入有限数值
percent时,进度条宽度通过 CSS 变量--progress-percent驱动,并把数值收敛在 0–100 之间; - 无百分比(仅开启动画)时,会输出
role="status" aria-live="polite"的隐藏区域(内容为 "Loading"),同时根节点带aria-busy,为屏幕阅读器提供加载状态; - 两个
.progress-ink-*墨迹层 + 伪元素共叠加出 5 层水彩流光动画,其关键帧动画定义在 style/progressAnimation.ts; - 动画时长由组件 Token
progressAnimationDuration控制(默认 3s,见 style/index.ts)。
值得注意的边界行为(见 index.tsx):当 placeholder 是 ReactNode 且未提供 src 时,该占位会被当作覆盖层渲染(shouldRenderPlaceholderOverlay),因为此时底层 rc-image 会把空 src 判为 error 状态;只有提供进度配置或正常 src 时才走常规图片流程。
加载失败容错:fallback
当 src 加载失败时,fallback 会指定一张替代图。官方示例 demo/fallback.tsx 直接把 src 指向无效地址 "error",并传入一张 base64 内嵌图作为兜底:
<Image
alt="basic image"
width={200}
height={200}
src="error"
fallback="data:image/png;base64,iVBORw0KGgo..." // 加载失败时展示的兜底 URL
/>
fallback 也支持通过 ConfigProvider 做全局配置(自 5.28.0 起),在 index.tsx 中通过 mergedFallback = fallback ?? contextFallback 实现"组件级优先、上下文兜底"的合并逻辑。失败时触发的 onError 回调可用于埋点或自定义后续处理。
预览功能全解:preview 配置与受控预览
单图预览
默认 preview 为 true(点击放大)。设置 preview={false} 即关闭预览。传对象时则进行精细定制,例如官方示例 demo/controlled-preview.tsx 展示的完全受控预览——预览的开关由外部 state 驱动:
const [open, setOpen] = useState(false);
const [scaleStep, setScaleStep] = useState(0.5);
<Button type="primary" onClick={() => setOpen(true)}>show image preview</Button>
<Image
width={200}
style={{ display: 'none' }} // 原图隐藏,仅作为预览入口
alt="basic image"
src="...缩略图URL..."
preview={{
open,
scaleStep,
src: '...高清大图URL...', // 预览时使用的大图,与缩略图分离
onOpenChange: (value) => setOpen(value),
}}
/>
自定义预览大图(thumbnail → HD)
缩略图与预览大图分离是相册类产品非常实用的能力。官方示例 demo/previewSrc.tsx 中,展示的 src 是一张经过模糊/压缩的缩略图(URL 上带 blur 与 resize 处理参数),而 preview.src 指向原图:
<Image
width={200}
alt="basic image"
src="...?x-oss-process=image/blur,r_50,s_50/quality,q_1/resize,m_mfit,h_200,w_200" // 列表中的小图
preview={{
src: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', // 预览大图
}}
/>
这个模式在"列表缩略、点击看原图"的典型场景中,既能保证首屏性能,又不牺牲预览清晰度。
从任意一张图进入组预览
多图联动不只局限于 JSX 包裹这一种形式。demo/preview-group-visible.tsx 演示了先给 Image.PreviewGroup 配置 items(图片数组),再通过某个 Image 直接进入组预览。此外 PreviewGroup 的 items 还支持 { src: string, crossOrigin: string, ... } 形式以携带额外属性。
预览中的操作能力
进入 Preview 全屏浮层后,默认支持:放大/缩小(步进为 1 + scaleStep)、向左/向右旋转、水平/垂直翻转、大图拖拽(movable)、鼠标滚轮缩放(wheel,6.6.0 起)、双击放大、复位与关闭。各项能力均有对应开关与上下限:
maxScale最大缩放倍数,默认50;minScale最小缩放倍数,默认1;scaleStep缩放步进因子,默认0.5,即每次缩放为上一状态的1 + 0.5 = 1.5倍;movable图片大于视口时是否可拖拽,默认true;wheel是否开启滚轮缩放,默认true(6.6.0 引入);focusTrap打开预览时是否将焦点圈定在预览内部,默认true(6.4.0 引入,配合无障碍键盘浏览)。
打开/切换/变换回调
Preview 体系提供了三类关键回调:
| 回调 | 说明 | 适用组件 |
|---|---|---|
onOpenChange(visible) |
预览开关状态变化时触发 | Image / PreviewGroup |
onChange(current, prevCurrent) |
切换预览图片时触发(携带当前索引与上一次索引) | PreviewGroup |
onTransform({ transform, action }) |
预览发生任何变换(缩放/旋转/翻转/拖拽/复位等)时触发 | Image / PreviewGroup |
其中 onTransform 的 action 与 transform 分别由 TransformAction 与 TransformType 描述(见下文 Interface 小节),你既可以用它来做"当前是滚轮缩放还是按钮缩放"的区分,也可以据此同步外部的自定义工具栏状态。注意 PreviewGroup 的 onOpenChange 额外携带当前索引:(visible, info: { current }) => void。
工具栏与预览内容自定义
actionsRender:替换整条操作栏
从 5.x 开始官方推荐使用 actionsRender(取代已废弃的 toolbarRender)接管预览底部操作栏。回调签名(即 ToolbarRenderInfoType)如下:
(originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode
ToolbarRenderInfoType 中包含默认图标集合 icons(翻转、旋转、缩放、关闭图标),以及可直接调用的动作集合 actions:
{
icons: {
flipYIcon: React.ReactNode; flipXIcon: React.ReactNode;
rotateLeftIcon: React.ReactNode; rotateRightIcon: React.ReactNode;
zoomOutIcon: React.ReactNode; zoomInIcon: React.ReactNode;
};
actions: {
onActive?: (index: number) => void; // support after 5.21.0
onFlipY: () => void; onFlipX: () => void;
onRotateLeft: () => void; onRotateRight: () => void;
onZoomOut: () => void; onZoomIn: () => void;
onReset: () => void; // support after 5.17.3
onClose: () => void;
};
transform: TransformType;
current: number;
total: number;
image: ImgInfo;
}
注意:Image 与 PreviewGroup 的 actionsRender 签名在 info 上略有差异,PreviewGroup 场景下 current/total 才真正有意义。对应 demo 为 demo/toolbarRender.tsx(组件内 toolbarRender 的旧用法会自动转换为 actionsRender,见 hooks/usePreviewConfig.ts)。
imageRender:替换预览主体内容
若不想用默认的 <img> 展示,可通过 imageRender 自定义预览内容(例如叠加自定义绘制、水印或形状处理)。单图场景签名:
(originalNode: React.ReactElement, info: { transform: TransformType; image: ImgInfo }) => React.ReactNode
PreviewGroup 场景下 info 中额外携带 current。对应 demo:demo/imageRender.tsx。
cover / mask:悬浮遮罩与预览遮罩
文档对遮罩体系做了清晰划分,且在 6.0 之后有明显演进:
preview.cover(6.0 起支持配置对象):自定义"点击进入预览"的悬浮遮罩节点,即缩略图上方悬浮的提示层。可传ReactNode或CoverConfig:demo 参见 demo/coverPlacement.tsx(自定义放置位置)与 demo/preview-mask.tsx(自定义遮罩节点)。在 PreviewGroup.tsx 中维护了type CoverConfig = { coverNode?: React.ReactNode; // 预览遮罩的自定义节点 placement?: 'top' | 'bottom' | 'center'; // 预览遮罩的显示位置 };icons与cover相关合并逻辑。preview.mask(对象化):控制预览弹层自身背景遮罩的显示/模糊/点击关闭行为,类型为boolean | { enabled?: boolean; blur?: boolean; closable?: boolean },默认true。其中closable(点击遮罩关闭)自 6.4.0 引入;blur会在遮罩上叠加backdrop-filter: blur(4px)(对应 class 见 style/index.ts 的preview-mask-blur)。注意:旧版把mask当作 ReactNode 传入的用法已被废弃,请改用cover(源码中会发出对应 deprecation 警告)。
语义化 classNames / styles 定制
6.0.0 起,Image 全面支持 classNames/styles 两种定制方式(均可传对象或 (info: { props }) => ... 函数形式),分别注入 class 与内联样式,覆盖以下语义节点:
root:根元素(相对定位 + inline-block 布局);image:<img>本身;cover:悬浮预览提示层;placeholder.progress:进度占位内部结构(root/content/rail/indicator,由 Progress.tsx 定义ProgressClassNames/ProgressStyles);popup.*:预览弹层内部结构,包括popup.root、popup.mask、popup.body、popup.footer、popup.actions、popup.close(6.4.0 起)。
语义结构演示见 demo/_semantic.tsx,配套测试在 semantic.test.tsx。在实现上,index.tsx 借助 useMergeSemantic 将 contextClassNames/contextStyles(来自 ConfigProvider 组件级配置)、props 上的 classNames/styles 以及旧版遗留的 wrapperStyle/rootClassName/maskClassName 合并归一,其中 popup._default 指向 root,使得旧写法能平滑迁移。
其他预览配置
closeIcon:自定义关闭按钮(ConfigProvider 全局配置自 5.14.0 支持);getContainer:指定预览浮层挂载的容器(默认挂到body);传false表示挂载在当前图片位置。仍以全屏尺寸呈现;rootClassName:预览根 DOM 类名(PreviewGroup 中已废弃,改用classNames.root);countRender:仅在 PreviewGroup 中存在,用于自定义(current, total)计数展示。
全局统一配置(ConfigProvider)
Image 是一个支持 ConfigProvider 组件级全局配置 的组件:fallback(5.28.0 起)、preview.closeIcon(5.14.0 起)、preview.mask(6.0.0 起)、preview.mask.closable(6.4.0 起)均可下沉到 ConfigProvider,通过一次配置全局生效(上述 API 表格中标注 Global Config 的列)。例如给全站图片统一兜底图:
import { ConfigProvider, Image } from 'antd';
<ConfigProvider
image={{ fallback: 'https://example.com/placeholder.png' }}
>
{/* 内部所有 Image 加载失败均展示 fallback */}
</ConfigProvider>
在 index.tsx 中通过 useComponentConfig('image') 读取该上下文,并将其中的 preview、fallback、classNames、styles 与组件 props 做合并(合并逻辑集中在 hooks/useMergedPreviewConfig.ts,其中还包括 z-index 自动递增、遮罩 blur 状态与 getContainer 兜底等细节)。
图片 API 参考
通用属性可参考 Common props;其余透传属性遵循原生
<img>(如crossOrigin、loading等)。
Image
| Property | Description | Type | Default | Version | Global Config |
|---|---|---|---|---|---|
| alt | Image description | string | - | × | |
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | 6.0.0 | |
| fallback | Fallback URL when load fails | string | - | 5.28.0 | |
| height | Image height | string | number | - | × | |
| placeholder | Loading placeholder, supports ReactNode or config object | PlaceholderType | - | × | |
| preview | Preview configuration; set to false to disable | boolean | PreviewType | true | preview.closeIcon: 5.14.0, preview.mask: 6.0.0, preview.mask.closable: 6.4.0 |
|
| src | Image URL | string | - | × | |
| styles | Customize inline style for each semantic structure inside the component. Supports object or function. | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 6.0.0 | |
| width | Image width | string | number | - | × | |
| onError | Callback when loading error occurs | (event: Event) => void | - | × |
PlaceholderType
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| progress | Progress config, set to true to show gradient animation, set { percent: number } to show progress, render for custom rendering |
boolean | ImageProgressConfig | - |
ImageProgressConfig
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| percent | Progress value | number | - | |
| render | Custom rendering, receives default progress UI and percentage | (progress: React.ReactNode, percent: number) => React.ReactNode | - |
PreviewType
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| actionsRender | Custom toolbar render | (originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode | - | |
| closeIcon | Custom close icon | React.ReactNode | - | |
| cover | Custom preview mask | React.ReactNode | CoverConfig | - | CoverConfig support after v6.0 |
| focusTrap | Whether to trap focus within the preview when open | boolean | true | 6.4.0 |
| Destroy child elements on preview close (removed, no longer supported) | boolean | false | ||
| Force render preview image (removed, no longer supported) | boolean | - | ||
| getContainer | Specify container for preview mounting; still full screen; false mounts at current location | string | HTMLElement | (() => HTMLElement) | false | - | |
| imageRender | Custom preview content | (originalNode: React.ReactElement, info: { transform: TransformType, image: ImgInfo }) => React.ReactNode | - | |
| mask | preview mask effect | boolean | { enabled?: boolean, blur?: boolean, closable?: boolean } | true | mask.closable: 6.4.0 |
| Thumbnail mask class name; please use 'classNames.cover' instead | string | - | ||
| maxScale | Maximum zoom scale | number | 50 | |
| minScale | Minimum zoom scale | number | 1 | |
| movable | Whether the preview image can be dragged when it is larger than the viewport | boolean | true | |
| open | Whether to display preview | boolean | - | |
| rootClassName | Root DOM class name for preview; applies to both image and preview wrapper | string | - | |
| scaleStep | Each step's zoom multiplier is 1 + scaleStep | number | 0.5 | |
| src | Custom preview src | string | - | |
| styles | Custom semantic structure styles | Record<SemanticDOM, CSSProperties> | - | |
| wheel | Whether to enable mouse wheel zoom | boolean | true | 6.6.0 |
| Custom toolbar; please use 'actionsRender' instead | (originalNode: React.ReactElement, info: Omit<ToolbarRenderInfoType, 'current' | 'total'>) => React.ReactNode | - | ||
| Whether to show; please use 'open' instead | boolean | - | ||
| onOpenChange | Callback when preview open state changes | (visible: boolean) => void | - | |
| onTransform | Callback for preview transform changes | { transform: TransformType, action: TransformAction } | - | |
| Callback when 'visible' changes; please use 'onOpenChange' instead | (visible: boolean, prevVisible: boolean) => void | - |
PreviewGroup
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | |
| fallback | Fallback URL for load error | string | - | |
| items | Array of preview items | string[] | { src: string, crossOrigin: string, ... }[] | - | |
| preview | Preview configuration; disable by setting to false | boolean | PreviewGroupType | true |
PreviewGroupType
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| actionsRender | Custom toolbar render | (originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode | - | |
| closeIcon | Custom close icon | React.ReactNode | - | |
| countRender | Custom preview count render | (current: number, total: number) => React.ReactNode | - | |
| focusTrap | Whether to trap focus within the preview when open | boolean | true | 6.4.0 |
| current | Index of the current preview image | number | - | |
| Force render preview image (removed, no longer supported) | boolean | - | ||
| getContainer | Specify container for preview mounting; still full screen; false mounts at current location | string | HTMLElement | (() => HTMLElement) | false | - | |
| imageRender | Custom preview content | (originalNode: React.ReactElement, info: { transform: TransformType, image: ImgInfo, current: number }) => React.ReactNode | - | |
| mask | preview mask effect | boolean | { enabled?: boolean, blur?: boolean, closable?: boolean } | true | mask.closable: 6.4.0 |
| Thumbnail mask class name; please use 'classNames.cover' instead | string | - | ||
| minScale | Minimum zoom scale | number | 1 | |
| maxScale | Maximum zoom scale | number | 50 | |
| movable | Whether the preview image can be dragged when it is larger than the viewport | boolean | true | |
| open | Whether to display preview | boolean | - | |
| Root DOM class name for preview; applies to both image and preview wrapper. Use 'classNames.root' instead | string | - | ||
| styles | Custom semantic structure styles | Record<SemanticDOM, CSSProperties> | - | |
| wheel | Whether to enable mouse wheel zoom | boolean | true | 6.6.0 |
| scaleStep | Each step's zoom multiplier is 1 + scaleStep | number | 0.5 | |
| Custom toolbar; please use 'actionsRender' instead | (originalNode: React.ReactElement, info: ToolbarRenderInfoType) => React.ReactNode | - | ||
| Whether to show; please use 'open' instead | boolean | - | ||
| onOpenChange | Callback when preview open state changes, includes current preview index | (visible: boolean, info: { current: number }) => void | - | |
| onChange | Callback when changing preview image | (current: number, prevCurrent: number) => void | - | |
| onTransform | Callback for preview transform changes | { transform: TransformType, action: TransformAction } | - | |
| Callback when 'visible' changes; please use 'onOpenChange' instead | (visible: boolean, prevVisible: boolean, current: number) => void | - |
废弃 API 与迁移路线
从 hooks/usePreviewConfig.ts 的 dev 警告可以看出完整的迁移矩阵,开发环境下传入旧属性会输出 deprecation/breaking 警告:
visible→open;onVisibleChange→onOpenChange;toolbarRender→actionsRender;maskClassName→classNames.cover;rootClassName(组预览)→classNames.root;wrapperStyle→styles.root;mask传 ReactNode 的旧用法 →cover;forceRender与destroyOnClose已被移除、不再支持:预览在打开后总会渲染。
得益于 hooks/usePreviewConfig.ts 的归一化逻辑(open: open ?? visible、onOpenChange 兼容旧回调、actionsRender: actionsRender ?? toolbarRender、cover ?? 旧 mask 元素),这些废弃写法在过渡期内仍可工作,方便分批升级。
Interface 定义
以下为文档定义的核心类型,均在自定义工具栏、预览内容与变换回调中直接使用。
TransformType
{
x: number;
y: number;
rotate: number;
scale: number;
flipX: boolean;
flipY: boolean;
}
TransformAction
type TransformAction =
| 'flipY'
| 'flipX'
| 'rotateLeft'
| 'rotateRight'
| 'zoomIn'
| 'zoomOut'
| 'close'
| 'prev'
| 'next'
| 'wheel'
| 'doubleClick'
| 'move'
| 'dragRebound'
| 'reset';
可以看到 onTransform 的 action 覆盖了按钮缩放、滚轮(wheel)、双击(doubleClick)、拖拽移动(move)乃至拖拽回弹(dragRebound)与复位(reset)等全部变换来源,方便你做数据埋点或状态同步。
ToolbarRenderInfoType
{
icons: {
flipYIcon: React.ReactNode;
flipXIcon: React.ReactNode;
rotateLeftIcon: React.ReactNode;
rotateRightIcon: React.ReactNode;
zoomOutIcon: React.ReactNode;
zoomInIcon: React.ReactNode;
};
actions: {
onActive?: (index: number) => void; // support after 5.21.0
onFlipY: () => void;
onFlipX: () => void;
onRotateLeft: () => void;
onRotateRight: () => void;
onZoomOut: () => void;
onZoomIn: () => void;
onReset: () => void; // support after 5.17.3
onClose: () => void;
};
transform: TransformType,
current: number;
total: number;
image: ImgInfo
}
ImgInfo
{
url: string;
alt: string;
width: string | number;
height: string | number;
}
CoverConfig
type CoverConfig = {
coverNode?: React.ReactNode; // The custom node of preview mask
placement?: 'top' | 'bottom' | 'center'; // Set the position of the preview mask display.
};
Semantic DOM 与 Design Token
Image 的语义 DOM 结构与各节点职责如下(交互式演示见 demo/_semantic.tsx,完整结构映射定义在 index.tsx 的 ImageSemanticType):
| 语义节点 | 职责 |
|---|---|
root |
根元素,相对定位 + inline-block 布局 |
image |
图片元素,负责宽高与垂直对齐 |
cover |
悬浮显示的预览提示层(绝对定位、半透明背景、hover 渐显) |
placeholder.progress |
进度占位内部结构(rail/indicator 等) |
popup.root |
预览弹层根节点(fixed 定位、z-index、遮罩与内容区) |
popup.mask |
预览背景遮罩(半透明底 + 可选 blur 效果) |
popup.body |
预览内容区(flex 居中、指针事件控制) |
popup.footer |
预览底部区域(计数与操作栏容器) |
popup.actions |
底部操作按钮组(圆角胶囊背景) |
popup.close |
右上角关闭按钮(6.4.0 起纳入语义节点) |
在 Design Token 层面,Image 通过 style/index.ts 的 prepareComponentToken 暴露了以下组件级 Token,可用 ConfigProvider 的 theme.components.Image 或 theme 的 token 覆盖:
zIndexPopup:预览浮层 z-index(默认在全局zIndexPopupBase基础上 +80);previewOperationSize:预览操作图标尺寸(默认fontSizeIcon * 1.5);previewOperationColor/previewOperationHoverColor/previewOperationColorDisabled:操作图标的常规、悬浮与禁用颜色(基于colorTextLightSolid透明度派生);progressAnimationDuration:加载动画的基础时长(默认3s,墨迹层动画时长在其上叠加偏移)。
对外的 classNames/styles 与 Token 覆盖、ConfigProvider 的组件级配置共同构成了三套渐进式定制体系:不换框架的全局统一(ConfigProvider)→ 语义化精确打点(classNames/styles)→ 深度主题定制(Design Token)。
边界与兼容性提示
- 语义化 classNames 相关能力以 6.0.0 为分水岭(如
preview.mask对象化、classNames.cover),6.4.0 又补充了popup.close语义节点与mask.closable、focusTrap;在旧版本中这些字段会被忽略,接入前请核对目标版本的组件版本号(文档 API 表中 Version 列已逐条标注)。 - 受控预览必须配合
onOpenChange:一旦传入open,预览开关即由外部接管,若不回调更新将无法关闭。 preview.src与src分离是性能利器:列表展示缩略图,打开预览才加载原图。- 内置的进度占位、水彩墨迹动画与遮罩 blur 均依赖现代 CSS(
backdrop-filter、渐变动画),在低版本浏览器中视觉表现可能退化,但不影响基本功能。
更多可直接运行、逐项演示上述能力的示例位于 components/image/demo 目录;对应的行为测试与语义快照测试(如 tests/index.test.tsx、tests/semantic.test.tsx)可帮助你确认各配置项在不同版本下的实际表现。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00