代码说明:
添加缩略图功能:
- 为每个视频项添加缩略图容器
- 支持自定义缩略图或自动生成
- 添加悬停效果和播放图标
布局优化:
- 重新设计了列表项的布局
- 添加了缩略图hover效果
- 优化了文字溢出处理
新增功能:
- 自动生成视频缩略图
- 播放图标动画效果
- 自定义滚动条样式
使用说明:
设置视频和缩略图:
- 将 /path-to-your-video1.mp4 替换为实际视频URL
- 将 /path-to-thumbnail1.jpg 替换为实际缩略图URL
- 如果不提供缩略图,系统会自动从视频中生成
- controlslist=”nodownload”参数为禁用html5播放器下载视频的功能
自定义样式:
- 可以调整缩略图大小(修改 thumbnail-container 的宽高)
- 可以修改播放图标样式
- 可以调整列表项的间距和颜色
响应式设计:
- 在移动设备上自动调整布局
- 缩略图大小会相应调整
性能优化:
- 缩略图懒加载
- 视频时长异步获取
- 平滑过渡动画
- 这个优化版本添加了缩略图预览功能,使界面更加直观和美观,同时保持了良好的性能和用户体验。
页面的HTML代码如下:
在wordpress当中新建页面,然后,切换编辑器为文本模式。
然后,粘入如下代码:
<div class="video-player-wrapper">
<!-- 视频播放器 -->
<div class="video-container">
<video id="mainPlayer" controls controlslist="nodownload">
<source src="/path-to-your-video1.mp4" type="video/mp4">
您的浏览器不支持 HTML5 视频播放
</video>
</div>
<!-- 视频列表 -->
<div class="video-list">
<div class="video-item active" data-src="/path-to-your-video1.mp4" data-poster="/path-to-thumbnail1.jpg">
<div class="thumbnail-container">
<img src="/path-to-thumbnail1.jpg" alt="视频缩略图">
<div class="play-icon">▶</div>
</div>
<div class="video-info">
<div class="video-title">视频标题 1</div>
<div class="video-duration"></div>
</div>
</div>
<div class="video-item" data-src="/path-to-your-video2.mp4" data-poster="/path-to-thumbnail2.jpg">
<div class="thumbnail-container">
<img src="/path-to-thumbnail2.jpg" alt="视频缩略图">
<div class="play-icon">▶</div>
</div>
<div class="video-info">
<div class="video-title">视频标题 2</div>
<div class="video-duration"></div>
</div>
</div>
<div class="video-item" data-src="/path-to-your-video3.mp4" data-poster="/path-to-thumbnail3.jpg">
<div class="thumbnail-container">
<img src="/path-to-thumbnail3.jpg" alt="视频缩略图">
<div class="play-icon">▶</div>
</div>
<div class="video-info">
<div class="video-title">视频标题 3</div>
<div class="video-duration"></div>
</div>
</div>
</div>
</div>
<style>
.video-player-wrapper {
max-width: 1200px;
margin: 20px auto;
display: flex;
gap: 20px;
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.video-container {
flex: 2;
}
.video-container video {
width: 100%;
height: auto;
border-radius: 4px;
}
.video-list {
flex: 1;
max-height: 400px;
overflow-y: auto;
background: #f5f5f5;
border-radius: 4px;
padding: 10px;
}
.video-item {
padding: 10px;
margin-bottom: 8px;
background: white;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 10px;
}
.video-item:hover {
background: #e9ecef;
}
.video-item.active {
background: #007bff;
color: white;
}
.thumbnail-container {
position: relative;
width: 120px;
height: 67.5px; /* 16:9 比例 */
flex-shrink: 0;
overflow: hidden;
border-radius: 4px;
}
.thumbnail-container img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.7);
color: white;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.video-item:hover .play-icon {
opacity: 1;
}
.video-item:hover img {
transform: scale(1.1);
}
.video-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
min-width: 0; /* 防止文本溢出 */
}
.video-title {
font-weight: 500;
margin-bottom: 5px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.video-duration {
font-size: 0.8em;
color: #666;
padding: 2px 6px;
background: #f0f0f0;
border-radius: 3px;
display: inline-block;
}
.video-item.active .video-duration {
color: #007bff;
background: rgba(255, 255, 255, 0.9);
}
/* 自定义滚动条样式 */
.video-list::-webkit-scrollbar {
width: 6px;
}
.video-list::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.video-list::-webkit-scrollbar-thumb {
background: #888;
border-radius: 3px;
}
.video-list::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* 响应式布局 */
@media (max-width: 768px) {
.video-player-wrapper {
flex-direction: column;
}
.video-list {
max-height: 300px;
}
.thumbnail-container {
width: 100px;
height: 56.25px;
}
}
</style>
JS部分代码:
请粘到当前主题的Page.php文件的</head>标签后面
代码如下:
<script>
document.addEventListener('DOMContentLoaded', function() {
const mainPlayer = document.getElementById('mainPlayer');
const videoItems = document.querySelectorAll('.video-item');
// 格式化时间函数
function formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
seconds = Math.floor(seconds % 60);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
// 获取视频时长
async function getVideoDuration(videoSrc) {
return new Promise((resolve) => {
const tempVideo = document.createElement('video');
tempVideo.src = videoSrc;
tempVideo.addEventListener('loadedmetadata', function() {
resolve(formatTime(tempVideo.duration));
});
tempVideo.addEventListener('error', function() {
resolve('--:--');
});
});
}
// 生成视频缩略图
async function generateThumbnail(videoSrc) {
return new Promise((resolve) => {
const video = document.createElement('video');
video.src = videoSrc;
video.addEventListener('loadeddata', function() {
video.currentTime = 1; // 跳转到第1秒
});
video.addEventListener('seeked', function() {
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
resolve(canvas.toDataURL());
});
video.addEventListener('error', function() {
resolve(null);
});
});
}
// 初始化视频时长和缩略图
async function initializeVideos() {
for (const item of videoItems) {
const videoSrc = item.getAttribute('data-src');
const durationElement = item.querySelector('.video-duration');
const thumbnailImg = item.querySelector('img');
durationElement.textContent = 'Loading...';
try {
// 获取时长
const duration = await getVideoDuration(videoSrc);
durationElement.textContent = duration;
// 如果没有设置缩略图,则自动生成
if (!thumbnailImg.src || thumbnailImg.src.includes('path-to-thumbnail')) {
const thumbnail = await generateThumbnail(videoSrc);
if (thumbnail) {
thumbnailImg.src = thumbnail;
}
}
} catch (error) {
durationElement.textContent = '--:--';
}
}
}
// 调用初始化函数
initializeVideos();
videoItems.forEach(item => {
item.addEventListener('click', function() {
videoItems.forEach(i => i.classList.remove('active'));
this.classList.add('active');
const videoSrc = this.getAttribute('data-src');
const posterSrc = this.getAttribute('data-poster');
mainPlayer.src = videoSrc;
if (posterSrc) {
mainPlayer.poster = posterSrc;
}
mainPlayer.load();
mainPlayer.play();
});
});
// 视频播放结束时自动播放下一个
mainPlayer.addEventListener('ended', function() {
const currentVideo = document.querySelector('.video-item.active');
const nextVideo = currentVideo.nextElementSibling;
if (nextVideo) {
nextVideo.click();
} else {
videoItems[0].click();
}
});
// 当前播放视频的时间更新
mainPlayer.addEventListener('timeupdate', function() {
const currentTime = formatTime(mainPlayer.currentTime);
const totalTime = formatTime(mainPlayer.duration);
const activeItem = document.querySelector('.video-item.active');
if (activeItem) {
const durationElement = activeItem.querySelector('.video-duration');
durationElement.textContent = `${currentTime} / ${totalTime}`;
}
});
});
</script>
最终效果如下图所示:
是不是很简单?!
补充说明:
数据还是需要你手动填充的!
评论抢沙发