js控制页面滚动(实例)

2019-05-21  本文已影响0人  码代码的小公举

react 项目下

目标描述:多个图片排列下来,按右边的小按钮,抵达相应位置,鼠标滑动,抵达下一图,或者上一图
知识点:onmousewheel,addEventListener,scrollTo,setTimeout

过程:
1.body 宽,高钉死,100vw,100vh,overflow:hidden 使得不出现滚动条,不然不好看
2.图片放进去,排起来,(注意:默认空隙的处理,可以使用flex布局,空隙就不见了)
3.制作相对于视窗的按钮,几张图片就几个按钮,(position: fixed;计算一下高度,可以利用calc计算top使得上下居中)
4.美化一下,css写写
5.先写简单的按钮事件

handlerGoNext(page) { //传入要走到第几个图
    this.num = 10
    const vw = document.body.clientWidth < 1000 ? 1000 : document.body.clientWidth //这里按图片比例算出来高度
    let nowH = window.pageYOffset //此时距离顶部的高度
    this.top = nowH //当前top //给存一下,后面要用到
    let h = 675/1200*vw*(page - 1) + 91 //计算总高度,这里我顶部有个导航栏高度是91
    if(page === 1) {
      h = 0 //第一张就是0啦
    }
    const faster = (h-nowH)/10 //10次结束,每次需要增加的的距离,
    this.handlerGo(faster) //去走动画效果啦
    this.setState({
      now: page //把当前的位置存一下
    })
  }

  handlerGo(faster) {
    this.timer && clearTimeout(this.timer) //注意clearTimeout
    if(this.num > 0) { //当次数没走完的时候
      this.num = this.num - 1
      this.top = this.top + faster //每次改变top
      window.scrollTo(0,this.top) //滚动到需要到位置
      this.timer = setTimeout(() => {
        this.handlerGo(faster)//这里循环
      },50)//每次滚动的时间,这里可以试着变长,500左右,你可以清除看到你动画的慢动作
    }else {//10次结束,要重新变成10,然后允许下一次动画
      this.num = 10
      this.timer = setTimeout(() => {
        this.ing = false //这里是控制动画的,为了限制滑动后的触发次数
      },500) //这里给点时间间隔,不然容易跨页,滑动有惯性
    }
  }

6.写监听滑动事件(onmousewheel在火狐无效,DOMMouseScroll只在火狐有效)
react在componentDidMount的时候监听

document.body.onmousewheel = (e) => {
      if(e.wheelDelta < 0 && this.state.now < 5 && !this.ing) { //向下滑动,没有到底,没有正在执行的滑动效果
        this.timer && clearTimeout(this.timer)
        this.timer = setTimeout(() => {
          !this.ing && this.handlerGoNext(this.state.now+1)
          this.ing = true
        }, 30);
      }else if(e.wheelDelta > 0 && this.state.now > 1 && !this.ing){//向上滑动,没有到顶
        this.timer && clearTimeout(this.timer)
        this.timer = setTimeout(() => {
          !this.ing && this.handlerGoNext(this.state.now-1)
          this.ing = true
        }, 30);
      }else if (e.wheelDelta < 0 && this.state.now === 5 && !this.ing) {
        //向下滑动,刚好最后一个动画的时候,这里是因为我的页面有个底部,滑动到最后一个图片还不够全部展示,这里单独走一次动画,使得滑动到最底下。
        this.timer && clearTimeout(this.timer)
        this.timer = setTimeout(() => {
          !this.ing && this.handlerGo(10) //这里我根据自己的页面做了简单的计算保证速度10可以到底
          this.ing = true
        }, 30);
      }
    }

7.补充写一下火狐的

componentDidMount() {
    getData({type:1, no:1},(data) => {
      this.setState({
        dataA: data.list.result[0]
      })
    })
    getData({type:2, no:1},(data) => {
      this.setState({
        dataB: data.list.result[0]
      })
    })
    if(window.navigator.userAgent.indexOf('Firefox') > -1) {
      document.addEventListener('DOMMouseScroll',(e) => {
        this.handleMove( 0 - e.detail) 
      },false)
    }else {
      document.body.onmousewheel = (e) => {
        this.handleMove(e.wheelDelta)
      }
    }
  }

  handleMove(type) { //用type表示上下
    if(type < 0 && this.state.now < 5 && !this.ing) { //向下滑动,没有到底,没有正在执行的滑动效果
      this.timer && clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        !this.ing && this.handlerGoNext(this.state.now+1)
        this.ing = true
      }, 30);
    }else if(type > 0 && this.state.now > 1 && !this.ing){
      this.timer && clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        !this.ing && this.handlerGoNext(this.state.now-1)
        this.ing = true
      }, 30);
    }else if (type < 0 && this.state.now === 5 && !this.ing) {
      this.timer && clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        !this.ing && this.handlerGo(10)
        this.ing = true
      }, 30);
    }
  }
  1. 页面卸载,取消绑定
if(window.navigator.userAgent.indexOf('Firefox') > -1) {
      document.addEventListener('DOMMouseScroll',this.handlerGet,false) //这里为了取消他,需要用这样的函数替代
    }else {
      document.body.onmousewheel = (e) => {
        this.handleMove(e.wheelDelta)
      }
    }

handlerGet = (e) => { //过渡一下
    this.handleMove( 0 - e.detail) 
  }

componentWillUnmount() { //清除监听事件
    this.timer && clearTimeout(this.timer)
    if(window.navigator.userAgent.indexOf('Firefox') > -1) {
      document.removeEventListener('DOMMouseScroll',this.handlerGet,false)
    }else {
      document.body.onmousewheel = false
    }
  }

9.测试检查一下。
完成啦,啦啦啦~
我的截图:


成果

缺点:这里我是一直对页面进行监听,导致滑动过快对时候动画效果开始执行对时间延后。体现为滑动对轻,整个就流畅一点。
ps:写这种带计算带页面,我觉得是考验思维的,你可以对这里的知识点不熟练,但是你必须得能理解每一步的加加减减。

上一篇下一篇

猜你喜欢

热点阅读