miniwhite's picture
视频封面整个区域都可以进行点击播放,视频列表中视频详情有点赞功能
60a46cc verified
class CustomVideoCard extends HTMLElement {
connectedCallback() {
const videoId = this.getAttribute('video-id');
const title = this.getAttribute('title');
const thumbnail = this.getAttribute('thumbnail');
const videoUrl = this.getAttribute('video-url');
const likes = this.getAttribute('likes');
const orientation = this.getAttribute('orientation');
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
.video-card {
background: white;
border-radius: 0.5rem;
overflow: hidden;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: transform 0.2s ease, box-shadow 0.2s ease;
cursor: pointer;
}
.video-card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
z-index: 10;
}
.video-thumbnail {
position: relative;
padding-bottom: ${orientation === 'portrait' ? '177.78%' : '56.25%'};
height: 0;
overflow: hidden;
border-radius: 0.5rem 0.5rem 0 0;
}
.video-thumbnail img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.play-button {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(255, 255, 255, 0.8);
border-radius: 50%;
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.video-info {
padding: 1rem;
}
.video-title {
font-weight: 600;
margin-bottom: 0.5rem;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.video-stats {
display: flex;
align-items: center;
color: #6b7280;
font-size: 0.875rem;
cursor: pointer;
transition: color 0.2s;
pointer-events: auto;
}
.video-stats:hover {
color: #ef4444;
}
.video-stats i {
transition: all 0.2s;
}
.video-stats[data-liked] i,
.video-stats.liked i {
color: #ef4444;
fill: #ef4444;
}
</style>
<div class="video-card">
<div class="video-thumbnail">
<img src="${thumbnail}" alt="${title}">
<div class="play-button" id="play-button">
<i data-feather="play" class="text-purple-600"></i>
</div>
</div>
<div class="video-info">
<h3 class="video-title">${title}</h3>
<div class="video-stats">
<i data-feather="heart" class="w-4 h-4 mr-1"></i>
<span>${likes}</span>
</div>
</div>
</div>
<script>
feather.replace();
</script>
`;
const videoCard = this.shadowRoot.querySelector('.video-card');
videoCard.addEventListener('click', (e) => {
// Don't trigger if clicking on like button
if (!e.target.closest('.video-stats')) {
const videoPlayer = document.querySelector('custom-video-player');
if (videoPlayer) {
videoPlayer.playVideo(videoUrl, parseInt(likes));
}
}
});
// Handle like button click
const likeButton = this.shadowRoot.querySelector('.video-stats');
likeButton.addEventListener('click', (e) => {
e.stopPropagation();
let currentLikes = parseInt(likes);
const isLiked = likeButton.hasAttribute('data-liked');
if (isLiked) {
likeButton.removeAttribute('data-liked');
currentLikes--;
likeButton.querySelector('i').classList.remove('liked');
} else {
likeButton.setAttribute('data-liked', '');
currentLikes++;
likeButton.querySelector('i').classList.add('liked');
}
likes = currentLikes.toString();
likeButton.querySelector('span').textContent = currentLikes.toLocaleString();
});
}
}
customElements.define('custom-video-card', CustomVideoCard);