纵向多媒体展示组件和横向容器
· 19 min read
本篇文章介绍了两个自主研发的 React 组件:纵向多媒体展示组件 VerticalMediaDisplay
和横向容器组件 HorizontalMediaContainer
。VerticalMediaDisplay
支持图片、视频、表格、自定义组件等多种媒体类型的纵向排版,具备统一的缩放预览、响应式设计和丰富的样式配置。HorizontalMediaContainer
则用于将多个纵向媒体单元以灵活的宽度比例和间距进行横向排列,支持响应式断点、居中显示和多种对齐方式。文章详细展示了各类用法示例、属性说明及关键技术实现要点,为技术文档和产品展示场景提供了高效、美观的多媒体排版解决方案。
定义:
- "纵向媒体单元",是指媒体内容在上方,标题和说明在下方的垂直排列布局。
VerticalMediaDisplay
组件专门用于创建这种纵向排列的媒体展示单元。- 与横向布局组件不同,纵向布局更适合展示图片集、产品展示、作品集等场景。
VerticalMediaDisplay 的开发
VerticalMediaDisplay
组件用于创建媒体内容和描述信息在垂直方向上排列的展示单元。它采用媒体在上、文字在下的布局,支持图片、视频、表格等多种媒体类型,并提供统一的缩放预览功能。
基本用法
图片展示
智能机器人产品
这是一款功能强大的智能机器人展示
<VerticalMediaDisplay
title="智能机器人产品"
caption="这是一款功能强大的智能机器人展示"
>
<MediaImage
src="https://picsum.photos/400/300?random=1"
alt="智能机器人产品图片"
/>
</VerticalMediaDisplay>
仅标题展示
产品特写
<VerticalMediaDisplay
title="产品特写"
>
<MediaImage
src="https://picsum.photos/400/300?random=2"
alt="产品特写"
/>
</VerticalMediaDisplay>
仅说明展示
无标题的产品展示,仅包含说明文字
<VerticalMediaDisplay
caption="无标题的产品展示,仅包含说明文字"
>
<MediaImage
src="https://picsum.photos/400/300?random=3"
alt="产品展示"
/>
</VerticalMediaDisplay>
视频展示
产品演示视频
观看完整产品功能演示
<VerticalMediaDisplay
title="产品演示视频"
caption="观看完整产品功能演示"
mediaType="video"
> <MediaVideo title="产品演示">
<iframe
width="100%"
height="200"
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
title="产品演示视频"
style={{ border: "none" }}
allowFullScreen
/>
</MediaVideo>
</VerticalMediaDisplay>
表格数据展示
参数 | 型号 A | 型号 B | 型号 C |
---|---|---|---|
处理器 | ARM Cortex-A72 | Intel i5 | NVIDIA Jetson |
内存 | 4GB | 8GB | 16GB |
续航时间 | 4 小时 | 6 小时 | 8 小时 |
价格 | ¥2,999 | ¥4,999 | ¥8,999 |
技术规格参数
详细技术参数对比表
<VerticalMediaDisplay
title="技术规格参数"
caption="详细技术参数对比表"
mediaType="table"
>
<MediaTable caption="产品规格表">
<table>
<thead>
<tr>
<th>参数</th>
<th>型号 A</th>
<th>型号 B</th>
<th>型号 C</th>
</tr>
</thead>
<tbody>
<tr>
<td>处理器</td>
<td>ARM Cortex-A72</td>
<td>Intel i5</td>
<td>NVIDIA Jetson</td>
</tr>
<tr>
<td>内存</td>
<td>4GB</td>
<td>8GB</td>
<td>16GB</td>
</tr>
<tr>
<td>续航时间</td>
<td>4 小时</td>
<td>6 小时</td>
<td>8 小时</td>
</tr>
<tr>
<td>价格</td>
<td>¥2,999</td>
<td>¥4,999</td>
<td>¥8,999</td>
</tr>
</tbody>
</table>
</MediaTable>
</VerticalMediaDisplay>
Markdown 表格展示
平台 | 支持状态 | 版本要求 | 备注 |
---|---|---|---|
Windows | ✅ 完全支持 | Win10+ | 推荐使用 |
macOS | ✅ 完全支持 | 10.15+ | Intel/Apple Silicon |
Linux | ✅ 完全支持 | Ubuntu 18.04+ | 需要额外配置 |
Android | ⚠️ 部分支持 | API 21+ | 功能受限 |
iOS | ❌ 不支持 | - | 计划中 |
兼容性矩阵
支持的操作系统和平台
<VerticalMediaDisplay
title="兼容性矩阵"
caption="支持的操作系统和平台"
mediaType="table"
>
<MarkdownTable caption="平台兼容性">
{`| 平台 | 支持状态 | 版本要求 | 备注 |
|------|----------|----------|------|
| Windows | ✅ 完全支持 | Win10+ | 推荐使用 |
| macOS | ✅ 完全支持 | 10.15+ | Intel/Apple Silicon |
| Linux | ✅ 完全支持 | Ubuntu 18.04+ | 需要额外配置 |
| Android | ⚠️ 部分支持 | API 21+ | 功能受限 |
| iOS | ❌ 不支持 | - | 计划中 |`}
</MarkdownTable>
</VerticalMediaDisplay>
组件属性 (API)
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
title | string | - | 媒体标题(粗体显示) |
caption | string | - | 媒体说明(常规文本) |
mediaAlt | string | - | 媒体内容的替代文本描述(用于无障碍) |
children | ReactNode | - | 媒体内容和其他子元素 |
onMediaClick | () => void | - | 媒体内容被点击时的回调函数 |
onTitleClick | () => void | - | 标题被点击时的回调函数 |
className | string | "" | 额外的 CSS 类名 |
shadow | boolean | false | 是否显示阴影效果 |
compact | boolean | false | 是否使用紧凑模式 |
mediaStyle | CSSProperties | {} | 媒体容器的自定义样式 |
mediaType | "image" | "video" | "table" | "component" | "iframe" | "component" | 媒体内容类型,用于优化显示 |
disableZoom | boolean | false | 是否禁用图片的默认缩放功能 |
高级用法
带阴影效果
带阴影的展示
启用阴影效果可以让展示更加突出
<VerticalMediaDisplay
title="带阴影的展示"
caption="启用阴影效果可以让展示更加突出"
shadow={true}
>
<MediaImage
src="https://picsum.photos/400/300?random=4"
alt="带阴影的产品"
/>
</VerticalMediaDisplay>
紧凑模式
紧凑展示
紧凑模式减少间距,适合密集布局
<VerticalMediaDisplay
title="紧凑展示"
caption="紧凑模式减少间距,适合密集布局"
compact={true}
>
<MediaImage
src="https://picsum.photos/400/300?random=5"
alt="紧凑模式产品"
/>
</VerticalMediaDisplay>
自定义宽度展示
自定义宽度展示
通过 mediaWidthRatio 自定义媒体宽度
<VerticalMediaDisplay
title="自定义宽度展示"
caption="通过 mediaWidthRatio 自定义媒体宽度"
mediaWidthRatio={70}
>
<MediaImage
src="https://picsum.photos/400/300?random=6"
alt="自定义宽度产品"
/>
</VerticalMediaDisplay>
自定义组件展示
系统性能监控
92%
CPU 使用率
78%
内存使用率
45°C
系统温度
自定义图表组件
展示自定义React组件,如图表、数据可视化等
<VerticalMediaDisplay
title="自定义图表组件"
caption="展示自定义React组件,如图表、数据可视化等"
mediaType="component"
>
<Media type="component" alt="性能监控图表">
<div style={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
borderRadius: '12px',
padding: '2rem',
color: 'white',
textAlign: 'center',
minHeight: '200px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
gap: '1rem'
}}>
<h3 style={{ margin: 0, fontSize: '1.5rem' }}>系统性能监控</h3>
<div style={{ display: 'flex', justifyContent: 'space-around', gap: '1rem' }}>
<div>
<div style={{ fontSize: '2rem', fontWeight: 'bold' }}>92%</div>
<div style={{ fontSize: '0.9rem', opacity: 0.8 }}>CPU 使用率</div>
</div>
<div>
<div style={{ fontSize: '2rem', fontWeight: 'bold' }}>78%</div>
<div style={{ fontSize: '0.9rem', opacity: 0.8 }}>内存使用率</div>
</div>
<div>
<div style={{ fontSize: '2rem', fontWeight: 'bold' }}>45°C</div>
<div style={{ fontSize: '0.9rem', opacity: 0.8 }}>系统温度</div>
</div>
</div>
</div>
</Media>
</VerticalMediaDisplay>
交互式卡片组件
🤖
机器人控制面板
状态:待机中 | 电量:85%
交互式功能卡片
带有按钮和状态的交互式组件展示
<VerticalMediaDisplay
title="交互式功能卡片"
caption="带有按钮和状态的交互式组件展示"
mediaType="component"
>
<Media type="component" alt="功能控制卡片">
<div style={{
border: '2px solid var(--ifm-color-primary)',
borderRadius: '16px',
padding: '1.5rem',
background: 'var(--ifm-background-color)',
boxShadow: 'var(--ifm-global-shadow-md)',
textAlign: 'center'
}}>
<div style={{
fontSize: '3rem',
marginBottom: '1rem',
filter: 'hue-rotate(120deg)'
}}>🤖</div>
<h4 style={{
margin: '0 0 1rem 0',
color: 'var(--ifm-color-primary)',
fontSize: '1.3rem'
}}>
机器人控制面板
</h4>
<div style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gap: '0.8rem',
marginBottom: '1rem'
}}>
<button style={{
padding: '0.6rem',
borderRadius: '8px',
border: '1px solid var(--ifm-color-primary)',
background: 'var(--ifm-color-primary)',
color: 'white',
cursor: 'pointer',
fontSize: '0.9rem'
}}>
启动
</button>
<button style={{
padding: '0.6rem',
borderRadius: '8px',
border: '1px solid var(--ifm-color-emphasis-400)',
background: 'transparent',
color: 'var(--ifm-color-emphasis-800)',
cursor: 'pointer',
fontSize: '0.9rem'
}}>
停止
</button>
</div>
<div style={{
fontSize: '0.85rem',
color: 'var(--ifm-color-emphasis-600)',
padding: '0.5rem',
background: 'var(--ifm-color-emphasis-100)',
borderRadius: '6px'
}}>
状态:待机中 | 电量:85%
</div>
</div>
</Media>
</VerticalMediaDisplay>
进度展示组件
机器人项目开发进度
硬件设计95%
软件开发78%
系统集成42%
测试验证15%
项目进度展示
使用自定义组件展示项目开发进度
<VerticalMediaDisplay
title="项目进度展示"
caption="使用自定义组件展示项目开发进度"
mediaType="component"
>
<Media type="component" alt="项目进度条">
<div style={{
padding: '1.5rem',
background: 'var(--ifm-background-color)',
borderRadius: '12px',
border: '1px solid var(--ifm-color-emphasis-200)'
}}>
<h4 style={{
margin: '0 0 1.5rem 0',
textAlign: 'center',
color: 'var(--ifm-color-emphasis-800)'
}}>
机器人项目开发进度
</h4>
{[
{ name: '硬件设计', progress: 95, color: '#28a745' },
{ name: '软件开发', progress: 78, color: '#007bff' },
{ name: '系统集成', progress: 42, color: '#ffc107' },
{ name: '测试验证', progress: 15, color: '#dc3545' }
].map((item, index) => (
<div key={index} style={{ marginBottom: '1rem' }}>
<div style={{
display: 'flex',
justifyContent: 'space-between',
marginBottom: '0.3rem',
fontSize: '0.9rem',
color: 'var(--ifm-color-emphasis-700)'
}}>
<span>{item.name}</span>
<span>{item.progress}%</span>
</div>
<div style={{
background: 'var(--ifm-color-emphasis-200)',
borderRadius: '10px',
height: '8px',
overflow: 'hidden'
}}>
<div style={{
background: item.color,
height: '100%',
width: `${item.progress}%`,
borderRadius: '10px',
transition: 'width 0.3s ease'
}} />
</div>
</div>
))}
</div>
</Media>
</VerticalMediaDisplay>
设计特点
- 纵向布局:媒体内容在上方,标题和说明在下方,适合作品展示
- 多媒体支持:支持图片、视频、表格、iframe 等多种媒体类型
- 图片:自动优化显示比例,支持点击放大预览
- 视频:自动设置 16:9 宽高比,优化嵌入式播放体验
- 表格:美化样式设计,支持响应式布局和深色模式
- iframe:适配外部内容嵌入,保持统一的圆角和边框样式
- 组件:支持自定义 React 组件作为媒体内容
- 使用
<Media type="component">
包装自定义组件 - 可展示图表、仪表盘、交互式卡片、进度条等自定义内容
- 完全保持组件的交互性和响应式特性
- 自动应用统一的容器样式和圆角边框
- 使用
- 文字样式:标题使用粗体,说明使用深色文本(
var(--ifm-color-emphasis-800)
)确保可读性,与正文样式有所区别 - 居中对齐:所有内容都采用居中对齐,视觉效果统一
- 宽度控制:通过
mediaWidthRatio
属性精确控制媒体内容的宽度比例(0-100%) - 响应式设计:在不同屏幕尺寸下都能保持良好的显示效果
- 图片缩放:内置图片点击放大功能,与横向组件保持一致的体验
- 图片预览打开时会自动适配屏幕大小,确保最佳查看效果
- "重置"按钮会恢复到图片预览打开时的初始状态(适合屏幕的缩放级别和居中位置)
- 修复了带阴影图片的缩放预览 bug,确保所有图片的预览行为一致
- 优化了悬停效果,避免与阴影容器的变换冲突
- 灵活性:支持多种媒体类型,可选的标题和说明配置
技术实现要点
- 统一模态框渲染:完全重写了图片缩放功能,使用与 HorizontalMediaDisplay 完全相同的模态框渲染方式
- 移除了所有 SSR/hydration 相关的检测代码,不再使用
isClient
状态或createPortal
- 直接在组件树中渲染模态框,确保在所有部署环境(包括 Cloudflare Workers)中都能正常工作
- 使用相同的
useImageZoom
hook 和事件处理逻辑,保证功能一致性
- 移除了所有 SSR/hydration 相关的检测代码,不再使用
- 部署环境兼容性:经过完全重写后,图片缩放功能现在在本地开发和生产部署环境中表现完全一致
- 解决了之前在服务器部署后点击图片无法显示模态框的问题
- 确保在各种静态站点托管平台(Vercel、Netlify、Cloudflare Pages 等)上都能正常工作
- 悬停效果优化:只有在可点击状态(cursor: pointer)时才应用缩放悬停效果,避免与阴影容器变换冲突
- 层级管理:模态框使用高优先级 z-index(9999),确保在所有内容之上正常显示
- 变换隔离:媒体容器的悬停变换与阴影容器的变换相互独立,彻底消除闪烁问题
- 统一体验:无论是否启用阴影效果,所有图片都具有完全一致的全屏预览体验
- 自定义组件支持:通过
data-media="true"
属性自动识别媒体内容,支持任意 React 组件- 使用
<Media type="component">
包装器确保组件被正确识别为媒体内容 - 自动应用
.mediaTypeComponent
样式类,提供统一的容器样式 - 保持组件内部的完整交互性和事件处理能力
- 支持响应式设计和主题切换(亮色/深色模式)
- 使用
HorizontalMediaContainer
HorizontalMediaContainer
是专门用于水平排列多个 VerticalMediaDisplay
组件的容器组件。它提供了灵活的宽度比例控制、响应式布局和多种对齐选项,让您可以轻松创建复杂的媒体展示布局。
基本用法
平均分配宽度
产品A
功能强大的基础版本
产品B
增强版本,更多功能
产品C
专业版本,完整功能
<HorizontalMediaContainer>
<VerticalMediaDisplay
title="产品A"
caption="功能强大的基础版本"
>
<MediaImage
src="https://picsum.photos/300/200?random=10"
alt="产品A"
/>
</VerticalMediaDisplay>
<VerticalMediaDisplay
title="产品B"
caption="增强版本,更多功能"
>
<MediaImage
src="https://picsum.photos/300/200?random=11"
alt="产品B"
/>
</VerticalMediaDisplay>
<VerticalMediaDisplay
title="产品C"
caption="专业版本,完整功能"
>
<MediaImage
src="https://picsum.photos/300/200?random=12"
alt="产品C"
/>
</VerticalMediaDisplay>
</HorizontalMediaContainer>
自定义宽度比例
缩略图
20%宽度
主要内容
50%宽度,突出显示
辅助信息
30%宽度
<HorizontalMediaContainer widthRatios={[20, 50, 30]}>
<VerticalMediaDisplay
title="缩略图"
caption="20%宽度"
>
<MediaImage
src="https://picsum.photos/300/200?random=13"
alt="缩略图"
/>
</VerticalMediaDisplay>
<VerticalMediaDisplay
title="主要内容"
caption="50%宽度,突出显示"
>
<MediaImage
src="https://picsum.photos/300/200?random=14"
alt="主要内容"
/>
</VerticalMediaDisplay>
<VerticalMediaDisplay
title="辅助信息"
caption="30%宽度"
>
<MediaImage
src="https://picsum.photos/300/200?random=15"
alt="辅助信息"
/>
</VerticalMediaDisplay>
</HorizontalMediaContainer>
混合媒体类型展示
参数 | 数值 |
---|---|
处理器 | ARM Cortex-A72 |
内存 | 4GB LPDDR4 |
存储 | 64GB eMMC |
续航 | 8 小时 |
产品规格
详细技术参数对比
演示视频
观看产品实际运行效果
🟢
系统正常
运行时间:72 小时
CPU: 23% | 内存:56%
实时状态
当前系统运行状态
<HorizontalMediaContainer
widthRatios={[40, 35, 25]}
gap={0.8}
maxWidth="1200px"
centered={true}
>
<VerticalMediaDisplay
title="产品规格"
caption="详细技术参数对比"
mediaType="table"
>
{/* 表格内容 */}
</VerticalMediaDisplay>
<VerticalMediaDisplay
title="演示视频"
caption="观看产品实际运行效果"
mediaType="video"
>
{/* 视频内容 */}
</VerticalMediaDisplay>
<VerticalMediaDisplay
title="实时状态"
caption="当前系统运行状态"
mediaType="component"
>
{/* 自定义组件内容 */}
</VerticalMediaDisplay>
</HorizontalMediaContainer>
响应式布局控制
主要产品展示
更大的展示区域,突出重点产品
核心特色
- 🚀 高性能处理
- 🔋 超长续航
- 🛡️ 安全可靠
- 🌐 云端同步
产品特色
简洁的特色说明
<HorizontalMediaContainer
widthRatios={[60, 40]}
responsive={true}
breakpoint={900} // 自定义断点
gap={1}
>
<VerticalMediaDisplay
title="主要产品展示"
caption="更大的展示区域,突出重点产品"
>
<MediaImage
src="https://picsum.photos/400/250?random=16"
alt="主要产品"
/>
</VerticalMediaDisplay>
<VerticalMediaDisplay
title="产品特色"
caption="简洁的特色说明"
>
{/* 自定义特色展示组件 */}
</VerticalMediaDisplay>
</HorizontalMediaContainer>
设计特点
- 灵活的宽度控制:通过
widthRatios
属性精确控制每个子组件的宽度比例 - 空间优化:默认间距设置为
0.5rem
,最大化内容展示区域,有效利用版面空间 - 响应式设计:自动在小屏幕设备上切换为垂直布局,确保良好的移动端体验
- 自定义断点:可以设置自定义的响应式断点,适应不同的设计需求
- 精细间距控制:通过
gap
属性控制子组件之间的间距,支持从紧凑到宽松的多种布局 - 对齐选项:支持多种垂直和水平对齐方式
- 容器控制:支持最大宽度限制和居中显示
- 完美兼容:专门为
VerticalMediaDisplay
优化,但也支持其他类型的子组件
技术实现要点
- CSS Grid 布局:使用现代 CSS Grid 技术实现精确的宽度控制和对齐
- 动态列模板:根据
widthRatios
动态生成grid-template-columns
值 - 响应式断点:使用 CSS 媒体查询和 CSS 变量实现灵活的响应式控制
- 比例标准化:自动处理宽度比例的标准化,确保总和为 100%
- 无障碍支持:提供适当的 ARIA 标签和语义化标记
- 性能优化:最小化重新渲染,使用纯 CSS 实现布局效果
属性说明
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
children | ReactNode | - | 子组件,通常是多个 VerticalMediaDisplay |
widthRatios | number[] | - | 各子组件的宽度比例数组,如 [30, 40, 30] |
gap | number | 0.5 | 子组件间距 (rem) |
alignItems | string | "stretch" | 垂直对齐:start 、center 、end 、stretch |
justifyItems | string | "stretch" | 水平对齐:start 、center 、end 、stretch |
responsive | boolean | true | 是否启用响应式布局 |
breakpoint | number | 768 | 响应式断点 (px) |
maxWidth | string | - | 容器最大宽度 |
centered | boolean | false | 是否居中显示容器 |
className | string | "" | 额外的 CSS 类名 |
style | CSSProperties | {} | 自定义样式 |