zz-shopify-components
Version:
Reusable Shopify components for theme projects
268 lines (246 loc) • 10.4 kB
JavaScript
class WorldVideo extends HTMLElement {
constructor() {
super();
this.init();
}
init() {
this.initSiteJump();
// 初始化详情按钮
this.initCommentsAction();
this.initVideoAction();
this.initCloseModal();
}
initSiteJump() {
const productLinks = decodeURIComponent(this.dataset.productLinks).replace(
/\+/g,
' '
);
// 去掉productLinks 里面 + 号
this.querySelectorAll('.world-video-learn-more').forEach((item) => {
item.addEventListener('click', (event) => {
const productType =
event.currentTarget.getAttribute('data-product-type');
window.zzAnalytics && window.zzAnalytics.trackEvent('world_video_learn_more', {
timestamp: new Date().toISOString(),
productType: productType,
});
});
bindSiteJump(item, productLinks);
});
}
initVideoAction() {
const video = this.querySelector('.video-player');
const videoPlayBtn = this.querySelector('.video-play-btn');
const playPauseBtn = this.querySelector('.play-pause');
const progressBar = this.querySelector('.progress-bar');
const progressContainer = this.querySelector('.progress-container');
const controlsContainer = this.querySelector('.controls-container');
const volumeBtn = this.querySelector('.volume-btn');
const mbVolumeBtn = this.querySelector('.mb-word-video-volume-btn');
const currentTimeDisplay = this.querySelector('.current-time');
const totalTimeDisplay = this.querySelector('.total-time');
const overlay = this.querySelector('.overlay');
this.video = video;
if (window.innerWidth > 1024) {
// 播放/暂停
playPauseBtn.addEventListener('click', () => {
if (video.paused) {
video.play();
} else {
video.pause();
}
});
} else {
overlay.addEventListener('click', () => {
if (video.paused) {
video.play();
} else {
video.pause();
}
});
videoPlayBtn.addEventListener('click', () => {
video.play();
videoPlayBtn.style.display = 'none';
});
}
// 进度条拖动功能
let isDragging = false;
// 更新进度条
video.addEventListener('timeupdate', () => {
if (isDragging) return;
const progress = (video.currentTime / video.duration) * 100;
progressBar.style.width = `${progress}%`;
currentTimeDisplay.textContent = formatTime(video.currentTime);
});
// 更新视频时间的函数
function updateVideoTime(e) {
const rect = progressContainer.getBoundingClientRect();
const clientX = e.clientX || (e.touches && e.touches[0].clientX);
const pos = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
video.currentTime = pos * video.duration;
progressBar.style.width = `${pos * 100}%`;
}
// 鼠标事件
progressContainer.addEventListener('mousedown', (e) => {
e.stopPropagation();
isDragging = true;
progressContainer.classList.add('dragging');
overlay.classList.add('hidden');
updateVideoTime(e);
});
progressContainer.addEventListener('mousemove', (e) => {
// 阻止冒泡
e.stopPropagation();
if (!isDragging) return;
updateVideoTime(e);
});
document.addEventListener('mouseup', () => {
progressContainer.classList.remove('dragging');
setTimeout(() => {
overlay.classList.remove('hidden');
isDragging = false;
}, 500);
});
// 触摸事件
progressContainer.addEventListener('touchstart', (e) => {
isDragging = true;
progressContainer.classList.add('dragging');
overlay.classList.add('hidden');
updateVideoTime(e);
});
document.addEventListener('touchmove', (e) => {
if (!isDragging) return;
e.preventDefault();
updateVideoTime(e);
});
document.addEventListener('touchend', () => {
progressContainer.classList.remove('dragging');
setTimeout(() => {
overlay.classList.remove('hidden');
isDragging = false;
}, 500);
});
volumeBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (video.muted === false) {
video.muted = true;
} else {
video.muted = false;
}
updateVolumeIcon();
});
mbVolumeBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (video.muted === false) {
video.muted = true;
} else {
video.muted = false;
}
updateVolumeIcon();
});
function updateVolumeIcon() {
let volumeIcon = '';
if (video.muted) {
volumeIcon = `<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.7271 6.92578C13.7191 7.58537 14.3729 8.71327 14.3729 9.99388C14.3729 11.2745 13.7191 12.4024 12.7271 13.062" stroke="white" stroke-width="1.15381" stroke-linecap="round"/>
<path d="M14.7729 4.91113C16.4168 6.00409 17.5001 7.87303 17.5001 9.99501C17.5001 12.117 16.4168 13.9859 14.7729 15.0789" stroke="white" stroke-width="1.15381" stroke-linecap="round"/>
<path d="M3.50098 3.79785L15.8753 16.1722" stroke="white" stroke-width="1.25" stroke-linecap="round"/>
<path d="M10 12.5468V16.4891C9.9997 17.1018 9.25411 17.4031 8.82812 16.9628L5.22754 13.2372H1.93164C1.5553 13.2371 1.25022 12.9319 1.25 12.5555V7.43153C1.25 7.05503 1.55517 6.74997 1.93164 6.74988H4.20312L10 12.5468ZM8.82812 3.0243C9.25423 2.58404 10 2.88606 10 3.49891V10.4257L5.76562 6.19129L8.82812 3.0243Z" fill="white"/>
</svg>
`;
} else {
volumeIcon = `<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.25 7.43155C1.25 7.05501 1.55525 6.74976 1.9318 6.74976H5.2272L8.82779 3.02494C9.25384 2.58419 9.9998 2.8858 9.9998 3.49881V16.4891C9.9998 17.1021 9.25375 17.4037 8.82773 16.9629L5.2272 13.2373H1.9318C1.55525 13.2373 1.25 12.932 1.25 12.5555V7.43155Z" fill="white"/>
<path d="M12.7271 6.92578C13.7191 7.58537 14.3729 8.71327 14.3729 9.99388C14.3729 11.2745 13.7191 12.4024 12.7271 13.062" stroke="white" stroke-width="1.15381" stroke-linecap="round"/>
<path d="M14.7729 4.91016C16.4168 6.00311 17.5001 7.87205 17.5001 9.99403C17.5001 12.116 16.4168 13.9849 14.7729 15.0779" stroke="white" stroke-width="1.15381" stroke-linecap="round"/>
</svg>
`;
}
mbVolumeBtn.innerHTML = volumeIcon;
volumeBtn.innerHTML = volumeIcon;
}
// 格式化时间
function formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
seconds = Math.floor(seconds % 60);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
// 设置总时长
video.addEventListener('loadedmetadata', () => {
totalTimeDisplay.textContent = formatTime(video.duration);
updateVolumeIcon();
});
video.addEventListener('loadeddata', () => {
if (video.duration) {
totalTimeDisplay.textContent = formatTime(video.duration);
}
});
// 播放时添加样式
video.addEventListener('play', () => {
videoPlayBtn.style.display = 'none';
playPauseBtn.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="6.6001" y="5.09961" width="3.6" height="13.8" rx="0.9" fill="white"/>
<rect x="13.7998" y="5.09961" width="3.6" height="13.8" rx="0.9" fill="white"/>
</svg>`;
});
// 暂停时添加样式
video.addEventListener('pause', () => {
if (window.innerWidth < 1024) {
videoPlayBtn.style.display = 'block';
}
playPauseBtn.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.2216 10.4612C20.3819 11.159 20.3819 12.841 19.2216 13.5388L10.2294 18.9463C9.03257 19.666 7.50836 18.804 7.50836 17.4075L7.50836 6.59251C7.50836 5.19597 9.03257 4.33398 10.2294 5.05368L19.2216 10.4612Z" fill="white"/>
</svg>`;
});
// 添加视频错误处理
video.addEventListener('error', (e) => {
console.error('视频加载错误:', e);
if (window.innerWidth < 1024) {
videoPlayBtn.style.display = 'block';
}
playPauseBtn.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.2216 10.4612C20.3819 11.159 20.3819 12.841 19.2216 13.5388L10.2294 18.9463C9.03257 19.666 7.50836 18.804 7.50836 17.4075L7.50836 6.59251C7.50836 5.19597 9.03257 4.33398 10.2294 5.05368L19.2216 10.4612Z" fill="white"/>
</svg>`;
});
// 确保视频加载完成后设置总时长
if (video.readyState >= 2) {
totalTimeDisplay.textContent = formatTime(video.duration);
}
}
initCloseModal() {
const closeBtn = this.querySelector('.mb-close-modal-btn');
closeBtn.addEventListener('click', () => {
document.querySelector('world-video-dialog').closeModal();
});
}
initCommentsAction() {
const commentBtns = this.querySelectorAll('.video-comments-btn');
if (commentBtns) {
commentBtns.forEach((item) => {
item.addEventListener('click', (event) => {
event.stopPropagation();
const id = event.currentTarget.getAttribute('data-id');
const dialog = this.querySelector('world-video-comments-dialog');
if (dialog) {
dialog.showModal(id);
}
window.zzAnalytics && window.zzAnalytics.trackEvent('world-video-comments', {
timestamp: new Date().toISOString(),
});
});
});
}
const likeBtns = this.querySelectorAll('.video-like-btn');
if (likeBtns) {
likeBtns.forEach((item) => {
item.addEventListener('click', (event) => {
event.stopPropagation();
window.zzAnalytics && window.zzAnalytics.trackEvent('world-video-like', {
timestamp: new Date().toISOString(),
});
});
});
}
}
}
customElements.define('world-video', WorldVideo);