256 lines
7.7 KiB
JavaScript
256 lines
7.7 KiB
JavaScript
(function () {
|
||
var H5_MQ = "(max-width: 767px)";
|
||
var isH5 = !!(window.matchMedia && window.matchMedia(H5_MQ).matches);
|
||
|
||
var announcementTrack = document.querySelector(".home-announcement-marquee");
|
||
if (announcementTrack) {
|
||
var announcementCopies = announcementTrack.querySelectorAll(".home-announcement-copy");
|
||
var announcementViewport = announcementTrack.parentElement;
|
||
if (announcementCopies.length === 2 && announcementViewport) {
|
||
var primaryAnnouncement = announcementCopies[0];
|
||
var duplicateAnnouncement = announcementCopies[1];
|
||
var announcementSourceNodes = Array.prototype.map.call(
|
||
primaryAnnouncement.childNodes,
|
||
function (node) {
|
||
return node.cloneNode(true);
|
||
}
|
||
);
|
||
|
||
function fillAnnouncementTrack() {
|
||
var rounds = 0;
|
||
while (
|
||
primaryAnnouncement.getBoundingClientRect().width <
|
||
announcementViewport.clientWidth + 80 &&
|
||
rounds < 20
|
||
) {
|
||
var repeated = document.createElement("span");
|
||
repeated.setAttribute("aria-hidden", "true");
|
||
repeated.className = "home-announcement-repeat";
|
||
|
||
var separator = document.createElement("span");
|
||
separator.className = "home-announcement-separator";
|
||
separator.textContent = " · ";
|
||
repeated.appendChild(separator);
|
||
|
||
announcementSourceNodes.forEach(function (node) {
|
||
repeated.appendChild(node.cloneNode(true));
|
||
});
|
||
primaryAnnouncement.appendChild(repeated);
|
||
rounds += 1;
|
||
}
|
||
duplicateAnnouncement.innerHTML = primaryAnnouncement.innerHTML;
|
||
}
|
||
|
||
window.requestAnimationFrame(fillAnnouncementTrack);
|
||
if ("ResizeObserver" in window) {
|
||
new ResizeObserver(fillAnnouncementTrack).observe(announcementViewport);
|
||
}
|
||
}
|
||
}
|
||
|
||
// H5:首屏只抢 LCP 主图,海报交给 IntersectionObserver,避免弱网争抢带宽
|
||
if (isH5) {
|
||
document.querySelectorAll(".poster-cover-img[data-lazy-eager]").forEach(function (img) {
|
||
img.removeAttribute("data-lazy-eager");
|
||
});
|
||
}
|
||
|
||
function loadHeroSlideImages(slide) {
|
||
if (!slide || typeof loadLazyNode !== "function") return;
|
||
var imgs = slide.querySelectorAll(".hero-image.lazy[data-src]:not([data-decrypted])");
|
||
Array.prototype.forEach.call(imgs, function (img) {
|
||
loadLazyNode(img);
|
||
});
|
||
}
|
||
|
||
var firstHeroImg = document.querySelector(
|
||
".hero-card .hero-image.lazy[data-src]:not([data-decrypted])"
|
||
);
|
||
if (firstHeroImg && typeof loadLazyNode === "function") {
|
||
loadLazyNode(firstHeroImg);
|
||
} else if (firstHeroImg && typeof processImage === "function") {
|
||
var src = firstHeroImg.getAttribute("data-src");
|
||
if (src) {
|
||
firstHeroImg.setAttribute("data-decrypted", "1");
|
||
processImage(src, firstHeroImg);
|
||
}
|
||
}
|
||
|
||
var mainEl = document.getElementById("heroSwiper");
|
||
var thumbsEl = document.getElementById("heroThumbs");
|
||
if (!mainEl) return;
|
||
|
||
var slideCount = mainEl.querySelectorAll(".swiper-slide").length;
|
||
if (slideCount === 0) return;
|
||
|
||
var swiperStarted = false;
|
||
|
||
function loadScript(src) {
|
||
return new Promise(function (resolve, reject) {
|
||
if (typeof Swiper !== "undefined") {
|
||
resolve();
|
||
return;
|
||
}
|
||
var existing = document.querySelector('script[src="' + src + '"]');
|
||
if (existing) {
|
||
existing.addEventListener("load", function () {
|
||
resolve();
|
||
});
|
||
existing.addEventListener("error", reject);
|
||
return;
|
||
}
|
||
var s = document.createElement("script");
|
||
s.src = src;
|
||
s.async = true;
|
||
s.onload = function () {
|
||
resolve();
|
||
};
|
||
s.onerror = reject;
|
||
document.head.appendChild(s);
|
||
});
|
||
}
|
||
|
||
function loadStylesheet(href) {
|
||
return new Promise(function (resolve) {
|
||
if (document.querySelector('link[href="' + href + '"][data-swiper-css]')) {
|
||
resolve();
|
||
return;
|
||
}
|
||
var link = document.createElement("link");
|
||
link.rel = "stylesheet";
|
||
link.href = href;
|
||
link.setAttribute("data-swiper-css", "1");
|
||
link.onload = function () {
|
||
resolve();
|
||
};
|
||
link.onerror = function () {
|
||
resolve();
|
||
};
|
||
document.head.appendChild(link);
|
||
});
|
||
}
|
||
|
||
function ensureSwiperAssets() {
|
||
var cssHref = "/static/common/swiper-bundle.min.css";
|
||
var jsHref = "/static/common/swiper-bundle.min.js";
|
||
// PC 已通过 media=(min-width:768px) 预加载 CSS;H5 在此按需注入
|
||
var tasks = [loadScript(jsHref)];
|
||
if (isH5) {
|
||
tasks.unshift(loadStylesheet(cssHref));
|
||
}
|
||
return Promise.all(tasks);
|
||
}
|
||
|
||
function initSwiper() {
|
||
if (swiperStarted || typeof Swiper === "undefined") return;
|
||
swiperStarted = true;
|
||
mainEl.classList.remove("hero-swiper--h5-pending");
|
||
|
||
var thumbButtons = thumbsEl
|
||
? Array.prototype.slice.call(thumbsEl.querySelectorAll(".hero-thumb"))
|
||
: [];
|
||
|
||
function setActiveThumb(index) {
|
||
thumbButtons.forEach(function (btn, i) {
|
||
btn.classList.toggle("is-active", i === index);
|
||
});
|
||
}
|
||
|
||
var enableLoop = slideCount > 1;
|
||
|
||
var mainSwiper = new Swiper(mainEl, {
|
||
loop: enableLoop,
|
||
effect: "fade",
|
||
fadeEffect: {
|
||
crossFade: true,
|
||
},
|
||
speed: isH5 ? 650 : 900,
|
||
autoplay: enableLoop
|
||
? {
|
||
delay: 3000,
|
||
disableOnInteraction: false,
|
||
pauseOnMouseEnter: !isH5,
|
||
waitForTransition: true,
|
||
}
|
||
: false,
|
||
pagination: {
|
||
el: mainEl.querySelector(".hero-dots"),
|
||
clickable: true,
|
||
bulletClass: "hero-dot",
|
||
bulletActiveClass: "hero-dot--active",
|
||
},
|
||
on: {
|
||
init: function () {
|
||
loadHeroSlideImages(this.slides[this.activeIndex]);
|
||
},
|
||
slideChange: function () {
|
||
setActiveThumb(this.realIndex);
|
||
loadHeroSlideImages(this.slides[this.activeIndex]);
|
||
if (isH5) return;
|
||
var next = this.slides[this.activeIndex + 1];
|
||
var prev = this.slides[this.activeIndex - 1];
|
||
if (next) loadHeroSlideImages(next);
|
||
if (prev) loadHeroSlideImages(prev);
|
||
},
|
||
},
|
||
});
|
||
|
||
var previousButton = mainEl.querySelector(".hero-thumb-prev");
|
||
var nextButton = mainEl.querySelector(".hero-thumb-next");
|
||
if (previousButton) {
|
||
previousButton.addEventListener("click", function () {
|
||
mainSwiper.slidePrev();
|
||
});
|
||
}
|
||
if (nextButton) {
|
||
nextButton.addEventListener("click", function () {
|
||
mainSwiper.slideNext();
|
||
});
|
||
}
|
||
|
||
thumbButtons.forEach(function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
var index = Number(btn.getAttribute("data-index"));
|
||
if (Number.isNaN(index)) return;
|
||
if (enableLoop) {
|
||
mainSwiper.slideToLoop(index);
|
||
} else {
|
||
mainSwiper.slideTo(index);
|
||
}
|
||
setActiveThumb(index);
|
||
});
|
||
});
|
||
}
|
||
|
||
function startSwiper() {
|
||
if (swiperStarted) return;
|
||
ensureSwiperAssets()
|
||
.then(initSwiper)
|
||
.catch(function () {
|
||
mainEl.classList.remove("hero-swiper--h5-pending");
|
||
});
|
||
}
|
||
|
||
if (isH5) {
|
||
mainEl.classList.add("hero-swiper--h5-pending");
|
||
|
||
function scheduleSwiper() {
|
||
startSwiper();
|
||
}
|
||
|
||
// 用户滑动/点击 banner 时立即初始化;否则空闲后再加载,避开 LCP 争抢
|
||
mainEl.addEventListener("touchstart", scheduleSwiper, { once: true, passive: true });
|
||
mainEl.addEventListener("click", scheduleSwiper, { once: true });
|
||
|
||
if ("requestIdleCallback" in window) {
|
||
requestIdleCallback(scheduleSwiper, { timeout: 3500 });
|
||
} else {
|
||
setTimeout(scheduleSwiper, 2200);
|
||
}
|
||
return;
|
||
}
|
||
|
||
// PC:立即加载并初始化 Swiper
|
||
startSwiper();
|
||
})();
|