Skip to content

258. 全屏滚动官网(二)

Published:

上节实现了 3D 全屏滚动页面的基本效果:

2025-08-31 20.38.18.gif

这节我们继续完善。

首先,我们可以算出滚动的每一屏:

image.png

window.addEventListener('scroll', () => {
    const pageNo = Math.round(window.scrollY /window.innerHeight);
    console.log(pageNo);
});

这里用 Math.round 来做四舍五入

2025-09-03 14.54.58.gif

用滚动的距离除以每一屏的高度,就可以算出当前是第几屏或者叫第几页。

然后在切换页码的时候做一下标题的动画。

安装 gsap 来做动画:

pnpm install --save gsap

image.png

let curPageNo;
window.addEventListener('scroll', () => {
    const pageNo = Math.round(window.scrollY /window.innerHeight);

    if(pageNo !== curPageNo) {
        curPageNo = pageNo;
        gsap.to('.section' + (pageNo + 1) + ' h1', {
            rotate: '+=360',
            duration: 1
        });
    }
});

如果页数变化了,就让当前页的标题转一圈。

+=360 是在之前角度上加 360 度的意思。

2025-09-03 14.56.56.gif

这样,切换页码时的标题动画就做完了。

然后我们在切换页码的时候,加一下 3D 场景中对应物体的动画:

image.png

gsap.to(mesh.children[pageNo].scale, {
    x: 0.3,
    y: 0.3,
    z: 0.3,
    yoyo: true,
    repeat: 1,
    duration: 0.5,
    ease: 'bounce.in'
})

让对应的物体做一下放缩的动画。

repeat 一次是 0,两次是 1,这里要来回动画,所以是 1

这里的缓动动画函数可以在这里调效果:

https://gsap.com/docs/v3/Eases/

2025-09-03 15.07.37.gif

2025-09-03 15.08.08.gif

试一下:

2025-09-03 15.08.58.gif

现在的交互还是太单调了,只有滚动的交互,我们再加上鼠标交互:

image.png

window.addEventListener('mousemove', (e) => {
    const moveX = (e.clientX / window.innerWidth) - 0.5;

    camera.position.x += moveX * 300 - camera.position.x;
});

监听 mousemove 事件。

e.clientX 拿到鼠标位置距离屏幕左边的距离,除以屏幕宽度,就是 -1 到 1 的值。

因为物体是在中央,所以 -0.5 就是 -0.5 到 0.5 范围的值,也就是距离中央偏离了多少。

然后这个值放大一下减去相机原来的位置,就是偏移量。

看下效果:

2025-09-03 19.05.32.gif

2025-09-03 19.07.24.gif

这样,页面交互就更丰富了。

案例代码上传了小册仓库

总结

这节我们完善了下 3D 全屏滚动网站的交互。

首先,在 scroll 的时候,通过 window.scrollY 和 window.innerHeight 的比值算出当前是第几页。

如果页面切换了,就给标题加一个旋转动画,并且给对应的物体加一个放缩动画。

然后我们又加上了鼠标的交互,mousemove 的时候,根据鼠标移动的距离来移动相机,实现鼠标控制 3D 物体的效果。

当然,我们这里只是学习原理,做的效果比较简单,但复杂的效果也都是基于 scroll、mousemove 来改变 camera 位置实现的。

评论