0

I'm building a custom video player in React and I'm having trouble aligning the time displayed on hover over the progress bar with the actual seek time used when clicking.

Problem I use an as the progress bar.

On onMouseMove, I calculate the percentage based on event.clientX and show a tooltip (indicadorRef) displaying the estimated time for that position.

The time displayed on hover looks visually correct.

However, when the user clicks (using onChange), the actual seek time does not exactly match the hovered time — usually off by a small fraction of a second.

I've tried rounding values and aligning steps, but small mismatches remain.

Example:

const handleHoverProgress = (event) => {
  if (!isPlayerReady) return;

  const rect = inputProgressRef.current.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const percentage = Math.max(0, Math.min(1, x / rect.width));

  const min = parseFloat(inputProgressRef.current.min);
  const max = parseFloat(inputProgressRef.current.max);
  const step = parseFloat(inputProgressRef.current.step) || 0.001;

  let value = min + percentage * (max - min);
  value = Math.round(value / step) * step;
  value = parseFloat(value);

  indicadorRef.current.textContent = formatTime(value * duration);
  indicadorRef.current.style.visibility = "visible";

  let indicatorX = x - indicadorRef.current.offsetWidth / 2;
  indicatorX = Math.max(0, Math.min(rect.width - indicadorRef.current.offsetWidth, indicatorX));
  indicadorRef.current.style.left = `${indicatorX}px`;
};

ReactPlayer setup:

<ReactPlayer
  ref={playerRef}
  url={currentVideoUrl}
  playing={playing}
  volume={volume}
  onProgress={({ played }) => setPlayed(played)}
  onDuration={setDuration}
  onReady={() => setIsPlayerReady(true)}
  controls={false}
  width="100%"
  height="100%"
  progressInterval={100}
/>

Range input:

<input
  ref={inputProgressRef}
  onMouseMove={handleHoverProgress}
  type="range"
  min={0}
  max={1}
  step={0.001}
  value={played}
  onChange={(e) => handleSeek(parseFloat(e.target.value))}
  className="progress-bar"
/>

What I’ve tried Matching the tooltip value with the seek value by using the same percentage calculation.

Rounding to the nearest step to avoid floating-point issues (e.g., 0.73899999).

Using progressInterval={100} on ReactPlayer for more frequent updates.

The issue Despite all this, the hovered time and the actual seek time don’t perfectly match after clicking. Sometimes it’s off by a small fraction of a second or by one second depending on rounding behavior.

What I’m looking for How can I ensure that the time shown on hover exactly matches the time that the video seeks to when the user clicks?

Technologies React

ReactPlayer

Any help or suggestions are appreciated. Thank you!

enter image description here

2
  • Not to derail you here, but media-chrome player toolkit might make your player build a lot easier: media-chrome.org Commented Jun 22 at 11:10
  • Thanks for the suggestion. I'll definitely keep it in mind for my next project. :) Commented Jun 24 at 11:18

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.