ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Lenis 平滑滚动完整指南:从 3 行代码到调优实战

Lenis 平滑滚动完整指南:从 3 行代码到调优实战 Lenis 平滑滚动完整指南从 3 行代码到调优实战【免费下载链接】lenisSmooth scroll as it should be项目地址: https://gitcode.com/GitHub_Trending/le/lenis做 WebGL 交互或者 GSAP 视差动画的朋友大概率遇到过这个场景原生滚动是浏览器抢着管理的你的动画脚本想读取一个连续的、可控的滚动值却发现它和页面真实位置不同步视差效果一快就穿帮。Lenis 就是为这类问题而生的轻量级平滑滚动库——它接管滚动手感把滚动变成一个可预测、可驱动的数值流。库名 Lenis 在拉丁语里就是平滑的意思。先认识一下 LenisLenis 由 darkroom.engineering 开发定位是小而全的滚动内核体积很小、零运行时依赖整个库只有几 KB官方 README 表述为 a few KB基于原生滚动它包裹浏览器的真实滚动而不是伪造一个所以position: sticky、锚点链接、无障碍能力照常工作任意方向垂直、水平、嵌套容器同一个 API为同步而生一个 rAF 循环同时驱动 WebGL 场景、GSAP ScrollTrigger 和视差效果官方适配器React、Vue、Framer 各有一等公民包配套插件lenis/snap补上 CSS scroll-snap 的能力适合落地页、作品集、3D 滚动叙事、需要滚动与动画精确联动的页面。 不适合对像素级还原原生滚动行为有洁癖的场景——平滑滚动本质上是浏览器先到、你的动画跟拍理解了这个前提就不会失望。三步跑通安装到看到丝滑效果先安装包名是lenis不是旧文章里常见的studio-freight/lenisnpm i lenis然后是官方推荐的最短启动方式开了autoRaf就不用自己写动画循环import Lenis from lenis import lenis/dist/lenis.css // 官方推荐样式务必引入 const lenis new Lenis({ autoRaf: true }) // 每个滚动帧都会触发回调参数就是 Lenis 实例本身 lenis.on(scroll, (lenis) { console.log(lenis.scroll, lenis.velocity, lenis.progress) })如果你要把 Lenis 挂到别的时间轴上GSAP、Framer Motion 都是这么干的就关掉autoRaf自己每帧调用raf(time)时间单位是毫秒const lenis new Lenis() function raf(time) { lenis.raf(time) // 每帧推进一次内部动画 requestAnimationFrame(raf) } requestAnimationFrame(raf)推荐样式文件里做了几件关键事恢复html高度、平滑滚动时对 iframe 关闭pointer-events、给data-lenis-prevent元素加overscroll-behavior: contain。跳过这一步是很多不生效问题的根源。不想写代码也能用HTML 里直接挂脚本标签并传{ autoRaf: true, autoToggle: true, anchors: true, allowNestedScroll: true, stopInertiaOnNavigate: true }官方称之为 no-code 用法能顺带处理好锚点、嵌套滚动和页面切换时的惯性重置。原理拆解一个目标值、一条追赶曲线Lenis 的核心不复杂源码里有一句话式的注释值得先读packages/core/src/lenis.ts监听 wheel → 阻止默认滚动 → 归一化 delta → 累加到 targetScroll → 把真实滚动动画地推向 targetScroll它维护着两个关键数值targetScroll用户想要的位置滚轮、触摸累加出来的目标animatedScroll当前正在呈现的位置最终通过wrapper.scrollTo(..., { behavior: instant })写回浏览器两者之间的追赶由 Animate 类 完成支持两种模式// animate.ts 的核心分支 if (this.duration this.easing) { // 时间驱动按 easing 曲线在固定时长内走完 this.value this.from (this.to - this.from) * easedProgress } else if (this.lerp) { // 插值驱动指数阻尼帧率无关 this.value damp(this.value, this.to, this.lerp * 60, deltaTime) // damp lerp(x, y, 1 - Math.exp(-lambda * dt)) }默认走 lerp 模式lerp: 0.1用1 - e^(-λ·dt)做阻尼——这意味着 60Hz 和 144Hz 的屏幕上手感一致不会因为帧率高就追得更快。而 wheel/touch 事件先经过 VirtualScroll 归一化不同设备的deltaMode像素/行/页面被统一换算再乘以wheelMultiplier/touchMultiplier这就是手感可调的入口。滚动状态也会以类名的形式暴露给 CSSlenis-scrolling、lenis-smooth、lenis-stopped方便你在样式层做联动。配置项全表哪些参数决定手感以下默认值均来自 官方 README 的 Settings 一节参数类型 / 默认值对手感/行为的影响lerpnumber /0.1默认模式。越大追赶越快手感越贴手越小越拖尾durationnumber /1.2时间驱动模式的总时长秒需与easing搭配easingfunction / 内置指数衰减决定收尾曲线只给 easing 不给 duration 时时长按 1s 处理smoothWheelboolean /true滚轮是否走平滑关掉则滚轮为原生滚动syncTouchboolean /false让触摸也模拟轮式平滑惯性iOS 16 以下可能不稳定syncTouchLerpnumber /0.075触摸惯性阶段的插值强度touchInertiaExponentnumber /1.7抬手后惯性甩动的衰减强度wheelMultipliernumber /1滚轮灵敏度整体放大/缩小输入touchMultipliernumber /1触摸灵敏度同上overscrollboolean /true类似 CSSoverscroll-behavior控制到顶/底后是否再触发浏览器回弹anchorsboolean /false默认平滑滚动会拦截锚点开启后点锚点走scrollToinfiniteboolean /false无限滚动scroll属性在 limit 内取模循环orientationstring /verticalvertical或horizontalallowNestedScrollboolean /false自动放行嵌套滚动容器但每帧查 DOM 有性能开销autoRafboolean /false是否内置 rAF 循环autoToggleboolean /false根据容器 overflow 自动启停需配合推荐 CSSstopInertiaOnNavigateboolean /false点击站内链接时立即停止惯性避免翻页后还在滑常用方法与属性也值得记住scrollTo(target, options)目标可以是数字px、CSS 选择器、关键词top/bottom/start/end或 DOM 元素options支持offset、immediate瞬移、lock到达前禁止用户滚动、onComplete、userData等stop()/start()/destroy()暂停常见于打开弹窗时、恢复、销毁事件scroll参数是 Lenis 实例可顺手读progress、velocity、direction和virtual-scroll参数{deltaX, deltaY, event}可在此拦截输入实战组合动画库与框架GSAP ScrollTrigger官方给定的四行配方const lenis new Lenis() lenis.on(scroll, ScrollTrigger.update) // 滚动变化时通知 ScrollTrigger gsap.ticker.add((time) { lenis.raf(time * 1000) // GSAP 时间轴是秒换算成毫秒 }) gsap.ticker.lagSmoothing(0) // 关闭 GSAP 滞后补偿避免双重平滑让 GSAP 的 ticker 当唯一时钟Lenis 的插值和 ScrollTrigger 的 scrub 就共享同一帧快速滚动时也不会掉帧错位。React / Vue官方适配器React 侧用ReactLenis root /创建全局实例任意组件通过useLenis拿到它并注册每帧回调packages/react/import { ReactLenis, useLenis } from lenis/react function App() { useLenis((lenis) { // 每个滚动帧执行可做视差、进度条等 document.querySelector(.hero).style.transform translateY(${lenis.scroll * 0.2}px) }) return ReactLenis root{/* 页面内容 */}/ReactLenis }Vue 侧对应VueLenis root和vueLenisPlugin用法同构同样只在客户端环境初始化实例天然规避 SSR 时触碰window的问题。Framer Motion 的接法是frame.update((data) lenis.raf(data.timestamp), true)。lenis/snap平滑滚动 分节吸附原生 scroll-snap 在平滑滚动下会打架官方给了 snap 插件 作为替代import Lenis from lenis import Snap from lenis/snap const lenis new Lenis({ autoRaf: true }) const snap new Snap(lenis) snap.addElement(document.querySelector(.intro), { align: start, // 对齐方式start / center / end }) snap.add(1200) // 也可以直接吸附到某个 px 值 // 翻页式交互type 传 lock 时更像幻灯片支持proximity/mandatory/lock三种模式还有next()、previous()、goTo(index)供按钮调用。踩坑与排障官方列过的边界这些限制官方在 Limitations 一节里写得明明白白动手前先看Safari 上限 60fps低电量模式只有 30fps——高刷屏上别指望 120fps 的滚动iframe 内不生效iframe 不转发 wheel 事件推荐 CSS 会对.lenis-smooth iframe设pointer-events: nonemacOS SafariM1 之前position: fixed有滞后的已知问题syncTouch在 iOS 16 以下可能异常开发中高频的四个坑及解法完全不滚十有八九是漏了推荐 CSS或既没开autoRaf也没手动调lenis.raf(time)先摘掉 Lenis 确认页面本身可滚嵌套滚动容器弹窗、侧栏抢滚动轻量的做法是给容器加data-lenis-prevent属性还有-wheel、-touch、-vertical、-horizontal细分变体allowNestedScroll: true是自动方案但每次滚动都查 DOM性能敏感页面优先用属性锚点失效平滑滚动默认拦截锚点传anchors: true即可还能给offset和onComplete翻页后还在滑单页应用路由切换时加stopInertiaOnNavigate: true或自己lenis.reset()/destroy()清理入口与延伸一句话总结Lenis 用几 KB 的代码把滚动从一个不可控的浏览器行为变成了一个每帧可读、可驱动、可调手的数值流——这是它能同时服务普通官网和 3D 叙事页面的原因。完整 API 与选项说明README.md核心实现Lenis 主类、Animate、VirtualScrollpackages/core/src/各框架适配器packages/react/、packages/vue/分节吸附插件packages/snap/设计动机为什么它最初是为 WebGL 同步而生的MANIFESTO.md项目为 MIT 协议社区里还有 r3f-scroll-rig、locomotive-scroll 等基于 Lenis 的第三方插件可以直接选用。【免费下载链接】lenisSmooth scroll as it should be项目地址: https://gitcode.com/GitHub_Trending/le/lenis创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表