Skip to main content

纵向多媒体展示组件和横向容器

· 19 min read
Kyle
CTO of the Ph.D. Creative Station

本篇文章介绍了两个自主研发的 React 组件:纵向多媒体展示组件 VerticalMediaDisplay 和横向容器组件 HorizontalMediaContainerVerticalMediaDisplay 支持图片、视频、表格、自定义组件等多种媒体类型的纵向排版,具备统一的缩放预览、响应式设计和丰富的样式配置。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-A72Intel i5NVIDIA Jetson
内存4GB8GB16GB
续航时间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)

属性名类型默认值描述
titlestring-媒体标题(粗体显示)
captionstring-媒体说明(常规文本)
mediaAltstring-媒体内容的替代文本描述(用于无障碍)
childrenReactNode-媒体内容和其他子元素
onMediaClick() => void-媒体内容被点击时的回调函数
onTitleClick() => void-标题被点击时的回调函数
classNamestring""额外的 CSS 类名
shadowbooleanfalse是否显示阴影效果
compactbooleanfalse是否使用紧凑模式
mediaStyleCSSProperties{}媒体容器的自定义样式
mediaType"image" | "video" | "table" | "component" | "iframe""component"媒体内容类型,用于优化显示
disableZoombooleanfalse是否禁用图片的默认缩放功能

高级用法

带阴影效果

带阴影的产品
带阴影的展示
启用阴影效果可以让展示更加突出
<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>

设计特点

  1. 纵向布局:媒体内容在上方,标题和说明在下方,适合作品展示
  2. 多媒体支持:支持图片、视频、表格、iframe 等多种媒体类型
    • 图片:自动优化显示比例,支持点击放大预览
    • 视频:自动设置 16:9 宽高比,优化嵌入式播放体验
    • 表格:美化样式设计,支持响应式布局和深色模式
    • iframe:适配外部内容嵌入,保持统一的圆角和边框样式
    • 组件:支持自定义 React 组件作为媒体内容
      • 使用 <Media type="component"> 包装自定义组件
      • 可展示图表、仪表盘、交互式卡片、进度条等自定义内容
      • 完全保持组件的交互性和响应式特性
      • 自动应用统一的容器样式和圆角边框
  3. 文字样式:标题使用粗体,说明使用深色文本(var(--ifm-color-emphasis-800))确保可读性,与正文样式有所区别
  4. 居中对齐:所有内容都采用居中对齐,视觉效果统一
  5. 宽度控制:通过 mediaWidthRatio 属性精确控制媒体内容的宽度比例(0-100%)
  6. 响应式设计:在不同屏幕尺寸下都能保持良好的显示效果
  7. 图片缩放:内置图片点击放大功能,与横向组件保持一致的体验
    • 图片预览打开时会自动适配屏幕大小,确保最佳查看效果
    • "重置"按钮会恢复到图片预览打开时的初始状态(适合屏幕的缩放级别和居中位置)
    • 修复了带阴影图片的缩放预览 bug,确保所有图片的预览行为一致
    • 优化了悬停效果,避免与阴影容器的变换冲突
  8. 灵活性:支持多种媒体类型,可选的标题和说明配置

技术实现要点

  • 统一模态框渲染:完全重写了图片缩放功能,使用与 HorizontalMediaDisplay 完全相同的模态框渲染方式
    • 移除了所有 SSR/hydration 相关的检测代码,不再使用isClient状态或createPortal
    • 直接在组件树中渲染模态框,确保在所有部署环境(包括 Cloudflare Workers)中都能正常工作
    • 使用相同的useImageZoom hook 和事件处理逻辑,保证功能一致性
  • 部署环境兼容性:经过完全重写后,图片缩放功能现在在本地开发和生产部署环境中表现完全一致
    • 解决了之前在服务器部署后点击图片无法显示模态框的问题
    • 确保在各种静态站点托管平台(Vercel、Netlify、Cloudflare Pages 等)上都能正常工作
  • 悬停效果优化:只有在可点击状态(cursor: pointer)时才应用缩放悬停效果,避免与阴影容器变换冲突
  • 层级管理:模态框使用高优先级 z-index(9999),确保在所有内容之上正常显示
  • 变换隔离:媒体容器的悬停变换与阴影容器的变换相互独立,彻底消除闪烁问题
  • 统一体验:无论是否启用阴影效果,所有图片都具有完全一致的全屏预览体验
  • 自定义组件支持:通过 data-media="true" 属性自动识别媒体内容,支持任意 React 组件
    • 使用 <Media type="component"> 包装器确保组件被正确识别为媒体内容
    • 自动应用 .mediaTypeComponent 样式类,提供统一的容器样式
    • 保持组件内部的完整交互性和事件处理能力
    • 支持响应式设计和主题切换(亮色/深色模式)

HorizontalMediaContainer

HorizontalMediaContainer 是专门用于水平排列多个 VerticalMediaDisplay 组件的容器组件。它提供了灵活的宽度比例控制、响应式布局和多种对齐选项,让您可以轻松创建复杂的媒体展示布局。

基本用法

平均分配宽度

产品A
产品A
功能强大的基础版本
产品B
产品B
增强版本,更多功能
产品C
产品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>

设计特点

  1. 灵活的宽度控制:通过 widthRatios 属性精确控制每个子组件的宽度比例
  2. 空间优化:默认间距设置为 0.5rem,最大化内容展示区域,有效利用版面空间
  3. 响应式设计:自动在小屏幕设备上切换为垂直布局,确保良好的移动端体验
  4. 自定义断点:可以设置自定义的响应式断点,适应不同的设计需求
  5. 精细间距控制:通过 gap 属性控制子组件之间的间距,支持从紧凑到宽松的多种布局
  6. 对齐选项:支持多种垂直和水平对齐方式
  7. 容器控制:支持最大宽度限制和居中显示
  8. 完美兼容:专门为 VerticalMediaDisplay 优化,但也支持其他类型的子组件

技术实现要点

  • CSS Grid 布局:使用现代 CSS Grid 技术实现精确的宽度控制和对齐
  • 动态列模板:根据 widthRatios 动态生成 grid-template-columns
  • 响应式断点:使用 CSS 媒体查询和 CSS 变量实现灵活的响应式控制
  • 比例标准化:自动处理宽度比例的标准化,确保总和为 100%
  • 无障碍支持:提供适当的 ARIA 标签和语义化标记
  • 性能优化:最小化重新渲染,使用纯 CSS 实现布局效果

属性说明

属性类型默认值说明
childrenReactNode-子组件,通常是多个 VerticalMediaDisplay
widthRatiosnumber[]-各子组件的宽度比例数组,如 [30, 40, 30]
gapnumber0.5子组件间距 (rem)
alignItemsstring"stretch"垂直对齐:startcenterendstretch
justifyItemsstring"stretch"水平对齐:startcenterendstretch
responsivebooleantrue是否启用响应式布局
breakpointnumber768响应式断点 (px)
maxWidthstring-容器最大宽度
centeredbooleanfalse是否居中显示容器
classNamestring""额外的 CSS 类名
styleCSSProperties{}自定义样式