javascript - 下次访问时恢复动态内容中的阅读位置

标签 javascript reactjs

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

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

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

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

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

作为替代方案,也许可以为我提供当前最可见的 html 元素,以便我坚持使用它。

有什么想法吗?

更新:现在我正在尝试获取内容 div 的父级中的所有元素,并使用 getBoundingClientRect() 遍历它们以获取元素在视口(viewport)中的位置>。我对此抱有希望。

最佳答案

首先你得到段落数组

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
  }
}

现在您可以将这个 closestIndex 保存在数据库中,并在下次加载时滚动到它:

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

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

关于javascript - 下次访问时恢复动态内容中的阅读位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55542893/

相关文章:

javascript - 如何从 randomuser API 获取用户的用户详细信息?

javascript - 编译失败。找不到模块 : Can't resolve 'react-router-dom'

javascript - 移除 componentDidMount 上的 backgroundImage

javascript - 无法将单击事件添加到创建对象后才创建的按钮

javascript - 如何使用 Chart.js 更改图表的宽度

javascript - Bootstrap - 多个可忽略的警报

reactjs - 混合内容与 heroku 服务器

javascript - md-checkbox 的行为类似于单选按钮 - AngularJS

javascript - 如何将提供程序添加到 Angular 2 中的服务类?

reactjs - window.location.replace() 的 React 版本?