zz-shopify-components
Version:
Reusable Shopify components for theme projects
199 lines (191 loc) • 6.39 kB
JavaScript
class WorldVideoDialog extends HTMLElement {
isInitOpen = true;
swiper = null; // swiper实例
constructor() {
super();
this.init();
}
init() {
this.initData();
document.addEventListener('DOMContentLoaded', () => {
this.initEvent();
});
}
initEvent() {
const closeBtn = this.querySelector('.close-modal-btn');
closeBtn.addEventListener('click', () => {
this.closeModal();
});
}
initData() {
this.x1Img = this.dataset.x1Img;
this.x1ProImg = this.dataset.x1proImg;
this.x121Img = this.dataset.x121Img;
this.x121Links = this.dataset.x121Links;
this.x1Links = this.dataset.x1Links;
this.x1ProLinks = this.dataset.x1proLinks;
}
// 初始化
initSwiper() {
const swiperContainer = this.querySelector('.video-page-swiper');
if (swiperContainer) {
const isDesktop = window.innerWidth >= 1024;
this.swiper = new Swiper(swiperContainer, {
direction: isDesktop ? 'horizontal' : 'vertical',
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
virtual: {
slides: [],
},
slidesPerView: 1,
spaceBetween: 0,
allowTouchMove: isDesktop ? false : true, // 禁用Swiper的触摸/拖动
preventInteractionOnTransition: false,
touchStartPreventDefault: false,
touchMoveStopPropagation: false,
on: {
slideChangeTransitionEnd: () => {
this.handleVideoOnSlideChange();
},
slideChange: () => {
const currentIndex = this.swiper.activeIndex;
if (currentIndex === this.swiper.virtual.slides.length - 1) {
// 滑到最后一条,加载下一页数据
const wordList = document.querySelector('world-video-list');
if (wordList) {
wordList.loadNextPage();
}
}
},
},
});
this.isInitOpen = true;
}
}
handleVideoOnSlideChange() {
// 暂停所有视频
this.parseVideo();
// 播放当前 active slide 中的视频
const activeSlide = this.querySelector('.swiper-slide-active');
const video = activeSlide.querySelector('.word-slide-lazy-video');
if (video) {
video.play().catch((err) => {
console.error('视频播放失败', err);
video.pause();
});
}
}
parseVideo() {
// 暂停所有视频
const allVideos = this.querySelectorAll('.word-slide-lazy-video');
allVideos.forEach((video) => {
video.pause();
});
}
updateSlide(data, productType, isInit = false) {
const template = $('#video-swiper-slide').html();
if (isInit) {
this.destroySwiper();
this.initSwiper();
}
data.forEach((item) => {
let replacedTemplate = template
.replace(new RegExp('{video-url}', 'g'), item.videoUrl)
.replace(new RegExp('{poster-url}', 'g'), item.pictureUrl)
.replace(
new RegExp('{avatar}', 'g'),
item.userInfo && item.userInfo.avatar
)
.replace(
new RegExp('{nickname}', 'g'),
item.userInfo && item.userInfo.nickname
)
.replace(new RegExp('{content}', 'g'), item.content)
.replace(new RegExp('{likeCount}', 'g'), item.likeCount)
.replace(new RegExp('{commentCount}', 'g'), item.commentCount)
.replace(new RegExp('{mediaId}', 'g'), item.id);
if (productType === 1) {
replacedTemplate = replacedTemplate
.replace(new RegExp('{product-links}', 'g'), this.x1Links)
.replace(new RegExp('{product-icon}', 'g'), this.x1Img)
.replace(new RegExp('{product-type}', 'g'), '130');
} else if (productType === 4) {
replacedTemplate = replacedTemplate
.replace(new RegExp('{product-links}', 'g'), this.x1ProLinks)
.replace(new RegExp('{product-icon}', 'g'), this.x1ProImg)
.replace(new RegExp('{product-type}', 'g'), '141');
} else if (productType === 3) {
replacedTemplate = replacedTemplate
.replace(new RegExp('{product-links}', 'g'), this.x121Links)
.replace(new RegExp('{product-icon}', 'g'), this.x121Img)
.replace(new RegExp('{product-type}', 'g'), '121');
}
this.swiper.virtual.slides.push(replacedTemplate);
});
this.swiper.virtual.update();
}
// 销毁
destroySwiper() {
if (this.swiper) {
// 完全销毁swiper,包括所有事件监听器和DOM元素
const swiperWrapper = this.querySelector('.swiper-wrapper');
if (!swiperWrapper) return;
// 找到swiper-wrapper 清空
swiperWrapper.innerHTML = '';
this.swiper.destroy(true, true);
this.swiper = null;
}
}
// 虚拟列表播放视频
playVideo() {
setTimeout(() => {
this.handleVideoOnSlideChange();
}, 200);
}
showModal(videoIndex) {
const modal = this.querySelector('#world-video-modal');
const mask = this.querySelector('#world-video-modalMask');
const body = document.body;
modal.style.display = 'block';
mask.style.display = 'block';
setTimeout(() => {
modal.classList.add('show');
}, 10);
body.classList.add('modal-open');
window.zzLockBodyScroll && window.zzLockBodyScroll();
// 滑到固定位置
if (this.isInitOpen) {
// 是否是初始化后第一次打开
videoIndex && this.swiper.slideTo(videoIndex);
} else {
this.swiper.slideTo(videoIndex);
}
this.isInitOpen = false;
this.playVideo();
window.zzAnalytics && window.zzAnalytics.trackEvent('world_video_dialog_open', {
timestamp: new Date().toISOString(),
});
}
closeModal() {
const modal = this.querySelector('#world-video-modal');
const mask = this.querySelector('#world-video-modalMask');
const body = document.body;
window.zzUnlockBodyScroll && window.zzUnlockBodyScroll();
modal.classList.remove('show');
setTimeout(() => {
modal.style.display = 'none';
mask.style.display = 'none';
this.parseVideo();
}, 200);
body.classList.remove('modal-open');
}
closeTouchMove() {
this.swiper.allowTouchMove = false;
}
openTouchMove() {
this.swiper.allowTouchMove = true;
}
}
customElements.define('world-video-dialog', WorldVideoDialog);