本文主要使用了以下方法来实现此功能
(1). [react方式]利用定时器requestAnimationFrame来实现
let timer: number = 1000;
/* 方法一:利用性能最好的定时器requestAnimationFrame来实现 */
cancelAnimationFrame(timer);
timer = requestAnimationFrame(function fn(){
var oTop = document.body.scrollTop || document.documentElement.scrollTop;
if(oTop > 0){
document.body.scrollTop = document.documentElement.scrollTop = oTop - 50;
timer = requestAnimationFrame(fn);
}else{
cancelAnimationFrame(timer);
}
});
(2). [react方式]利用html自带的方法scrollTo来实现
/* 方法二:利用html自带的方法来实现 */
scrollTo({top:0,behavior:'smooth'});
(3). [react方式]方法1和方法2的结合版
let timer: number = 1000;
cancelAnimationFrame(timer);
timer = requestAnimationFrame(function fn(){
var oTop = document.body.scrollTop || document.documentElement.scrollTop;
if(oTop > 0){
// eslint-disable-next-line no-restricted-globals
scrollTo(0,oTop-50);
timer = requestAnimationFrame(fn);
}else{
cancelAnimationFrame(timer);
}
});
(4). [react+ts]利用定时器requestAnimationFrame和运动来实现
count: number = 0;
start: number = 0;
dis: number = 0;
timer: number = 0; /* 方法4类型 */
n: number = 0;
step: number = 0;
cur: number = 0;
cancelAnimationFrame(this.timer);
this.start = document.body.scrollTop || document.documentElement.scrollTop; // 开始的位置
this.count = Math.floor(1000 / 30); //次数
this.dis = 0 - this.start; //
this.n = 0;
this.timer = requestAnimationFrame(this.func.bind(this, this.n,this.count));
func(n:number,count:number):void {
n++;
this.step = 1 - n / count; //步长
this.cur = this.start + this.dis * (1 - this.step * this.step * this.step); //每次移动的距离
document.documentElement.scrollTop = document.body.scrollTop = this.cur;
this.timer = requestAnimationFrame(this.func.bind(this,n,count));
if (n === count) {
cancelAnimationFrame(this.timer);
}
(5).[react+ts]利用定时器setInterval来实现
count: number = 0;
start: number = 0;
dis: number = 0;
n: number = 0;
step: number = 0;
cur: number = 0;
timer?: NodeJS.Timeout;
if (this.timer) clearInterval(this.timer);
this.start = document.body.scrollTop || document.documentElement.scrollTop; // 开始的位置
this.count = Math.floor(1000 / 30); //次数
this.dis = 0 - this.start; //要移动的距离
this.n = 0; //清零
this.timer = setInterval(this.func.bind(this), 30); //定义定时器,调用返回顶部方法
func() {
this.n++; //移动次数自增
this.step = 1 - this.n / this.count; //步长
this.cur = this.start + this.dis * (1 - this.step * this.step * this.step); //每次移动的距离
document.documentElement.scrollTop = document.body.scrollTop = this.cur; //设置当前滚动的距离
if (this.n === this.count) {
if (this.timer) clearInterval(this.timer);
}
}
整个项目代码:
import React, { Component } from "react";
import "./backToTop.less";
export default class Home extends Component {
count: number = 0;
start: number = 0;
dis: number = 0;
// timer: number = 0; /* 方法4类型 */
n: number = 0;
step: number = 0;
cur: number = 0;
timer?: NodeJS.Timeout;
oDiv?: HTMLElement;
componentDidMount() {
document.addEventListener("scroll", () => {
if (
document.documentElement.clientHeight +
document.documentElement.scrollTop >
document.documentElement.scrollHeight - 200
) {
this.oDiv = document.querySelector(".fixed") as HTMLElement;
if (this.oDiv) this.oDiv.style.display = "block";
} else { if (this.oDiv) this.oDiv.style.display = "none";}
});
}
backTop() {
// let timer: number = 1000;
// /* 方法一:利用性能最好的定时器requestAnimationFrame来实现 */
// cancelAnimationFrame(timer);
// timer = requestAnimationFrame(function fn(){
// var oTop = document.body.scrollTop || document.documentElement.scrollTop;
// if(oTop > 0){
// document.body.scrollTop = document.documentElement.scrollTop = oTop - 50;
// timer = requestAnimationFrame(fn);
// }else{
// cancelAnimationFrame(timer);
// }
// });
/* 方法二:利用html自带的方法来实现 */
// eslint-disable-next-line no-restricted-globals
// scrollTo({top:0,behavior:'smooth'});
/* 方法三:1和2的结合版 */
// cancelAnimationFrame(timer);
// timer = requestAnimationFrame(function fn(){
// var oTop = document.body.scrollTop || document.documentElement.scrollTop;
// if(oTop > 0){
// // eslint-disable-next-line no-restricted-globals
// scrollTo(0,oTop-50);
// timer = requestAnimationFrame(fn);
// }else{
// cancelAnimationFrame(timer);
// }
// });
/* 方法4:时间版运动 */
/* cancelAnimationFrame(this.timer);
this.start = document.body.scrollTop || document.documentElement.scrollTop; // 开始的位置
this.count = Math.floor(1000 / 30); //次数
this.dis = 0 - this.start; //
this.n = 0;
this.timer = requestAnimationFrame(this.func.bind(this, this.n,this.count)); */
/* 方法5:setInterval */
if (this.timer) clearInterval(this.timer);
console.log(
document.documentElement.scrollHeight,
document.documentElement.scrollTop + document.documentElement.clientHeight
);
this.start = document.body.scrollTop || document.documentElement.scrollTop; // 开始的位置
this.count = Math.floor(1000 / 30); //次数
this.dis = 0 - this.start; //要移动的距离
this.n = 0; //清零
this.timer = setInterval(this.func.bind(this), 30); //定义定时器,调用返回顶部方法
}
/* 方法4函数 */
/* func(n:number,count:number):void {
n++;
this.step = 1 - n / count; //步长
this.cur = this.start + this.dis * (1 - this.step * this.step * this.step); //每次移动的距离
document.documentElement.scrollTop = document.body.scrollTop = this.cur;
this.timer = requestAnimationFrame(this.func.bind(this,n,count));
if (n === count) {
cancelAnimationFrame(this.timer);
} */
/* 方法5函数 */
func() {
this.n++; //移动次数自增
this.step = 1 - this.n / this.count; //步长
this.cur = this.start + this.dis * (1 - this.step * this.step * this.step); //每次移动的距离
document.documentElement.scrollTop = document.body.scrollTop = this.cur; //设置当前滚动的距离
if (this.n === this.count) {
if (this.timer) clearInterval(this.timer);
}
}
render() {
return (
<div className="back-to-top">
<div className="container">
<h3 className="center"> 返回顶部页面</h3>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
<p>test 测试</p>
</div>
<div className="fixed" onTouchStart={this.backTop.bind(this)}>
<div className="back">返回顶部</div>
</div>
</div>
);
}
}