4/11/2022 ∙ 3 minuty czytania

banner

Czas i postęp czytania ⏱

Wiele stron zawiera funkcjonalność estymującą czas czytania tekstu oraz pokazuje, ile tekstu zdążyliśmy już przeczytać. Dzisiaj zaimplementujemy obie te funkcjonalności.

Estymacja tego, ile zajmie czytanie

Aby prawidłowo określić, ile czasu zajmuje czytanie tekstu przykładowo w minutach, wystarczy określić, jaki jest średni czas czytania tekstu na minutę, a następnie podzielić ilość słów w tekście przez tę wartość. Możemy napisać własną funkcję, która się tym zajmuje, ale jest kilka dodatkowych elementów o których należy pamiętać jak np.:

dlatego skorzystamy z gotowej paczki: reading-time do której przekazujemy tekst. W wyniku działania funkcji zostanie zwrócony obiekt o następującym typie:

type ReadingTimeResults = {
  minutes: number
  time: number
  words: WordCountStats
}

z obiektu wyciągamy minuty, a następnie pokazujemy w tekście ile czasu zajmuje czytanie.

Postęp czytania

Na niektórych stronach można zobaczyć cienki pasek postępu czytania na samej górze strony reagujący na wydarzenie przewijania tekstu na stronie. Możemy w prosty sposób skopiować dane zachowanie pisząc następujący fragment kodu:

// components/Progress.tsx
import { Indicator as RawIndicator, Root } from '@radix-ui/react-progress'
import { motion, useTransform, useViewportScroll } from 'framer-motion'
import { useEffect, useState } from 'react'

const Indicator = motion(RawIndicator)

export const Progress = () => {
  const [progress, setProgress] = useState(0)
  const { scrollYProgress } = useViewportScroll()
  const y = useTransform(scrollYProgress, [0, 1], [0, 100])

  useEffect(() => {
    const unsubscribe = y.onChange(setProgress)

    return unsubscribe
  }, [y])

  return (
    <Root className="fixed top-0 right-0 left-0" value={progress}>
      <Indicator
        className="h-2 bg-indigo-500"
        style={{ width: `${progress}%` }}
      />
    </Root>
  )
}

Rozbijmy kod na czynniki pierwsze i przeanalizujmy co się tutaj właściwie dzieje:

Importy

import { Indicator as RawIndicator, Root } from '@radix-ui/react-progress'
import { motion, useTransform, useViewportScroll } from 'framer-motion'

Wiązanie przewijania tekstu z postępem czytania

const [progress, setProgress] = useState(0)
const { scrollYProgress } = useViewportScroll()
const y = useTransform(scrollYProgress, [0, 1], [0, 100])

useEffect(() => {
  const unsubscribe = y.onChange(setProgress)

  return unsubscribe
}, [y])

Komponent postępu czytania

<Root className="fixed top-0 right-0 left-0" value={progress}>
  <Indicator className="h-2 bg-indigo-500" style={{ width: `${progress}%` }} />
</Root>

W drzewie DOM możemy zobaczyć, że dzięki zastosowaniu ww. komponentów wyrenderowane zostały atrybuty aria oraz data przydatne dla technologi wspomagających.

exit

Poniżej znajdziesz więcej postów, które mogą Cię zainteresować.