lenis-smooth-scroll
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSkill: lenis-smooth-scroll
Skill: lenis-smooth-scroll
Thiết lập Lenis làm nền cuộn vật lý (physics-based) cho toàn trang, và đồng bộ đúng cách với GSAP ScrollTrigger — đây là bước hay bị làm sai nhất khi ráp 2 thư viện này chung.
将 Lenis 设置为全页面基于物理(physics-based)的滚动基础,并以正确方式与 GSAP ScrollTrigger 同步——集成这两个库时,这是最容易做错的一步。
WHAT
WHAT
Purpose và context
目的与上下文
- Purpose: dựng Lenis làm nền cuộn vật lý cho TOÀN TRANG và đồng bộ đúng với GSAP ScrollTrigger (một driver raf, không lệch pha, không giật khi quay lại tab), mặc định bằng bản gốc nguyên văn ở .
Rheinmir/uiux-asset - Trigger (when to use):
- Trang cần cảm giác cuộn "nặng tay/mượt" kiểu Apple/awwwards thay vì cuộn giật cứng mặc định của trình duyệt.
- Trang đã hoặc sẽ dùng GSAP ScrollTrigger (parallax, reveal, pin) và cần Lenis + ScrollTrigger KHÔNG đá nhau (giật, lệch vị trí trigger).
- KHÔNG dùng nếu chỉ cần vài hiệu ứng cuộn nhẹ không cần smooth-scroll nền (dùng — vanilla, 0 dependency).
scroll-effects - KHÔNG dùng để pin/cuộn-ngang một section riêng (đó là ) — nhưng nếu trang có cả hai nhu cầu, khởi tạo Lenis theo skill này TRƯỚC, rồi
gsap-scrolltrigger-pinhoạt động bình thường bên trên vì cả hai đều lấy ScrollTrigger làm trục.gsap-scrolltrigger-pin- User nói "lenis", "smooth scroll", "cuộn mượt kiểu apple", "physics-based scroll", hoặc .
/lenis-smooth-scroll
- User nói "lenis", "smooth scroll", "cuộn mượt kiểu apple", "physics-based scroll", hoặc
- Non-goals: không pin/cuộn ngang một section (→ ), không hiệu ứng cuộn lẻ 0-dependency (→
gsap-scrolltrigger-pin), không viết lại code gốc của tác giả.scroll-effects
- **目的:**构建 Lenis 作为全页面基于物理的滚动基础,并与 GSAP ScrollTrigger 正确同步(只使用一个 raf driver,不发生相位偏移,重新切回标签页时也不会卡顿),默认使用 中未经改写的原始版本。
Rheinmir/uiux-asset - 触发条件(何时使用):
- 页面需要 Apple/awwwards 风格富有“分量感/顺滑感”的滚动体验,而不是浏览器默认的生硬滚动。
- 页面已经或将要使用 GSAP ScrollTrigger(parallax、reveal、pin),并且需要确保 Lenis + ScrollTrigger 不会相互干扰(卡顿或 trigger 位置偏移)。
- 如果只需要少量轻量滚动效果而不需要全页面 smooth-scroll 基础,则不要使用(应使用 ——vanilla、0 dependency)。
scroll-effects - 不要用于固定或横向滚动某个独立 section(那属于 )——但如果页面同时存在这两种需求,应先按本 skill 初始化 Lenis,再在其上使用
gsap-scrolltrigger-pin;由于两者都以 ScrollTrigger 为轴,后者仍可正常工作。gsap-scrolltrigger-pin - 用户提到“lenis”“smooth scroll”“Apple 风格的平滑滚动”“physics-based scroll”或 。
/lenis-smooth-scroll
- **非目标:**不用于固定或横向滚动某个 section(→ ),不用于零依赖的单项滚动效果(→
gsap-scrolltrigger-pin),也不重写作者的原始代码。scroll-effects
Mental model
心智模型
bản gốc (Rheinmir/uiux-asset) → copy nguyên file → chỉ sửa nội dungassets/ (vanilla rút gọn) → ADAPTreduced-motion? → không Lenisnew Lenis → driver: 2A raf tự quản (không GSAP) XOR 2B gsap.ticker (có GSAP) → lenis.on('scroll', ScrollTrigger.update) → reveal/data-speed ăn theo cùng driver原始版本(Rheinmir/uiux-asset)→ 原样复制整个文件 → 只修改内容assets/(精简版 vanilla)→ ADAPTreduced-motion? → 不启用 Lenisnew Lenis → driver 2A:raf 自管(无 GSAP)XOR driver 2B:gsap.ticker(有 GSAP)→ lenis.on('scroll', ScrollTrigger.update) → reveal/data-speed 跟随同一个 driverInput và output contract
输入与输出约定
| Field | Required? | Ý nghĩa | |
|---|---|---|---|
| In | trang/dự án đích | có | có build step (npm) hay trang tĩnh (CDN) |
| In | có dùng GSAP ScrollTrigger? | có | quyết định driver 2A hay 2B |
| In | được kéo lib ngoài? | có | quyết định bản gốc hay |
| Out | trang cuộn Lenis | có | một driver duy nhất; |
| Out | bằng chứng verify | có | |
| 字段 | 必填? | 含义 | |
|---|---|---|---|
| 输入 | 目标页面/项目 | 是 | 是否有 build step(npm),或是静态页面(CDN) |
| 输入 | 是否使用 GSAP ScrollTrigger? | 是 | 决定使用 driver 2A 还是 2B |
| 输入 | 是否允许拉取外部库? | 是 | 决定使用原始版本还是 |
| 输出 | 使用 Lenis 滚动的页面 | 是 | 只能有一个 driver;如果通过 |
| 输出 | 验证证据 | 是 | 使用 |
Rules và capabilities
规则与能力
- RULE-01 (MUST): Cài đặt: (khuyến nghị cho dự án có build step) — hoặc CDN như trong
npm i lenis gsap(assets/demo.html,unpkg.com/lenis) cho trang tĩnh/demo nhanh. Không dùng bản Lenis cũ tên góicdnjs.cloudflare.com/.../gsap(đã đổi tên thành@studio-freight/lenis) trừ khi dự án đang pin phiên bản cũ có lý do.lenis - RULE-02 (MUST): Lỗi thường gặp #1: quên → cuộn mượt bình thường nhưng giật một cú khi người dùng đổi tab rồi quay lại — vì GSAP tự bù-lag chồng lên cơ chế làm mượt riêng của Lenis (xem giải thích ở mục Cơ chế).
gsap.ticker.lagSmoothing(0) - RULE-03 (MUST): Lỗi thường gặp #2: chạy CẢ 2A (tự quản) LẪN 2B (
requestAnimationFrame(raf)) cùng lúc → hai vòng raf lệch pha, giật nhẹ liên tục. Chỉ chọn MỘT driver: có GSAP thì dùng 2B, không có thì dùng 2A.gsap.ticker.add - RULE-04 (MUST): Lỗi thường gặp #3: gọi từ
lenis.raf(time)mà quên nhângsap.ticker(giây → mili-giây) → easing tính sai.* 1000 - RULE-05 (MUST): → không khởi tạo Lenis, không giả-mượt bằng CSS
prefers-reduced-motion: reducethay thế — để cuộn gốc trình duyệt hoàn toàn (đã code trongscroll-behavior: smooth, đừng xoá nhánh này khi adapt).assets/lenis-demo.js - RULE-06 (MUST): Verify bằng : cuộn nhanh liên tục, kiểm tra không có nhảy vị trí giữa
playwright-verifyvà section chứa nó; test cả nhánh reduced-motion (giả lập quadata-ls-reveal).page.emulateMedia - Capabilities: đọc/copy file mẫu từ repo ngoài hoặc ; ghi vào dự án đích; cài dependency frontend (lenis, gsap); chạy trình duyệt headless để verify.
assets/
- RULE-01(必须):安装:(推荐用于带 build step 的项目)——静态页面或快速 demo 可使用
npm i lenis gsap中的 CDN 方式(assets/demo.html、unpkg.com/lenis)。除非项目因故固定了旧版本,否则不要使用旧包名cdnjs.cloudflare.com/.../gsap(现已更名为@studio-freight/lenis)。lenis - RULE-02(必须):常见错误 #1:忘记 → 滚动平时虽然平滑,但用户切换标签页再回来时会出现一次卡顿——因为 GSAP 的自动 lag 补偿与 Lenis 自带的平滑机制发生重叠(详见“机制”部分)。
gsap.ticker.lagSmoothing(0) - RULE-03(必须):常见错误 #2:同时运行 2A(自行管理的 )和 2B(
requestAnimationFrame(raf))→ 两个 raf 循环发生相位偏移,并持续产生轻微卡顿。只能选择一个 driver:有 GSAP 时使用 2B,没有时使用 2A。gsap.ticker.add - RULE-04(必须):常见错误 #3:从 调用
gsap.ticker时忘记乘以lenis.raf(time)(秒 → 毫秒)→ easing 计算错误。* 1000 - RULE-05(必须):当 时,不初始化 Lenis,也不要用 CSS
prefers-reduced-motion: reduce伪造平滑效果——应完全保留浏览器的原生滚动(在scroll-behavior: smooth中已实现该分支,ADAPT 时不要删除)。assets/lenis-demo.js - RULE-06(必须):使用 验证:连续快速滚动,检查
playwright-verify与其所在 section 之间没有位置跳跃;通过data-ls-reveal测试 reduced-motion 分支。page.emulateMedia - 能力:从外部 repo 或 读取/复制示例文件;写入目标项目;安装前端依赖(lenis、gsap);运行 headless browser 进行验证。
assets/
Failure boundaries
失败边界
- Không mở/clone được → dùng
Rheinmir/uiux-assetvanilla rút gọn (partial), báo user.assets/ - User bật → không khởi tạo Lenis (đúng hành vi, không phải lỗi).
prefers-reduced-motion: reduce - Verify thấy nhảy vị trí/giật → failed, rà lại 3 lỗi thường gặp (#1–#3) trước khi báo xong.
- Dự án pin có lý do → giữ nguyên, clarify với user trước khi đổi gói.
@studio-freight/lenis
- 无法打开或 clone → 使用
Rheinmir/uiux-asset中自行编写的精简 vanilla 版本(partial),并告知用户。assets/ - 用户启用了 → 不初始化 Lenis(这是正确行为,不是错误)。
prefers-reduced-motion: reduce - 验证发现位置跳跃或卡顿 → failed,完成前先复查三个常见错误(#1–#3)。
- 项目因故固定了 → 保持不变,更改包名前先向用户说明并确认。
@studio-freight/lenis
HOW
HOW
Main workflow
主工作流
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|---|---|---|---|---|
| W01 | judgment | yêu cầu | Chọn pen gốc phù hợp trong bảng "Bản gốc", mở link chạy xem đúng hiệu ứng | pen được chọn | không được kéo lib ngoài → B01 |
| W02 | effect | pen | Copy nguyên file | trang chạy | — |
| W03 | deterministic | trang | Cài ( | Lenis chạy | có GSAP → B02 |
| W04 | deterministic | trang | Verify bằng | pass | giật/nhảy → rà lỗi #1–#3, lặp W03 |
Chi tiết từng bước (nguồn chân lý cho W01–W04):
| 步骤 | 类型 | 输入 | 操作 | 输出/退出条件 | 失败/下一步 |
|---|---|---|---|---|---|
| W01 | 判断 | 需求 | 在“原始版本”表格中选择合适的 Pen,打开链接并实际运行以确认效果 | 选定 Pen | 无法拉取外部库 → B01 |
| W02 | 效果 | Pen | 将完整 | 页面可运行 | — |
| W03 | 确定性 | 页面 | 安装( | Lenis 正常运行 | 有 GSAP → B02 |
| W04 | 确定性 | 页面 | 使用 | 通过 | 卡顿/跳跃 → 复查错误 #1–#3,重复 W03 |
以下为各步骤的详细信息(W01–W04 的事实来源):
Bản gốc — dùng TRƯỚC (copy nguyên file, đừng viết lại)
原始版本——优先使用(完整复制文件,不要重写)
Code gốc NGUYÊN VĂN của tác giả (CodePen public = MIT) nằm ở repo ngoài — gallery chạy thật: https://rheinmir.github.io/uiux-asset/scroll-effects/ .
Quy trình: mở link chạy để xem đúng hiệu ứng → copy nguyên file (+ thư mục nếu file trỏ tới) vào dự án → giữ comment ghi công dòng đầu → chỉ sửa nội dung/ảnh/màu. Chạy local qua HTTP, không .
nếu cần cả bộ offline.
Rheinmir/uiux-asset.html_assets/file://git clone --depth 1 https://github.com/Rheinmir/uiux-asset| Pen gốc — tác giả | Link |
|---|---|
| Lenis Smooth Scroll & GSAP Page — filipz | chạy · code |
| Lenis Smooth Scroll Cinematic Experience — filipz | chạy · code |
| Layout Explorations with GSAP, Flip, Lenis and ScrollTrigger N°2 — filipz | chạy · code |
| Staggered Text Scroll Reveal — gusevdigital | chạy · code |
assets/作者未经改写的原始代码(公开 CodePen = MIT)位于外部 repo ——实际运行 gallery:https://rheinmir.github.io/uiux-asset/scroll-effects/ 。
流程:打开链接并实际运行以查看正确效果 → 将完整 文件(如果文件引用了 ,也一并复制)复制到项目中 → 保留文件首部的署名注释 → 只修改内容、图片和颜色。通过 HTTP 在本地运行,不要使用 。
如需完整离线副本,可执行 。
Rheinmir/uiux-asset.html_assets/file://git clone --depth 1 https://github.com/Rheinmir/uiux-asset| 原始 Pen——作者 | 链接 |
|---|---|
| Lenis Smooth Scroll & GSAP Page — filipz | 运行 · 代码 |
| Lenis Smooth Scroll Cinematic Experience — filipz | 运行 · 代码 |
| Layout Explorations with GSAP, Flip, Lenis and ScrollTrigger N°2 — filipz | 运行 · 代码 |
| Staggered Text Scroll Reveal — gusevdigital | 运行 · 代码 |
本 skill 中的 只是自行编写的精简 vanilla 版本——仅在项目不能拉取外部库时使用;默认使用上述原始版本。
assets/Assets
Assets
assets/demo.htmlassets/lenis-demo.cssassets/lenis-demo.jsassets/demo.htmlassets/lenis-demo.cssassets/lenis-demo.jsCơ chế
机制
1. Khởi tạo Lenis
1. 初始化 Lenis
js
const lenis = new Lenis({
lerp: 0.1, // nội suy mỗi frame (0–1): thấp = mượt/trễ hơn, cao = bám sát input hơn
duration: 1.2, // easing khi có target (vd anchor scroll), không áp dụng cho wheel liên tục
smoothWheel: true, // bật vật lý mượt cho wheel/trackpad — lý do chính để dùng Lenis
});js
const lenis = new Lenis({
lerp: 0.1, // nội suy mỗi frame (0–1): thấp = mượt/trễ hơn, cao = bám sát input hơn
duration: 1.2, // easing khi có target (vd anchor scroll), không áp dụng cho wheel liên tục
smoothWheel: true, // bật vật lý mượt cho wheel/trackpad — lý do chính để dùng Lenis
});2A. Đứng một mình (không GSAP) — vòng lặp raf tự quản
2A. 独立运行(无 GSAP)——自行管理的 raf 循环
js
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);js
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);2B. Có GSAP ScrollTrigger — GỘP về một driver duy nhất (không dùng cả 2A lẫn 2B cùng lúc)
2B. 有 GSAP ScrollTrigger——合并到唯一 driver(不要同时使用 2A 和 2B)
js
gsap.registerPlugin(ScrollTrigger);
lenis.on('scroll', ScrollTrigger.update); // Lenis cuộn -> báo ScrollTrigger cập nhật ngay
gsap.ticker.add((time) => lenis.raf(time * 1000)); // gsap.ticker LÀM vòng raf cho Lenis luôn
gsap.ticker.lagSmoothing(0); // tắt bù-lag mặc định của GSAP (xem lý do bên dưới)Tại sao phải làm đúng thứ tự 3 dòng này (điểm hay sai nhất):
- đã tự chạy một vòng
gsap.tickernội bộ để lái mọi tween/ScrollTrigger. Nếu Lenis lại tự chạy thêm mộtrequestAnimationFrameriêng (cách 2A) TRONG KHI đã có GSAP, hai vòng lặp không cùng nhịp — mỗi frame chúng cập nhật lệch nhau vài mili-giây, ScrollTrigger đọc vị trí cuộn "cũ hơn" hoặc "mới hơn" Lenis một khung hình. Cảm giác là giật nhẹ liên tục khi cuộn nhanh, đặc biệt ở section córequestAnimationFrame(raf)hoặcpin. Sửa bằng cách để gsap.ticker làm driver DUY NHẤT: bỏ hẳnscrubriêng, thay bằngrequestAnimationFrame(raf).gsap.ticker.add(...) - phát
gsap.tickertính bằng giây, còntimecần mili-giây → phải nhânlenis.raf(). Quên nhân là lỗi im lặng: Lenis chạy nhưng easing/velocity tính sai theo một hệ thời gian nhỏ hơn 1000 lần, scroll trông "đơ" hoặc "bay" tuỳ lerp.* 1000 - bắt buộc vì Lenis cập nhật vị trí cuộn qua transform nội bộ (
lenis.on('scroll', ScrollTrigger.update)mỗi frame, không phảilerptức thời) — nếu không báo, ScrollTrigger vẫn dùng sự kiệnscrollTopgốc của trình duyệt để tính pin/progress, vốn KHÔNG khớp với vị trí "mượt" mà Lenis đang vẽ ra → pin bị lệch vài px hoặc trigger bắn sai thời điểm.scroll - xử lý một lỗi khác, dễ bị bỏ sót: mặc định GSAP tự phát hiện khung hình bị trễ bất thường (ví dụ tab mất focus vài giây rồi quay lại) và "nén" thời gian lại để bù, cho animation không nhảy cóc. Nhưng Lenis đã tự có cơ chế làm mượt delta-time của riêng nó — hai hệ bù-thời-gian chồng lên nhau khiến cú quay-lại-tab bị giật một nhịp rõ rệt thay vì mượt. Tắt hẳn bù của GSAP (
gsap.ticker.lagSmoothing(0)) để một mình Lenis lo phần đó.lagSmoothing(0)
js
gsap.registerPlugin(ScrollTrigger);
lenis.on('scroll', ScrollTrigger.update); // Lenis cuộn -> báo ScrollTrigger cập nhật ngay
gsap.ticker.add((time) => lenis.raf(time * 1000)); // gsap.ticker LÀM vòng raf cho Lenis luôn
gsap.ticker.lagSmoothing(0); // tắt bù-lag mặc định của GSAP (xem lý do bên dưới)为什么必须严格按这 3 行的顺序执行(这是最容易出错的点):
- 本身已经运行一个内部
gsap.ticker循环,用来驱动所有 tween/ScrollTrigger。如果在已有 GSAP 的情况下,又让 Lenis 自行运行额外的requestAnimationFrame(方式 2A),两个循环将无法保持相同节奏——每一帧的更新时间会相差数毫秒,ScrollTrigger 读到的滚动位置会比 Lenis 的位置旧一帧或新一帧。快速滚动时会因此产生持续轻微卡顿,在包含requestAnimationFrame(raf)或pin的 section 中尤其明显。解决方法是让 gsap.ticker 成为唯一 driver:彻底移除独立的scrub,改用requestAnimationFrame(raf)。gsap.ticker.add(...) - 输出的
gsap.ticker使用秒,而time需要毫秒——因此必须乘以lenis.raf()。忘记相乘会造成静默错误:Lenis 虽然运行,但其 easing/velocity 会按照小 1000 倍的时间系统计算,最终滚动效果会根据 lerp 参数显得“生硬”或“飞驰”。* 1000 - 必须使用 ,因为 Lenis 通过内部 transform 更新滚动位置(每帧执行
lenis.on('scroll', ScrollTrigger.update),而不是立即修改lerp)——如果不通知 ScrollTrigger,它仍会使用浏览器原生的scrollTop事件计算 pin/progress,这与 Lenis 当前绘制出的“平滑”位置不一致 → pin 会偏移数个 px,或 trigger 在错误的时间触发。scroll - 解决另一个容易被忽略的问题:GSAP 默认会检测异常延迟的帧(例如标签页失去焦点数秒后重新激活),并“压缩”时间来补偿,使动画不会突然跳跃。但 Lenis 本身已经具有独立的 delta-time 平滑机制——两套时间补偿机制叠加后,重新切回标签页时会出现一次明显卡顿。必须通过
gsap.ticker.lagSmoothing(0)完全关闭 GSAP 的 lag 补偿,让 Lenis 独自负责这一部分。lagSmoothing(0)
3. Tôn trọng prefers-reduced-motion: reduce
prefers-reduced-motion: reduce3. 尊重 prefers-reduced-motion: reduce
prefers-reduced-motion: reduceKhông được "giả-mượt" cho người đã bật giảm chuyển động — không khởi tạo luôn, để trình duyệt cuộn gốc (jump-scroll bình thường). Kiểm tra TRƯỚC khi gọi :
Lenisnew Lenis(...)js
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
// new Lenis(...) + sync ở trên
} else {
// cuộn gốc trình duyệt; nếu có reveal-on-scroll đi kèm, hiện thẳng bằng CSS/class, không chờ cuộn mượt
}Xem cách áp dụng đầy đủ (kèm demo reveal fallback) trong .
assets/lenis-demo.js不得为已启用“减少动态效果”的用户“伪平滑”——不要初始化 ,让浏览器保持原生滚动(正常的 jump-scroll)。必须在调用 之前检查:
Lenisnew Lenis(...)js
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
// new Lenis(...) + sync ở trên
} else {
// cuộn gốc trình duyệt; nếu có reveal-on-scroll đi kèm, hiện thẳng bằng CSS/class, không chờ cuộn mượt
}有关完整实现方式(包括 demo reveal fallback),请参阅 。
assets/lenis-demo.js4. Demo: reveal + data-speed
khi cuộn qua Lenis
data-speed4. Demo:通过 Lenis 滚动实现 reveal + data-speed
data-speedassets/demo.htmldata-ls-revealScrollTrigger.create({ once: true })data-speed="0.12"gsap.to(..., { scrollTrigger: { scrub: true } })|v| ≤ 0.3scrollassets/demo.htmldata-ls-revealScrollTrigger.create({ once: true })data-speed="0.12"gsap.to(..., { scrollTrigger: { scrub: true } })|v| ≤ 0.3scrollBranches
分支
| ID | Kind | Guard | Hành vi | Skip / failure | Rejoin |
|---|---|---|---|---|---|
| B01 | conditional_required | dự án KHÔNG được kéo lib ngoài / cần bản tự viết | dùng | — | W03 |
| B02 | conditional_required | trang có GSAP ScrollTrigger | driver 2B: | không GSAP → 2A | W04 |
| B03 | conditional_required | | không | — | W04 |
| B04 | user_optional | trang cần thêm pin/cuộn ngang section | khởi tạo Lenis theo skill này TRƯỚC rồi dùng | — | W04 |
| ID | 类型 | Guard | 行为 | 跳过/失败 | 汇合点 |
|---|---|---|---|---|---|
| B01 | conditional_required | 项目不能拉取外部库,或需要自行编写的版本 | 使用 | — | W03 |
| B02 | conditional_required | 页面使用 GSAP ScrollTrigger | driver 2B: | 无 GSAP → 2A | W04 |
| B03 | conditional_required | | 不执行 | — | W04 |
| B04 | user_optional | 页面还需要固定/横向滚动某个 section | 先按本 skill 初始化 Lenis,再在其上使用 | — | W04 |
Validation và stopping
验证与停止条件
Xong khi cuộn nhanh liên tục không nhảy vị trí giữa và section chứa nó, và nhánh reduced-motion (qua ) cuộn gốc không Lenis. Code chỉ có MỘT driver raf.
playwright-verifydata-ls-revealpage.emulateMedia使用 连续快速滚动时, 与其所在 section 之间没有位置跳跃;同时,通过 验证 reduced-motion 分支使用浏览器原生滚动,而不是 Lenis。代码中只能存在一个 raf driver。
playwright-verifydata-ls-revealpage.emulateMediaExamples
示例
- Positive: "làm trang landing cuộn mượt kiểu apple có parallax" → chọn pen "Lenis Smooth Scroll & GSAP Page — filipz", copy nguyên , đổi nội dung/ảnh → verify cuộn nhanh không lệch pin, reduced-motion cuộn gốc.
lenis-smooth-scroll-gsap-page.html - Boundary/failure: code adapt có cả lẫn
requestAnimationFrame(raf)→ giật nhẹ liên tục (lỗi #2) → xoá vòng 2A, chỉ giữ 2B, verify lại; quêngsap.ticker.add(...)thì scroll "đơ/bay" (lỗi #3).* 1000
- 正向:“制作一个具有 Apple 风格平滑滚动和 parallax 的 landing page”→ 选择 Pen“Lenis Smooth Scroll & GSAP Page — filipz”,完整复制 ,修改内容/图片 → 验证快速滚动时 pin 不偏移,并确认 reduced-motion 下使用浏览器原生滚动。
lenis-smooth-scroll-gsap-page.html - **边界/失败:**ADAPT 后的代码同时包含 和
requestAnimationFrame(raf)→ 持续出现轻微卡顿(错误 #2)→ 删除 2A 循环,仅保留 2B,然后重新验证;忘记gsap.ticker.add(...)会导致滚动“生硬/飞驰”(错误 #3)。* 1000
Origin
来源
Batch 180926 — bản gốc NGUYÊN VĂN nằm ở (xem mục "Bản gốc" ở trên); là bản rút gọn vanilla tự viết.
Rheinmir/uiux-asset/scroll-effects/assets/Batch 180926——未经改写的原始版本位于 (见上文“原始版本”部分); 是自行编写的精简 vanilla 版本。
Rheinmir/uiux-asset/scroll-effects/assets/