zoukankan      html  css  js  c++  java
  • vue锚点双向绑定

    • 需求描述:

    头部固定吸顶,右侧菜单,左侧长页面,要求左侧滚动右侧菜单对应高亮,点击右侧菜单,左侧页面滚动到对应位置。(这个对应位置就是模块头部刚好在固定头部下面)

    • 需求分析:

    头部和右侧可使用fixed定位,左侧长页面不限制高度。有两件事需要处理:监听滚动事件,实现滚动效果。

    • 解决问题
    // 监听事件添加和销毁
    mounted() {
        document.addEventListener('scroll', this.handleScroll)
    },
        
    beforeDestroy() {
        document.removeEventListener('scroll', this.handleScroll)
    }
    
    // 滚动事件
    handleScroll() {
        // 滚动高度
      const sTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      // 最大值,当页面滚动到最大值后,下面的模块不会再向上滚动了
      const max = this.sArea[8] + 10
      
      // 滚动停止后执行函数
      runLastFn(_ => {
        this.initSArea()
        if (sTop < max) {
          // 判读页面滚动对应的菜单index
          const idx = this.findAreaIndex(sTop)
          if (!this.mFlag) return
          this.currentFloor = 'block' + idx
        }
      })
    },
        
    // 初始化不同模块(12个)滚动间距,注意每个模块都设置一个ref,每个模块滚动的距离组成一个数组,与菜单对应
    initSArea() {
      const arr = []
      for (let i = 1; i < 12; i++) {
        const height = this.$refs[`block${i}`].offsetTop - 240 // 240 是所有模块滚动目标位置
        arr.push(height > 0 ? height : 0)
      }
      this.sArea = arr
      this.boxScreenHeight = this.$refs.boxRef.scrollHeight
    },
        
    // 滚动距离在数组中位置,以此判读哪个菜单应该在选择状态
    findAreaIndex(val) {
      const sArea = this.sArea
      const len = sArea.length
      if (val < sArea[1]) return 1
      if (val > sArea[len - 1]) return len - 1
    
      let idx = 0
      let i = 0
      for (i; i < len; i++) {
        if (sArea[i] > val) {
          idx = i
          break
        }
      }
      return idx
    }
    
    // 点击菜单滚动到对应模块
    gotoBlock(el, speed) {
      const idx = Number(el.slice(5))
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop // 滚动条距离顶部高度
      let currentTop = scrollTop // 默认滚动位置为当前滚动条位置,若改为0,则每次都会从顶部滚动到指定位置
      let top = 0 // 需要滚动到的位置
    
      if (idx < 9) {
        this.mFlag = true
        const i = idx - 1 > 0 ? idx - 1 : 0 // 有个回到顶部菜单,所以第一个和第二个滚动位置一样
        top = this.sArea[i] + 1 // 模块需要滚动的位置
      } else {
        this.mFlag = false // 页面无需滚动了,但是菜单被点击后仍要选中状态
        top = this.boxScreenHeight
        this.currentFloor = el
        setTimeout(_ => {
          this.mFlag = true
        }, 1200)
      }
        
      let requestId
      function step() {
        // 如果需要滚动的位置和当前位置之差小于步长speed,直接滚动到目标位置,否则按照步长滚动
        if (Math.abs(currentTop - top) < speed) {
          window.scrollTo(0, top)
        } else {
          if (scrollTop < top) {
            // 如果滚动条的高度小于元素距离顶部的高度
            if (currentTop <= top) {
              window.scrollTo(0, currentTop)
              requestId = window.requestAnimationFrame(step)
            } else {
              window.cancelAnimationFrame(requestId)
            }
            // 向下滚动
            currentTop += speed
          } else {
            if (top <= currentTop) {
              window.scrollTo(0, currentTop - speed)
              requestId = window.requestAnimationFrame(step)
            } else {
              window.cancelAnimationFrame(requestId)
            }
            // 向上滚动
            currentTop -= speed
          }
        }
      }
      window.requestAnimationFrame(step)
    },
    
  • 相关阅读:
    [转载]DataView详解
    (转)C#中“EQUALS”与“==”的速度比较
    CS0016: 未能写入输出文件“c:WindowsMicrosoft.NETFramework64v2.0.50727Temporary ASP.NET Files oot921bbfc4ca7cf42App_Code.fu98jwep.dll”--“拒绝访问。 ”
    C# 配置错误定义了重复的“system.web.extensions/scripting/scriptResourceHandler”节
    C# 利用mysql.data 在mysql中创建数据库及数据表
    【转载】经典SQL语句大全
    我不是一个做产品人,但我有一颗做产品的心--浅谈“痛点”
    软件工程--个人总结
    第十六周进度条
    梦断代码阅读笔记3
  • 原文地址:https://www.cnblogs.com/codebook/p/15380056.html
Copyright © 2011-2022 走看看