html实现滚动/滑动阻尼
对于这个问题我一直处于不知道如何解决的阶段。思考过使用js解决,将视图固定,然后监听鼠标滚动事件,然后使用类似pid的方案来实现阻尼的效果。
当是移动端是则监听按下,然后在按下上监听移动...后面就不知道如何解决了。
现在观看https://www.bilibili.com/video/BV1QN411T7gW/ jiejoe视频得到了思路,但是没有看懂,遂手写一下再水篇文章(笑
首先我们搭建一下基础的框架
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>滑动阻尼</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100%;
}
img {
width: 100%;
}
</style>
<body>
<!-- 首先我们创建一个基础的容器存放图片 -->
<div class="container">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
</div>
</body>
</html>
container容器存放图片,显示在页面当中,而我们再创建一个swipe称之为视图,用来显示浏览器能够看到的界面,宽100%搞为浏览器高度,并且设置为fixd不让他滚动,通过修改top定位来移动他
因为fixed脱离了文档流,没有内容能够撑起body,所以我们的滚动条会消失,无法滚动浏览器,所以我们需要为body设置高度,这样我们才能够滚动浏览器,同时监听浏览器的resize和load当触发两个事件之后我们重新设置body的高度。
再监听滚动事件修改swipe的top配合transition即可达到阻尼的效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>滑动阻尼</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
img {
width: 100%;
}
.container {
width: 100%;
position: relative;
}
.swipe {
position: fixed;
top: 0;
transition: top 0.15s ease;
}
</style>
<body>
<!-- swipe是视图窗口,通过移动他来展示container的内容 -->
<div class="swipe">
<!-- container只是用来存放一堆图片,并且获取高度给body,即父级的父级元素的高度 -->
<div class="container">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
</div>
</div>
</body>
<script>
let container = document.querySelector(".container")
let body = document.querySelector("body")
let swipe = document.querySelector(".swipe")
function resize() {
body.style.height = container.offsetHeight + 'px'
}
function scroll() {
swipe.style.top = `${-scrollY}px`
}
window.addEventListener("scroll", scroll)
window.addEventListener("load", resize)
</script>
</html>
一个是让fixed视图动,还有一个是让container容器移动,效果都可以实现
这里存在一个小问题,当图片没有设置宽/高,而是100%自适应时offsetHeight获取到的终点位置会过高,我们有两种解决办法
1.设置图片的宽度/高度
2.监听图片加载当所有图片加载完成执行resize重新设置大小
这里我采用了第二种办法,遍历img标签为其设置监听事件再判断是否需要重新设置大小
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>滑动阻尼</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
img {
width: 100%;
}
.container {
width: 100%;
position: relative;
}
.swipe {
position: fixed;
top: 0;
transition: top 0.15s ease;
}
</style>
<body>
<!-- swipe是视图窗口,通过移动他来展示container的内容 -->
<div class="swipe">
<!-- container只是用来存放一堆图片,并且获取高度给body,即父级的父级元素的高度 -->
<div class="container">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
<img src="pic.jpg" alt="">
</div>
</div>
</body>
<script>
let container = document.querySelector(".container")
let body = document.querySelector("body")
let swipe = document.querySelector(".swipe")
function resize() {
body.style.height = container.offsetHeight + 'px'
}
function scroll() {
swipe.style.top = `${-scrollY}px`
}
let images = document.querySelectorAll('.container img');
let imagesLoaded = 0;
function checkImages() {
imagesLoaded++;
if (imagesLoaded === images.length) {
console.log(container.offsetHeight);
resize()
}
}
images.forEach(img => {
img.addEventListener('load', checkImages);
});
window.addEventListener("scroll", scroll)
window.addEventListener("load", resize)
</script>
</html>
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。