Skip to Content
@anker-in/headless-ui 2.0 is released 🎉

ImageWithText (图文分栏1)

多功能图文展示组件,支持三种运行模式、四种布局方向、图片视频媒体类型、Tab切换和按钮交互。【✅ 已发布】

加载中...
当前视口: 1920px × 600px场景: 图左文右布局
打开链接

功能特性

ImageWithText 组件是一个全能型图文展示组件,具有以下核心能力:

  • 三种运行模式 - 基础模式、Tab 切换模式、按钮交互模式
  • 四种布局方向 - 左文右图、右文左图、上文下图、下文上图(layout: left | right | top | bottom)
  • 双媒体类型支持 - 支持图片和视频,视频带懒加载和自动播放
  • 三端独立配置 - 桌面端、平板端、移动端可分别配置图片/视频
  • Tab 切换动画 - 平滑滑块动画 + Framer Motion 内容切换效果
  • 功能列表展示 - 支持带图标的功能特性列表,图标标题带蓝色渐变效果
  • 按钮功能 - 支持 primary/secondary 两种按钮样式,自动影响文本区对齐方式
  • 文本对齐控制 - 支持左对齐和居中对齐(textAlign: left | center)
  • 视频封面图 - 图片自动作为视频 poster,支持三端独立封面
  • 响应式布局 - 移动端自动切换为上文下图布局,5 个断点完整适配
  • BEM 类名体系 - 完整的 BEM 命名规范,支持深度样式定制
  • 曝光追踪 - 内置 useExposure hook,自动追踪组件曝光
  • 主题切换 - 支持 light/dark 主题
  • TypeScript 严格模式 - 完整的类型定义和类型安全

Props 参数

ImageWithTextProps

属性类型必填默认值说明
dataImageWithTextData-组件数据配置
classNamestring-自定义类名

ImageWithTextData

字段类型必填默认值说明
titlestring-主标题
subtitlestring-副标题/描述文本
descstring-大号高亮描述文本(基础模式/Tab 模式)
descIconstring-描述文本图标(基础模式)
theme'light' | 'dark''dark'主题颜色
layout'left' | 'right' | 'top' | 'bottom''left'布局位置,控制媒体区和文本区的相对位置
mediaType'image' | 'video''image'媒体类型,支持图片和视频
textAlign'left' | 'center''left'文本区域对齐方式
imageMedia-桌面端图片(视频模式下作为封面图)
videoMedia-桌面端视频 URL(mediaType=‘video’ 时使用)
padImageMedia-平板端图片(fallback 到 image)
padVideoMedia-平板端视频 URL(fallback 到 video)
mobileImageMedia-移动端图片(fallback 到 image)
mobVideoMedia-移动端视频 URL(fallback 到 video)
itemsImageWithTextItem[][]功能特性列表(基础模式)
datalistImageWithTextTabItem[][]Tab 数据列表(Tab 模式,优先级最高)
buttonButtonConfig-按钮配置

ImageWithTextItem

字段类型必填说明
iconMedia功能图标
textstring功能标题(带蓝色渐变效果)
descstring功能描述

ImageWithTextTabItem

字段类型必填说明
titlestringTab 标题
imageMedia桌面端图片(视频模式下作为封面图)
imgPadMedia平板端图片(fallback 到 image)
imageMobMedia移动端图片(fallback 到 image)
videoMedia桌面端视频 URL(mediaType=‘video’ 时使用)
padVideoMedia平板端视频 URL(fallback 到 video)
mobVideoMedia移动端视频 URL(fallback 到 video)

ButtonConfig

字段类型必填默认值说明
textstring-按钮文字
linkstring-跳转链接
variant'primary' | 'secondary''primary'按钮样式类型

Media

属性类型必填说明
urlstring媒体资源 URL
altstring无障碍替代文本
thumbnailURLstring缩略图 URL
mimeTypestringMIME 类型

使用示例

