封装动画函数(滚动导航为例)
示例
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
width: 100%;
background-color: #f7f8f9;
}
div[ class ^='box'] {
width: 800px;
height: 400px;
text-align: center;
font-size: 40px;
color: rgb(44, 51, 82);
font-weight: 700;
line-height: 400px;
background-color: #fff;
border: 1px solid #ccc;
margin: 0 auto;
margin-bottom: 20px;
}
ul {
position: absolute;
top: 400px;
right: 50%;
margin-right: -480px;
}
li {
list-style: none;
width: 60px;
height: 40px;
padding: 10px;
text-align: center;
color: #000;
font-weight: 700;
cursor: pointer;
font-size: 12px;
background-color: #fff;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="box1">
<p>box1</p>
</div>
<div class="box2">
<p>box2</p>
</div>
<div class="box3">
<p>box3</p>
</div>
<div class="box4">
<p>box4</p>
</div>
<div class="box5">
<p>box5</p>
</div>
<div class="box6">
<p>box6</p>
</div>
<div class="box7">
<p>box7</p>
</div>
<div class="box8">
<p>box8</p>
</div>
<div class="box9">
<p>box9</p>
</div>
<ul>
<li data-index="1">box1</li>
<li data-index="2">box2</li>
<li data-index="3">box3</li>
<li data-index="4">box4</li>
<li data-index="5">box5</li>
<li data-index="6">box6</li>
<li data-index="7">box7</li>
<li data-index="8">box8</li>
<li data-index="9">box9</li>
</ul>
<script>
let Html = document.documentElement,
ul = document.querySelector('ul');
window.addEventListener('scroll', () => {
if (ul.offsetTop - Html.scrollTop <= 100) {
ul.style.position = 'fixed';
ul.style.top = 100 + 'px';
}
if (Html.scrollTop <= 300) {
ul.style.position = 'absolute';
ul.style.top = 400 + 'px';
}
});
ul.addEventListener('click', (e) => {
let height = e.target.getAttribute('data-index');
// 动画函数
animate(window, 420 * (height - 1), (p) => {
console.log('执行' + p);
});
});
//animate
function animate(element, target, callback) {
// 清除定时器
clearInterval(element.timer);
// 开启定时器
element.timer = setInterval(() => {
//target >= Html.offsetHeight - window.innerHeight 用于判断目标位置 是否大于 能使页面最底部展示的window滚动数值
if (target > Html.offsetHeight - window.innerHeight) {
// 若是符合条件,则将目标值改为 能使页面最底部展示的window滚动数值
target = Html.offsetHeight - window.innerHeight;
}
// 获取步数(且递减)
let step = (target - window.pageYOffset) / 10;
// 限制递减的最小值
step = step > 0 ? Math.ceil((target - window.pageYOffset) / 20) : Math.floor((target - window.pageYOffset) / 20)
// 判断是否到达目标位置
if (window.pageYOffset === target) {
// 符合条件清除定时器
clearInterval(element.timer);
// 回调
callback && callback('success!');
// 到达目标位置后终止动画(避免到达目标位置后继续动画)
return;
}
// 处理页面滚动到最底部的问题
window.scroll(0, window.pageYOffset + step);
}, 10);
}
</script>
</body>
</html>
指定传入动画函数的参数
1 - 三个参数
- element -> 添加动画的元素
- target -> 动画的目标位置
- callback -> 回调函数
function animate(element, target, callback) {
}
2 - 开启定时器
function animate(element, target, callback) {
// 开启定时器
element.timer = setInterval(() => {
}, 10);
}
3 - 获取步数
- 步数 = 目标位置值 - 当前位置值 / 定值
- 最小步长 = 最小值(正数向上取整,取到最小值1。负数向下取整,拿到最小值-1)
function animate(element, target, callback) {
element.timer = setInterval(() => {
// 获取步数(且递减)(步数 = 目标位置值 - 当前位置值 / 定值)
let step = (target - window.pageYOffset) / 10;
// 限制递减的最小值(正数向上取整,取到最小值1。负数向下取整,拿到最小值-1)
step = step > 0 ? Math.ceil((target - window.pageYOffset) / 20) : Math.floor((target - window.pageYOffset) / 20)
}, 10);
}
4 - 移动元素
function animate(element, target, callback) {
// 开启定时器
element.timer = setInterval(() => {
// 获取步数(且递减)
let step = (target - window.pageYOffset) / 10;
// 限制递减的最小值
step = step > 0 ? Math.ceil((target - window.pageYOffset) / 20) : Math.floor((target - window.pageYOffset) / 20)
// 处理页面滚动到最底部的问题
window.scroll(0, window.pageYOffset + step);
}, 10);
}
5 - 到达目标值停止动画
function animate(element, target, callback) {
// 开启定时器
element.timer = setInterval(() => {
let step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil((target - window.pageYOffset) / 20) : Math.floor((target - window.pageYOffset) / 20)
// 判断是否到达目标位置
if (window.pageYOffset === target) {
// 符合条件清除定时器
clearInterval(element.timer);
// 回调
callback && callback('success!');
// 到达目标位置后终止动画(避免到达目标位置后继续动画)
return;
}
// 处理页面滚动到最底部的问题
window.scroll(0, window.pageYOffset + step);
}, 10);
}
节流优化
避免重复开启定时器
清除定时器
function animate(element, target, callback) {
// 清除定时器
clearInterval(element.timer);
element.timer = setInterval(() => {
let step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil((target - window.pageYOffset) / 20) : Math.floor((target - window.pageYOffset) / 20);
//target >= Html.offsetHeight - window.innerHeight 用于判断目标位置 是否大于 能使页面最底部展示的window滚动数值
if (target > Html.offsetHeight - window.innerHeight) {
// 若是符合条件,则将目标值改为 能使页面最底部展示的window滚动数值
target = Html.offsetHeight - window.innerHeight;
}
if (window.pageYOffset === target) {
clearInterval(element.timer);
callback && callback('success!');
return;
}
window.scroll(0, window.pageYOffset + step);
}, 10);
}