在下次访问时恢复动态内容中的读取位置

时间:2019-04-05 20:27:24

标签: javascript reactjs

我有一本书的很大一章可供用户阅读。章节可以具有任何字体大小。窗口可以是任何大小。如何在数据库中文本的正确位置(当前可见窗口的顶部)保存确切的位置,所以当用户继续从任何设备阅读本章时,我可以将其滚动到那里?

我尝试使用window.pageYOffset,然后尝试滚动位置的百分比,但是它对于动态窗口和字体大小并不准确,并且只能在相同的环境(字体大小,窗口大小)中工作。

我现在唯一的想法是将本章分成几行:

const lines = (chapter.match(/\r?\n/g) || '').length + 1

然后以某种方式找到当前可见窗口最上方的一行,保存其编号,并在加载时滚动到该行。

作为替代方案,也许可以提供一些当前最可见的html元素,以便我坚持下去。

有什么想法吗?

更新:现在,我正在尝试获取内容div的父级中的所有元素,并通过它们进行迭代以使用getBoundingClientRect()获取元素在视口中的位置。我对此有希望。

1 个答案:

答案 0 :(得分:0)

首先,您获得了一组段落

let children = Array.from(contentRef.current.children)

他们对最接近零(可见屏幕顶部)的段落进行二进制搜索。

let closestIndex = binaryClosest(
  children,
  target => 0 - target.getBoundingClientRect().y
)

localStorage.setItem('index', closestIndex)

function binaryClosest(a, compare) {
  let i = binarySearch()
  if (i === 0) return 0
  if (i === a.length) return i - 1
  let d1 = -compare(a[i]),
    d2 = compare(a[i - 1])
  return d1 < d2 ? i : i - 1

  function binarySearch() {
    let le = 0,
      ri = a.length - 1
    while (le <= ri) {
      let mid = (le + ri) >> 1,
        cmp = compare(a[mid])
      if (cmp > 0) {
        le = mid + 1
      } else if (cmp < 0) {
        ri = mid - 1
      } else {
        return mid
      }
    }
    return le
  }
}

现在,您可以将此closetIndex保存在数据库中,并在下次加载时滚动至该索引:

let children = Array.from(contentRef.current.children)

window.scrollTo(0, children[localStorage.getItem('index')].offsetTop)