This commit is contained in:
浅念
2026-09-02 18:35:45 +08:00
parent 9d9e57d7f4
commit ac58ebb32c
36 changed files with 253 additions and 86 deletions
+59
View File
@@ -366,6 +366,65 @@
}
var wrap = document.querySelector('.map-wrap');
// Paint the page's exact background onto the wrap: same image, stretched
// to .page-content's full size, offset by the wrap's position inside it —
// a pixel-perfect local copy. With .map-wrap { isolation: isolate } the
// blended img mixes against THIS instead of the page backdrop, so Chrome
// never has to capture a cross-element backdrop when the map scrolls into
// view (that capture lags a frame and flashes the map's intrinsic colors).
var pc = document.querySelector('.page-content');
if (wrap && pc) {
var syncBackdrop = function () {
var wr = wrap.getBoundingClientRect();
var pr = pc.getBoundingClientRect();
wrap.style.backgroundImage = 'url(image/home-bgs.png)';
wrap.style.backgroundSize = pr.width + 'px ' + pc.offsetHeight + 'px';
wrap.style.backgroundPosition = (pr.left - wr.left) + 'px ' + (pr.top - wr.top) + 'px';
wrap.style.backgroundRepeat = 'no-repeat';
};
syncBackdrop();
var rT2 = null;
window.addEventListener('resize', function () {
clearTimeout(rT2); rT2 = setTimeout(syncBackdrop, 150);
});
}
// Fade the map image in only after the page has fully loaded: the image
// color-dodges against the (locally copied) page background image, and
// over an unloaded near-white backdrop the map washes out — showing it
// early would flash a colorless map before the glow pops in.
var mapImg = wrap ? wrap.querySelector('.map-bg') : null;
if (mapImg) {
// Reveal needs BOTH: the lazy image decoded (it paints a frame or two
// before its mix-blend-mode composite kicks in) AND the page fully
// loaded (color-dodge over an unloaded white backdrop washes out).
// The fade is JS-driven because CSS animations/transitions lose to the
// !important reveal rule in the cascade — this way the un-blended
// first frames stay at near-zero opacity no matter what.
var imgLoaded = mapImg.complete && mapImg.naturalWidth > 0;
var pageLoaded = document.readyState === 'complete';
var tryReveal = function () {
if (!imgLoaded || !pageLoaded) return;
requestAnimationFrame(function () {
requestAnimationFrame(function () {
var t0 = null;
var step = function (t) {
if (t0 === null) t0 = t;
var p = Math.min((t - t0) / 700, 1);
mapImg.style.opacity = p.toFixed(3);
if (p < 1) requestAnimationFrame(step);
else mapImg.classList.add('ready'); // !important locks the final state
};
requestAnimationFrame(step);
});
});
};
if (!imgLoaded) mapImg.addEventListener('load', function () { imgLoaded = true; tryReveal(); }, { once: true });
if (!pageLoaded) window.addEventListener('load', function () { pageLoaded = true; tryReveal(); }, { once: true });
tryReveal();
}
if ('IntersectionObserver' in window && wrap) {
var mo = new IntersectionObserver(function (entries) {
entries[0].isIntersecting ? start() : stop();