我使用 Lenis 滚动实现平滑滚动,使用 Barba.js 进行页面转换,它们一起工作,除非在 lenis 仍在处理滚动时触发页面转换。例如,用户向下滚动,点击链接,同时滚动速度逐渐减慢。
该错误意味着新页面加载到与其离开的页面相同的滚动位置,
window.scrollTo();
似乎仅在 Lenis 尚未处理滚动时才起作用。
我尝试在 Barba.js 的
Scroll.stop();
部分中使用 scrollInstance.stop();
或 beforeLeave
来阻止 Lenis,但这会导致初始页面硬重新加载,而不是所需的页面转换。
我已经尝试解决这个问题好几天了,但我对此视而不见,我一定错过了一些明显的东西,所以任何帮助将不胜感激。
这是有错误的代码:
<!--Lenis / Barba Scroll & Animations-->
<script>
const Scroll = {
constructor(options) {
// Create a new Lenis instance
this.lenis = new Lenis({
force: true, // This forces Lenis to scroll even when the cursor is over a WebGL element
...options
});
// Initialize the Scroll class
this.time = 0;
this.isActive = true;
this.init();
},
init() {
// Call the Lenis config method
this.lenis.config();
// Render the scroll
this.render();
// Handle the editor view
this.handleEditorView();
},
render() {
// Call the Lenis raf method
this.lenis.raf(() => {
// Update the time
this.time += 10;
// Render the next frame
window.requestAnimationFrame(this.render.bind(this));
});
},
// ... Other methods ...
config() {
// allow scrolling on overflow elements
const overscroll = [
...document.querySelectorAll('[data-scroll="overscroll"]')
];
if (overscroll.length > 0) {
overscroll.forEach((item) =>
item.setAttribute("onwheel", "event.stopPropagation()")
);
}
// stop and start scroll btns
const stop = [...document.querySelectorAll('[data-scroll="stop"]')];
if (stop.length > 0) {
stop.forEach((item) => {
item.onclick = () => {
this.stop();
this.isActive = false;
};
});
}
const start = [...document.querySelectorAll('[data-scroll="start"]')];
if (start.length > 0) {
start.forEach((item) => {
item.onclick = () => {
this.start();
this.isActive = true;
};
});
}
// toggle page scrolling
const toggle = [...document.querySelectorAll('[data-scroll="toggle"]')];
if (toggle.length > 0) {
toggle.forEach((item) => {
item.onclick = () => {
if (this.isActive) {
this.stop();
this.isActive = false;
} else {
this.start();
this.isActive = true;
}
};
});
}
// anchor links
const anchor = [...document.querySelectorAll("[data-scrolllink]")];
if (anchor.length > 0) {
anchor.forEach((item) => {
const id = parseFloat(item.dataset.scrolllink);
const target = document.querySelector(`[data-scrolltarget="${id}"]`);
if (target) {
//console.log(id, target);
item.onclick = () => this.scrollTo(target);
}
});
}
},
handleEditorView() {
const html = document.documentElement;
const config = { attributes: true, childList: false, subtree: false };
const callback = (mutationList, observer) => {
for (const mutation of mutationList) {
if (mutation.type === "attributes") {
const btn = document.querySelector(".w-editor-bem-EditSiteButton");
const bar = document.querySelector(".w-editor-bem-EditorMainMenu");
const addTrig = (target) =>
target.addEventListener("click", () => this.destroy());
if (btn) addTrig(btn);
if (bar) addTrig(bar);
}
}
};
const observer = new MutationObserver(callback);
observer.observe(html, config);
}
};
// Create a new Scroll instance and assign it to a variable
const scrollInstance = scroll();
// Barba JS
var pageID;
var introOverlay = document.querySelector('.intro-overlay');
barba.init({
transitions: [{
sync: true,
beforeLeave: function(data) {
let end = data.next.html.indexOf(' data-wf-site="');
let start = data.next.html.indexOf('data-wf-page="');
let string = data.next.html.slice(start, end);
let arr = string.split('"');
pageID = arr[1];
const done = this.async();
gsap.to(data.current.container, {
opacity: 0,
duration: 0.5,
onComplete: done,
});
},
leave: function(data) {
const done = this.async();
done();
},
beforeEnter: function(data) {
$('html').attr('data-wf-page', pageID);
window.Webflow && window.Webflow.destroy();
window.Webflow && window.Webflow.ready();
window.Webflow && window.Webflow.require('ix2').init();
window.Webflow && window.Webflow.require('lottie').lottie;
if (introOverlay) {
introOverlay.style.display = 'none';
}
window.scrollTo(0, 1);
window.scrollTo(0, 0);
$("[js-line-animation-delayed]").each(function() {
$(this).removeAttr("js-line-animation-delayed");
$(this).attr("js-line-animation", true);
});
},
afterEnter: function(data) {
setTimeout(() => {
$("[js-line-animation]").each(function(index) {
gsap.set($(this), {
autoAlpha: 1
});
let textEl = $(this);
let textContent = $(this).text();
let tl;
function splitText() {
new SplitType(textEl, {
types: "lines",
tagName: "span"
});
textEl.find(".line").each(function(index) {
let lineContent = $(this).html();
$(this).html("");
$(this).append(`<span class="line-inner" style="display: block;">${lineContent}</span>`);
});
tl = gsap.timeline({
scrollTrigger: {
trigger: textEl,
start: "top bottom",
end: "bottom bottom",
toggleActions: "none play none reset"
}
});
tl.fromTo(textEl.find(".line-inner"), {
yPercent: 100
}, {
yPercent: 0,
duration: 0.6,
stagger: {
amount: 0.4,
ease: "power1.out"
}
});
}
splitText();
let windowWidth = window.innerWidth;
window.addEventListener("resize", function() {
if (windowWidth !== window.innerWidth) {
windowWidth = window.innerWidth;
tl.kill();
textEl.text(textContent);
splitText();
}
});
});
barbaHeroHome();
}, 100);
}
}]
});
</script>
确保页面始终在顶部加载:
// Hook from the Barba.js library that triggers before a page transition completes.
barba.hooks.beforeEnter(() => {
// Start or resume the Lenis smooth scrolling functionality.
lenis.start()
if (lenis) {
// scroll to the top using Lenis immediately (no smooth scrolling).
lenis.scrollTo(0, { immediate: true });
} else {
// If 'lenis' is not defined, fall back to the default browser scroll behavior.
window.scrollTo(0, 0)
}
})
为了防止页面执行硬重新加载,我们需要在链接单击事件发生后立即停止 Lenis 平滑滚动:
// Select all page links
document.querySelectorAll('.barba-link)').forEach(link => {
// Add a 'click' event listener to each link
link.addEventListener('click', (e) => {
// Prevent the default link behavior (stopping the page from navigating away)
e.preventDefault();
// Stop the Lenis smooth scrolling (pauses or halts the scroll animation)
lenis.stop();
});
});