数据
图片部分与标题部分封装出去
判断图片状态设置index值以便可以滑动切换不同视频内容
渲染视频上去
鼠标移入视频播放 移出暂停
import React, { useRef, useCallback } from 'react';
// 定义视频画廊的属性接口
interface VideoGalleryProps {
videos: string[]; // 视频源数组
}
// 创建视频画廊组件
const VideoGallery: React.FC<VideoGalleryProps> = ({ videos }) => {
// 创建引用,分别用于主视频和其他视频
const mainVideoRef = useRef<HTMLVideoElement | null>(null);
const videoRefs = useRef<(HTMLVideoElement | null)[]>([]);
// 鼠标悬停处理函数,播放视频
const handleMouseEnter = useCallback((index: number) => {
if (videoRefs.current[index]) {
videoRefs.current[index]?.play(); // 播放当前视频
}
if (index === 0 && mainVideoRef.current) {
mainVideoRef.current.play(); // 播放主视频
}
}, []);
// 鼠标离开处理函数,暂停视频
const handleMouseLeave = useCallback((index: number) => {
if (videoRefs.current[index]) {
videoRefs.current[index]?.pause(); // 暂停当前视频
}
if (index === 0 && mainVideoRef.current) {
mainVideoRef.current.pause(); // 暂停主视频
}
}, []);
return (
<div className='focus_bottom_shi'> {/* 整个视频画廊容器 */}
<div className='img_left'> {/* 主视频区域 */}
<video
controls // 启用控制条
ref={mainVideoRef} // 设置引用
onMouseEnter={() => handleMouseEnter(0)} // 鼠标悬停时播放
onMouseLeave={() => handleMouseLeave(0)} // 鼠标离开时暂停
>
<source src={videos[0]} type="video/mp4" /> {/* 主视频源 */}
</video>
</div>
<div className='img_right'> {/* 其他视频区域 */}
{videos.slice(1).map((src, index) => ( // 从第二个视频开始遍历
<div
key={index} // 唯一键值
onMouseEnter={() => handleMouseEnter(index + 1)} // 鼠标悬停时播放
onMouseLeave={() => handleMouseLeave(index + 1)} // 鼠标离开时暂停
>
<video
ref={el => videoRefs.current[index + 1] = el} // 设置引用
width="150" // 设置视频宽度
muted // 静音
>
<source src={src} type="video/mp4" key={index}/> {/* 视频源 */}
</video>
</div>
))}
</div>
</div>
);
};
// 导出组件
export default VideoGallery;
标题部分代码
import React from 'react';
// 定义接口,描述组件的属性类型
interface SectionListProps {
sections: string[]; // 字符串数组,表示所有章节的名称
activeSection: string; // 当前活动章节的名称
onSectionMouseEnter: (section: string) => void; // 鼠标进入章节时的回调函数
}
// 定义SectionList组件,接收SectionListProps类型的属性
const SectionList: React.FC<SectionListProps> = ({ sections, activeSection, onSectionMouseEnter }) => (
<ul> {/* 无序列表容器 */}
{sections.map((section) => ( // 遍历所有章节
<li
key={section} // 使用章节名称作为唯一键
className={`section ${activeSection === section ? 'active' : ''}`} // 根据activeSection决定是否添加active类
onMouseEnter={() => onSectionMouseEnter(section)} // 鼠标进入时调用回调函数
>
{section} {/* 显示章节名称 */}
</li>
))}
</ul>
);
export default SectionList;
如果是图片渲染标签就是图片