基础图文模式 - 左文右图

import { ImageWithText } from '@anker-in/headless-ui/biz' export default function Example() { return ( <ImageWithText data={{ title: 'Precise Navigation', subtitle: 'iPath Laser Navigation plans optimal cleaning routes.', layout: 'left', // 默认值,可省略 image: { url: '/precise_navigation.png', alt: 'Precise Navigation', }, padImage: { url: '/precise_navigation_pad.png', alt: 'Precise Navigation Pad', }, mobileImage: { url: '/precise_navigation_mobile.png', alt: 'Precise Navigation Mobile', }, }} /> ) }

适用场景: 产品功能介绍页、产品详情页的基础图文展示

基础模式 + 功能列表 + 渐变图标标题

<ImageWithText data={{ title: 'AI.See™ Obstacle Avoidance', subtitle: 'Advanced AI and RGB visual recognition.', layout: 'left', image: { url: '/ai-avoidance.png', alt: 'AI Obstacle Avoidance', }, mobileImage: { url: '/ai-avoidance-mobile.png', alt: 'AI Obstacle Avoidance Mobile', }, items: [ { icon: { url: '/led-icon.svg', alt: 'LED' }, text: 'LED', // 标题会自动应用蓝色渐变效果 desc: 'Equipped with LEDs for dark environments', }, { icon: { url: '/200-icon.svg', alt: '200+' }, text: '200+', desc: 'Identifies and avoids 200+ objects.', }, ], }} />

适用场景: 需要强调产品多个技术特性的场景,items 数组的图标标题自动应用 from-[#3ad1ff] to-[#008cd6] 渐变效果

视频模式 - 三端独立视频配置

<ImageWithText data={{ title: 'DuoSpiral™ Detangle Brushes', subtitle: 'DuoSpiral™ brushes prevent hair from getting tangled.', layout: 'left', mediaType: 'video', // 启用视频模式 // 桌面端视频和封面图 video: { url: '/desktop-video.mp4', alt: 'DuoSpiral Video' }, image: { url: '/video-poster.jpg', alt: 'Video Poster' }, // 移动端独立视频和封面图 mobVideo: { url: '/mobile-video.mp4', alt: 'DuoSpiral Mobile Video' }, mobileImage: { url: '/mobile-poster.jpg', alt: 'Mobile Video Poster' }, }} />

适用场景: 需要展示产品动态效果、使用演示的场景

关键特性:

  • 视频自动循环播放、静音、行内播放
  • IntersectionObserver 懒加载优化
  • 三端独立视频源,移动端可使用压缩版本
  • image 字段自动作为 video 的 poster

Tab 切换模式 - 多功能展示

<ImageWithText data={{ title: 'Smart App Control', desc: 'Effortless customization at your fingertips.', // 当存在 datalist 时,自动启用 Tab 模式 datalist: [ { title: 'Customizable Cleaning Modes', image: { url: '/mode-1.png', alt: 'Cleaning Modes' }, imgPad: { url: '/mode-1-pad.png', alt: 'Cleaning Modes Pad' }, imageMob: { url: '/mode-1-mobile.png', alt: 'Cleaning Modes Mobile' }, }, { title: 'Multi-Floor Mapping', image: { url: '/mode-2.png', alt: 'Floor Mapping' }, imgPad: { url: '/mode-2-pad.png', alt: 'Floor Mapping Pad' }, imageMob: { url: '/mode-2-mobile.png', alt: 'Floor Mapping Mobile' }, }, ], }} />

适用场景: 需要在同一区域展示多个相关功能、多个产品特性对比的场景

关键特性:

  • Tab 切换带平滑滑块动画
  • 内容切换使用 Framer Motion 淡入淡出效果
  • 点击 Tab 自动居中滚动
  • 支持三端独立图片配置

Tab 模式 + 视频

<ImageWithText data={{ title: 'Smart App Control', desc: 'Effortless customization at your fingertips.', mediaType: 'video', // 启用视频模式 datalist: [ { title: 'Customizable Cleaning Modes', video: { url: '/mode-1-video.mp4', alt: 'Cleaning Modes Video' }, image: { url: '/mode-1-poster.jpg', alt: 'Cleaning Modes Poster' }, mobVideo: { url: '/mode-1-mobile.mp4', alt: 'Cleaning Modes Mobile' }, imageMob: { url: '/mode-1-mobile-poster.jpg', alt: 'Mobile Poster' }, }, { title: 'Multi-Floor Mapping', video: { url: '/mode-2-video.mp4', alt: 'Floor Mapping Video' }, image: { url: '/mode-2-poster.jpg', alt: 'Floor Mapping Poster' }, }, ], }} />

适用场景: 需要通过视频动态展示多个产品功能的高级场景

关键特性:

  • Tab 切换时视频重新加载并播放
  • 视频播放失败静默处理,不影响用户体验
  • 每个 Tab 可配置独立的三端视频

带按钮的交互式图文

<ImageWithText data={{ title: '革新清洁体验', subtitle: '看见科技如何重新定义家居清洁', layout: 'top', // 上文下图布局 mediaType: 'video', video: { url: '/product-demo.mp4', alt: '产品演示' }, image: { url: '/product-demo-poster.jpg', alt: '产品演示封面' }, items: [ { icon: { url: 'ai-icon.png', alt: 'AI' }, text: 'AI 视觉识别', desc: '先进 AI 算法,智能识别并避开障碍物', }, { icon: { url: 'quiet-icon.png', alt: 'Quiet' }, text: '静音运行', desc: '噪音控制在 55dB 以下,静享清洁时光', }, ], button: { text: '查看详细参数', link: '/specs', variant: 'secondary', // 次要按钮样式(边框样式) }, }} />

适用场景: 需要引导用户点击跳转的营销页面、落地页

关键特性:

  • 按钮存在时,文本区由垂直居中改为 justify-between 对齐
  • 支持 primary(填充样式)和 secondary(边框样式)两种按钮变体
  • 按钮自动带右箭头图标
  • top/bottom 布局时,laptop 以上尺寸按钮显示在标题行右侧

文本居中对齐模式

<ImageWithText data={{ title: 'Precise Navigation', subtitle: 'iPath Laser Navigation plans optimal cleaning routes.', layout: 'left', textAlign: 'center', // 文本居中对齐 image: { url: '/precise_navigation.png', alt: 'Precise Navigation' }, items: [ { icon: { url: 'led-icon.svg', alt: 'LED' }, text: 'LED', desc: 'Equipped with LEDs', }, { icon: { url: '200-icon.svg', alt: '200+' }, text: '200+', desc: 'Identifies 200+ objects', }, ], button: { text: '立即购买', link: 'https://example.com', variant: 'primary', }, }} />

适用场景: 需要强调内容重要性、创造视觉聚焦的场景

关键特性:

  • 标题、副标题、描述文本全部居中对齐
  • 功能列表图标和标题居中对齐
  • 按钮居中显示
  • Tab 模式下 Tab 导航栏也会居中

响应式行为

断点定义

断点屏幕宽度布局变化特性
Mobile< 768px强制上文下图所有 layout 统一为上文下图,items 网格 2 列
Tablet≥ 768px支持横向布局left/right 开始生效,items 网格 4 列
Laptop≥ 1025px完整布局支持所有 layout 完全生效,items 根据 layout 调整
Desktop≥ 1440px间距增大gap 从 48px 增至 64px,字体大小增大
LG Desktop≥ 1920px最大尺寸超大屏优化,视频显示桌面端版本

布局响应式逻辑

// 基础模式 layout: 'left'Mobile: 上文下图, Laptop+: 左文右图 layout: 'right'Mobile: 上文下图, Laptop+: 右文左图 layout: 'top'所有断点: 上文下图 layout: 'bottom'所有断点: 下文上图

功能列表网格响应式

// 当 layout 为 left 或 right 时 Mobile: 2 (grid-cols-2) Tablet: 4 (tablet:grid-cols-4) Laptop+: 2 (laptop:grid-cols-2) // 当 layout 为 top 或 bottom 时 Mobile: 2 (grid-cols-2) Tablet+: 4 (tablet:grid-cols-4)

间距响应式

组件主间距: Mobile: 24px (gap-[24px]) Laptop: 48px (laptop:gap-[48px]) LG Desktop: 64px (lg-desktop:gap-[64px]) 功能列表 margin-top: Mobile: 24px (mt-[24px]) Laptop: 32px (laptop:mt-[32px]) Desktop: 48px (desktop:mt-[48px]) Top/Bottom: 24px (!mt-6, 固定值) 按钮 margin-top: Mobile: 24px (mt-[24px]) Laptop: 32px (laptop:mt-[32px])

视频响应式显示

桌面端视频: LG Desktop 及以上显示 (lg-desktop:block) 平板端视频: Tablet 到 LG Desktop 之间显示 (tablet:block lg-desktop:hidden) 移动端视频: Mobile 显示 (block tablet:hidden)

设计规范

标题和描述

  • 标题长度: 建议 20-40 个字符,过长会影响阅读体验
  • 副标题长度: 建议 50-100 个字符
  • desc 文本: 大号高亮文本,建议 10-20 个字符,适合数字、简短 slogan
  • descIcon 尺寸: 推荐 36x36px (移动端) / 48x48px (桌面端)

功能列表 items

  • 推荐数量: 2-4 个功能项,过多会显得拥挤
  • 图标尺寸: 推荐 28px (移动端) / 44-52px (桌面端)
  • 图标格式: 建议使用 SVG 格式,支持响应式缩放
  • 功能标题: 建议 2-8 个字符,过长会影响渐变效果
  • 功能描述: 建议 20-50 个字符

Tab 数据 datalist

  • 推荐数量: 2-4 个 Tab 项,过多会导致移动端显示不完整
  • Tab 标题: 建议 6-15 个字符,避免换行
  • Tab 滑块动画: transition-all duration-300 ease-in-out

图片和视频

  • 图片格式: 推荐 WebP 或 AVIF(fallback 到 JPG/PNG)
  • 桌面端图片尺寸: 推荐 800x600px 或更大,aspect-ratio 根据 layout 自动调整
  • 移动端图片尺寸: 推荐 600x800px 或更大
  • 视频格式: 推荐 MP4 (H.264 编码)
  • 视频大小:
    • 桌面端: 建议 5MB 以内
    • 移动端: 建议 2MB 以内,使用压缩版本
  • 视频时长: 建议 10-30 秒,循环播放

按钮

  • 按钮文字: 建议 4-8 个字符,过长会影响按钮美观度
  • 按钮样式:
    • primary: 填充样式,用于主要操作
    • secondary: 边框样式,用于次要操作
  • 按钮位置:
    • left/right 布局: 按钮在文本区底部,左对齐或居中(根据 textAlign)
    • top/bottom 布局: laptop+ 时按钮在标题行右侧,mobile 时在文本区底部

颜色规范

  • 功能标题渐变: from-[#3ad1ff] to-[#008cd6](固定值,不可修改)
  • desc 文本颜色: #3AD1FF(固定值,亮蓝色)
  • Tab 滑块背景: bg-white(固定值)
  • Tab 背景: bg-[#1D1D1F](固定值,深灰色)

无障碍性

语义化 HTML

<section> {/* 使用 section 作为根元素 */} <div className="content"> <Heading as="h2" size={4}> {/* 标题使用语义化 Heading 组件 */} {title} </Heading> <Text as="p" size={3}> {/* 描述使用 Text 组件 */} {subtitle} </Text> </div> <Picture /> {/* 图片使用 Picture 组件,自动处理 alt */} </section>

ARIA 属性

  • data-ui-component-id: "ImageWithText" - 组件标识,便于测试和追踪
  • video 元素:
    • playsInline - 移动端行内播放,不全屏
    • muted - 静音播放,避免打扰用户
    • poster - 视频封面图,提升加载体验
    • loop - 循环播放

键盘导航

  • Tab 切换: Tab 按钮支持键盘点击事件
  • 按钮链接: 使用 Link 组件,支持键盘导航(Enter/Space 键)
  • 焦点管理: Tab 切换后自动滚动到视图中心

曝光追踪

useExposure(boxRef, { componentType: 'image', componentName: 'image_with_text', componentTitle: title, componentDescription: subtitle, })
  • 使用 IntersectionObserver 监听组件可见性
  • 曝光数据自动上报,用于分析用户行为
  • 不影响组件性能和用户体验

屏幕阅读器支持

  • alt 属性: 所有 Media 对象必须提供有意义的 alt 文本
  • 图片描述: 避免使用 “image”、“photo” 等通用词,描述图片实际内容
  • 视频描述: alt 应描述视频内容,如 “产品使用演示视频”
  • 功能列表: 图标 alt + 标题 + 描述形成完整的语义

性能优化

React 优化

// 1. 使用 React.forwardRef const ImageWithText = React.forwardRef<HTMLDivElement, ImageWithTextProps>( ({ data, className }, ref) => { // ... } ) // 2. 使用 useRef 避免重复创建 const boxRef = useRef<HTMLDivElement>(null) const desktopVideoRef = useRef<HTMLDivElement>(null) const tabRefs = useRef<Array<HTMLDivElement | null>>([]) // 3. 使用 useEffect 管理副作用 useEffect(() => { // Tab 滑块位置计算 }, [activeIndex, datalist.length]) // 4. 使用 useState 管理视频懒加载状态 const [loadedDesktopVideoSrc, setLoadedDesktopVideoSrc] = useState('')

视频懒加载

// 使用 useIntersectionObserverDelay 监听媒体区域可见性 useIntersectionObserverDelay(mediaWrapperRef, { once: true, // 仅触发一次 threshold: 0.01, // 可见度阈值 1% callback: () => { setVideoIntersected(true) // 标记视频区域已可见 }, }) // 视频区域可见后才加载视频源 useEffect(() => { if (!videoIntersected || !isVideo) return // 加载视频 src setLoadedDesktopVideoSrc(desktopSrc) // 延迟触发播放 setTimeout(() => { videoElement.play() }, 200) }, [videoIntersected, isVideo])

优化效果:

  • 首屏不加载视频,减少初始加载时间
  • 视频可见时才加载,节省带宽
  • 延迟播放确保视频已加载足够数据

图片优化

// 使用 Picture 组件,支持响应式图片 <Picture source={`${image?.url},${padImage?.url || image?.url} 1024, ${mobileImage?.url || image?.url} 768`} alt={image?.alt} className="image-with-text__image" />

响应式图片策略:

  • 桌面端: 显示原始图片
  • 平板端(≤1024px): 显示 padImage 或降级到 image
  • 移动端(≤768px): 显示 mobileImage 或降级到 image

Framer Motion 优化

// 使用 AnimatePresence mode="wait" 确保动画不重叠 <AnimatePresence mode="wait"> <motion.div key={activeTab.video?.url} // 使用唯一 key 强制重新渲染 initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.3 }} // 短动画时长,快速响应 > {/* 内容 */} </motion.div> </AnimatePresence>

优化要点:

  • 使用 mode="wait" 确保退出动画完成后再开始进入动画
  • 动画时长 300ms,快速响应不拖沓
  • 使用唯一 key(video URL)强制组件重新渲染

常见问题

如何决定使用哪种运行模式?

ImageWithText 有三种运行模式,优先级如下:

// 优先级 1: Tab 模式(datalist 存在) datalist.length > 0 → Tab 模式 // 优先级 2: 功能列表模式(items 存在) items.length > 0 && datalist.length === 0 → 功能列表模式 // 优先级 3: 基础模式(无 datalist 和 items) datalist.length === 0 && items.length === 0 → 基础模式

选择建议:

  • 基础模式: 单一产品功能、简单图文介绍
  • 功能列表模式: 需要展示 2-4 个产品特性
  • Tab 模式: 需要在同一区域展示多个相关功能、对比不同产品功能

视频模式下,图片和视频的关系是什么?

// 当 mediaType='video' 时: - image/padImage/mobileImage 作为视频的 poster(封面图) - video/padVideo/mobVideo 是实际播放的视频 URL - 视频加载前显示 poster,加载完成后自动播放 // 优先级: 桌面端: video?.url → image?.url 作为 poster 平板端: padVideo?.url || video?.url → padImage?.url || image?.url 作为 poster 移动端: mobVideo?.url || video?.url → mobileImage?.url || image?.url 作为 poster

最佳实践:

  • 始终提供 poster 图片,提升用户体验
  • poster 图片建议使用视频第一帧或精心设计的封面图
  • 三端视频可以使用不同分辨率,移动端使用压缩版本

移动端布局总是变成上文下图吗?

是的,为了确保移动端良好的用户体验,所有 layout 配置在移动端(<768px)都会强制转换为上文下图:

// 移动端布局统一规则 layout: 'left'Mobile: 上文下图 layout: 'right'Mobile: 上文下图 layout: 'top'Mobile: 上文下图(保持不变) layout: 'bottom'Mobile: 下文上图(保持不变)

原因:

  • 移动端屏幕宽度有限,横向布局会导致图片和文字过于拥挤
  • 上下布局更符合移动端的滚动浏览习惯

如何自定义组件样式?

组件使用完整的 BEM 类名体系,支持深度样式定制:

/* 根元素 */ .image-with-text { } .image-with-text.aiui-dark { } /* 深色主题 */ /* 内容区域 */ .image-with-text__content { } .image-with-text__title { } .image-with-text__subtitle { } .image-with-text__description { } /* 功能列表 */ .image-with-text__items { } .image-with-text__item { } .image-with-text__item-icon { } .image-with-text__item-text { } /* 功能标题(带渐变) */ .image-with-text__item-desc { } /* Tab 模式 */ .image-with-text__tabs-wrapper { } .image-with-text__tabs { } .image-with-text__tab { } .image-with-text__tab--active { } /* 激活状态 */ .image-with-text__slider { } /* 滑块背景 */ /* 按钮 */ .image-with-text__button-wrapper { } .image-with-text__button { } /* 媒体区域 */ .image-with-text__media-wrapper { } .image-with-text__image { } .image-with-text__video { }

示例:

/* 自定义功能图标样式 */ .image-with-text__item-icon { border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 12px; } /* 自定义 Tab 滑块颜色 */ .image-with-text__slider { background: linear-gradient(90deg, #3ad1ff 0%, #008cd6 100%); }

按钮功能如何影响文本区布局?

按钮存在时,文本区的垂直对齐方式会自动改变:

// 无按钮:文本区垂直居中 !hasButton → justify-center // 有按钮:文本区上下分散对齐(space-between) hasButton → justify-between

效果:

  • 无按钮时,文本内容在媒体区旁边垂直居中显示
  • 有按钮时,标题/副标题/功能列表在上方,按钮在下方,充分利用垂直空间

特殊情况:

  • layout: 'top' | 'bottom' 时,laptop 及以上尺寸按钮会显示在标题行右侧
  • 移动端按钮始终显示在文本区底部

padImage/padVideo 不提供时会怎样?

组件使用 fallback 机制,确保所有断点都有图片/视频显示:

// 图片 fallback 逻辑 桌面端: image 平板端: padImage || image // 未提供 padImage 时使用 image 移动端: mobileImage || image // 未提供 mobileImage 时使用 image // 视频 fallback 逻辑 桌面端: video 平板端: padVideo || video // 未提供 padVideo 时使用 video 移动端: mobVideo || video // 未提供 mobVideo 时使用 video

最佳实践:

  • 至少提供 imagemobileImage,确保桌面端和移动端有不同尺寸
  • 如果三端图片完全相同,只提供 image 即可
  • 视频同理,但建议提供 mobVideo,使用压缩版本节省移动端流量

Tab 模式支持多少个 Tab 项?

推荐数量: 2-4 个 Tab 项

原因:

  • 移动端屏幕宽度有限,超过 4 个 Tab 会导致横向滚动
  • Tab 数量过多会分散用户注意力,降低信息传达效率

技术限制:

  • 无硬性上限,理论上可以添加任意数量的 Tab
  • 移动端使用 overflow-x-scroll 支持横向滚动
  • Tab 切换动画依赖 refs 数组,数量过多可能影响性能

建议:

  • 2-3 个 Tab: 最佳,信息清晰,用户易于理解
  • 4 个 Tab: 可接受,但移动端显示会比较紧凑
  • 5 个及以上: 不推荐,考虑拆分为多个组件或使用其他展示方式

技术实现

核心依赖

  • React 18+ - 组件框架
  • Tailwind CSS 3+ - 样式系统
  • Framer Motion - 动画库,用于 Tab 切换动画
  • Heading - 语义化标题组件
  • Text - 文本渲染组件
  • Picture - 响应式图片组件
  • Link - 链接组件

关键技术点

1. 三种运行模式判断

const isTabMode = datalist && datalist.length > 0 const hasItems = items && items.length > 0 const hasButton = !!button // 运行模式优先级: // 1. Tab 模式(datalist 存在) // 2. 功能列表模式(items 存在) // 3. 基础模式

2. 视频懒加载实现

const [videoIntersected, setVideoIntersected] = useState(false) useIntersectionObserverDelay(mediaWrapperRef, { once: true, threshold: 0.01, callback: () => setVideoIntersected(true), }) useEffect(() => { if (!videoIntersected || !isVideo) return setLoadedDesktopVideoSrc(desktopSrc) setTimeout(() => videoElement.play(), 200) }, [videoIntersected, isVideo])

3. Tab 滑块动画

useEffect(() => { if (!tabRefs.current[activeIndex]) return const activeTab = tabRefs.current[activeIndex] const sliderLeft = activeTab.offsetLeft const sliderWidth = activeTab.offsetWidth setSliderStyle({ left: `${sliderLeft}px`, width: `${sliderWidth}px`, }) }, [activeIndex])

4. Framer Motion 内容切换

<AnimatePresence mode="wait"> <motion.div key={activeTab.video?.url} initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.3 }} > {/* 内容 */} </motion.div> </AnimatePresence>

5. 响应式图片源

const getImageSource = () => { const desktop = image?.url const tablet = padImage?.url || desktop const mobile = mobileImage?.url || desktop return `${desktop}, ${tablet} 1024, ${mobile} 768` }

相关资源

组件源码

  • 组件实现: /packages/ui/src/biz-components/ImageWithText/
  • 类型定义: /packages/ui/src/biz-components/ImageWithText/types.ts
  • Stories: /packages/ui/src/stories/imageWithText.stories.tsx

相关组件

  • ImageTextFeature - 图文分栏(带卖点),包含功能项列表和渐变文字
  • FeatureCards - 特性卡片,网格布局展示多个功能
  • HeroBanner - 英雄横幅,带CTA按钮的大型图文展示
  • MediaPlayerBase - 媒体播放器基础组件,支持视频播放控制

外部文档

设计资源

Last updated on