滚动到指定位置
原生 js 和 lenis
点击后滚动到页面指定的 id
原生
方法
js
const smoothScrollTo = (element) => {
// 获取目标元素的当前位置
const targetPosition =
element.getBoundingClientRect().top + window.pageYOffset;
// 获取当前滚动位置
let currentPosition = window.pageYOffset;
// 计算滚动距离
const distance = targetPosition - currentPosition;
// 定义动画的起始时间
let startTime = null;
function animation(currentTime) {
// 如果是第一次执行,记录起始时间
if (startTime === null) startTime = currentTime;
// 计算已经过去的时间
const timeElapsed = currentTime - startTime;
// 使用 ease-in-out 动画效果
const run = ease(timeElapsed, currentPosition, distance, 1000);
// 更新当前滚动位置
window.scrollTo(0, run);
// 如果动画未完成,继续动画
if (timeElapsed < 1000) requestAnimationFrame(animation);
}
// 定义 ease-in-out 动画效果的函数
function ease(t, b, c, d) {
t /= d / 2;
if (t < 1) return (c / 2) * t * t + b;
t--;
return (-c / 2) * (t * (t - 2) - 1) + b;
}
// 开始动画
requestAnimationFrame(animation);
};
使用
- 传入 id 即可 不要加
#
js
const scrollgointoview = (id) => {
// 使用示例
const targetElement = document.getElementById(id);
smoothScrollTo(targetElement);
};
lenis
要是使用 项目里面就都使用,否则就不要用
安装
js
npm i lenis -S
- 或者使用 script 引入
html
<script src="https://unpkg.com/lenis@1.3.4/dist/lenis.min.js"></script>
基础使用
(1) 构造
设置页面平滑滚动
js
const lenis = new Lenis({
// 容器
wrapper: window,
smoothWheel: true,
// 持续时间 单位秒
duration: 1.2,
// 滑动效果的缓动函数
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
// 滑动方向 horizontal 水平方向 vertical 垂直方向
orientation: "vertical",
// 滑动手势 horizontal 水平方向 vertical 垂直方向 手机端
gestureOrientation: "vertical",
// 页面改变 他也改变
autoResize: true,
});
const raf = (time) => {
lenis.raf(time);
requestAnimationFrame(raf);
};
requestAnimationFrame(raf);
(2) 监听
- 监听滚动事件和距离
js
lenis.on("scroll", ({ scroll, limit, velocity, direction, progress }) => {
console.log("scroll", scroll);
console.log("limit", limit);
console.log("velocity", velocity);
console.log("direction 当前的滑动方向", direction);
console.log("progress 当前的滚动条进度", progress);
});
(3)页面是否能滚动
js
// 停止
lenis.stop();
// 2s开始
setTimeout(() => {
lenis.start();
}, 2000);
(4)滚动到指定位置
js
const scrollgointoview = (id) => {
lenis.scrollTo(document.getElementById(id), {
// 这样页面没有滑动完 不会有任何操作
lock: true,
// 偏移
offset: -50,
// 滚动到指定元素时,是否触发动画 true 就是不会触发动画
immediate: false,
// 动画持续时间
duration: 1.2,
// 动画结束后的回调函数
onComplete: () => {
console.log("滚动结束");
},
// 滑动效果的缓动函数
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
});
};
完整版案例
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/lenis@1.3.4/dist/lenis.min.js"></script>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<div id="div4"></div>
<div class="fixedright">
<div id="div5" onClick="scrollgointoview('div1')"></div>
<div id="div6" onClick="scrollgointoview('div2')"></div>
<div id="div7" onClick="scrollgointoview('div3')"></div>
<div id="div8" onClick="scrollgointoview('div4')"></div>
</div>
</body>
<script>
const lenis = new Lenis({
// 容器
wrapper: window,
// 滚轮
smoothWheel: true,
// 持续时间 单位秒
duration: 1.2,
// 滑动效果的缓动函数
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
// 滑动方向 horizontal 水平方向 vertical 垂直方向
orientation: "vertical",
// 滑动手势 horizontal 水平方向 vertical 垂直方向 手机端
gestureOrientation: "vertical",
// 页面改变 他也改变
autoResize: true,
});
const raf = (time) => {
lenis.raf(time);
requestAnimationFrame(raf);
};
requestAnimationFrame(raf);
// 监听
lenis.on("scroll", ({ scroll, limit, velocity, direction, progress }) => {
console.log("scroll", scroll);
console.log("limit", limit);
console.log("velocity", velocity);
console.log("direction 当前的滑动方向", direction);
console.log("progress 当前的滚动条进度", progress);
});
// 设置页面是否能滚动
// lenis.isStopped = true;
// lenis.stop();
// setTimeout(() => {
// lenis.start();
// }, 2000);
const scrollgointoview = (id) => {
lenis.scrollTo(document.getElementById(id), {
// 这样页面没有滑动完 不会有任何操作
lock: true,
// 偏移
offset: -50,
// 滚动到指定元素时,是否触发动画 true 就是不会触发动画
immediate: false,
// 动画持续时间
duration: 1.2,
// 动画结束后的回调函数
onComplete: () => {
console.log("滚动结束");
},
// 滑动效果的缓动函数
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
});
};
</script>
<style>
* {
margin: 0px;
padding: 0px;
}
.fixedright {
position: fixed;
width: 100px;
height: 200px;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
#div5 {
width: 100%;
height: 50px;
cursor: pointer;
background: red;
}
#div6 {
width: 100%;
height: 50px;
cursor: pointer;
background: blue;
}
#div7 {
width: 100%;
height: 50px;
cursor: pointer;
background: yellow;
}
#div8 {
width: 100%;
height: 50px;
cursor: pointer;
background: green;
}
#div1 {
width: 100%;
height: 1000px;
background-color: red;
}
#div2 {
width: 100%;
height: 1000px;
background-color: blue;
}
#div3 {
width: 100%;
height: 1000px;
background-color: yellow;
}
#div4 {
width: 100%;
height: 1000px;
background-color: green;
}
</style>
</html>