点击滚动到任意位置

涉及知识点:

window.scrollTo(x, y)
requestAnimationFrame(()=>{})  //帧动画,优点:按浏览器的刷新频率渲染,更加流畅。特点:类似 setTimeout 只执行一次

啥也不说,直接上 react 版代码:

  num 是需要到达的位置, 数字类型。调用:this.transitionScroll(100)

  下面这段代码,亲只需要知道,每个索引对应的高度就可以了。

let timer = null;

this.state = {
    onOff: true, //初始值为true,默认可以点击,在滚动的时候变成false,结束滚动再次为true
    active: 0
}

headerBtnClick = (index) => { //点击改变索引
    if(this.state.onOff) {
        this.setState({
            active: index
        }, () => {
            this.scrollFn(index)
        })
    }
}

scrollFn = (index) => {  //每个索引对应的位置
    //this.transitionScroll(...)  根据索引,判断需要滚动到的位置。
}

componentDidMount() {
    window.addEventListener("scroll", () => { //监听是否为滚动状态,在滚动状态不可再次点击
        clearTimeout(timer) //利用防抖技巧,在结束滚动250ms之后恢复可点击状态
        timer = setTimeout(() => {
            this.setState({
                onOff: true
            })
        }, 250)
        this.setState({
            onOff: false
        })
    })
}

componentWillUnmount() {
    if(timer) {
        clearTimeout(timer)
    }
}
//sensitivity: 容错率和灵敏度为 5 时正好
//容错率越小,滚动的位置越精确,太小可能会出现无限回调的错误(主要原因是数字相除再取整,值不再精确)
transitionScroll = (num) => { //判断需要上滚,还是下滚
    const n = window.pageYOffset;
    if(num < n) {
        this.ScrollDown(num)
    }
    if(num > n) {
        this.ScrollUp(num)
    }
}

ScrollDown = (num) => {  //向下滚
    const sensitivity = 5;
    window.requestAnimationFrame(() => {
        const n = window.pageYOffset;
        const Dvalue = Math.abs(num - n);
        if (num > n + sensitivity) {//容错率
            window.scrollTo(0, n + parseInt(Dvalue / sensitivity))//灵敏度
            this.ScrollDown(num)
        }
    })
}
   
ScrollUp = (num) => {  //向上滚
    const sensitivity = 5;
    window.requestAnimationFrame(() => {
        const n = window.pageYOffset;
        const Dvalue = Math.abs(num - n);
        if (num < n - sensitivity) {
            window.scrollTo(0, n - parseInt(Dvalue / sensitivity))
            this.ScrollDown(num)
        }
    })
}
原文地址:https://www.cnblogs.com/MrZhujl/p/11612423.html