精准还原页面滚动高度

529 阅读1分钟

背景

文档从背景页切换到编辑页面的时候,需要记住当前浏览的位置

方案一:

  1. 记住文档区域滚动的scrollTop
    window.addEventlister('scroll', () => {
        sessionStore.setItem(`${pageID}ScrollTop`)
    })
  1. 跳转到编辑页面的时候恢复滚动位置
    const scrollTop = sessionStore.getItem(`${pageId}ScrollTop`)

缺点:

  1. 只读页面和编辑页面,宽度不一致的时候,就会定位不到正确的位置,比如语雀那样子

方案二:

原理:

  1. 首先取到可视区域中最顶部的dom元素(利用IntersectionObserver
  2. 计算第一步中dom元素,可视区域占总高度的百分比

应用:

const clientRect = targetDom.getBoundingClientRect()

  • 根据第一步中取到的dom元素, 计算元素底部距离顶部的距离:clientRect.y
  • 加上第二步中的百分比,计算出高度,clientRect.height * Number(ratio)
  • 两者相加就是页面应该滚动的距离

实现:

  1. 阅读页

页面滚动的时候记住顶部可见区域的第一个dom元素

截屏2022-01-17 下午4.21.38.png


    // 取出顶部可见区域的第一个dom元素
    let intersectionObserver = new IntersectionObserver(
      function(entries) {
        let matchEntry: IntersectionObserverEntry | null = null
        entries.forEach((entry: IntersectionObserverEntry) => {
          if (entry.boundingClientRect.y < entry.rootBounds!.y) {
            if (!matchEntry) {
              matchEntry = entry
            } else if (entry.time >= matchEntry.time) {
              matchEntry = entry
            }
          }
        })

        // matchEntry 即时目标dom
        // do something
      },
      {
        root: scrollDom,
        rootMargin: '0',
        threshold: [0]
      }
    )

    // 监听子元素
    Array.from(children).forEach(children => {
        intersectionObserver.observe(children)
    })

然后计算dom可视区域的高度占总高度的比例

    const baseTopOffset = 0  //滚动区域距离页面顶部的距离
    const clientRect = targetDom.getBoundingClientRect()
    if (clientRect.bottom > baseTopOffset && clientRect.top < baseTopOffset) {
        const scrollTop = clientRect.y - baseTopOffset
        const ratio = Math.abs(scrollTop) / clientRect.height
    }
  1. 编辑页
    const baseTopOffset = 0 //滚动区域距离顶部的距离
    const clientRect = dom.getBoundingClientRect()
    const top = clientRect.y - baseTopOffset
    const domOffset = clientRect.height * Number(ratio) // 计算出第一步中顶部dom可见高度
    scrollDom.scrollTo(0, top + domOffset)