Dmitry Samoylov
Dmitry Samoylov

Reputation: 1318

How to determine if user interacted with document to start video?

I encounter an error trying to autoplay video in Chrome, which says: DOMException: play() failed because the user didn't interact with the document first.

There is a solution for that for 'normal' pages:

var promise = document.querySelector('video').play();
if (promise !== undefined) {
  promise.then(_ => {
    // Autoplay started!
  }).catch(error => {
    // Autoplay was prevented.
    // Show a "Play" button so that user can start playback.
  });
}

But I play video using Phaser framework Video object, which doesn't return promise, so I need to determine it user has interacted with the page before trying to play video. Is there any solution for that?

Upvotes: 10

Views: 4272

Answers (4)

Joseph Markle
Joseph Markle

Reputation: 1


        // Set a flag if the user has interacted because the video can't play before
        useEffect(() => {
          interactionListeners()
        }, [])

        function interactionListeners(){
          window.addEventListener("click", setInteractedFunction)
          window.addEventListener("scroll", setInteractedFunction)
        }
        function removeInteractionListeners(){
          window.removeEventListener("click", setInteractedFunction)
          window.removeEventListener("scroll", setInteractedFunction)
        }
        function setInteractedFunction(){
          console.log("setting interacted")
          if(!interacted)
            dispatcher(setInteracted(true))
          removeInteractionListeners()
        }

Upvotes: 0

Paurush Sinha
Paurush Sinha

Reputation: 165

window.onFocus

You can use this method to call an event when the tab is focused using JavaScript.

window.onFocus = function(){
playVideo(); //A dummy function
}

mousemove

You can check mouse movement.

document.addEventListener('mousemove', playVideo);

keydown

You can check if user has pressed a key

document.addEventListener('keydown', playVideo);

I think, these events must be enough to check if user has interacted with your site and call a method.

Upvotes: 0

William Guerrand
William Guerrand

Reputation: 31

I'm not satisfied with the responses to this kind of question so here's my take / solution. Keep in mind this uses React but can also be done natively.

(1) Add event listeners

  const [userInteracted, setUserInteracted] = useState(false)

  useEffect(() => {
    const handleInteraction = (event) => { setUserInteracted(true); console.log(`Event log for: ${event}`); }
  
    document.addEventListener('click', handleInteraction, true)
    document.addEventListener('scroll', handleInteraction, true)
  
    return () => {
      document.removeEventListener('click', handleInteraction('click'))
      document.removeEventListener('scroll', handleInteraction('scroll'))
    }
  }, [])

(2) Use native browser detection object

  if (navigator.userActivation.hasBeenActive) { doSomething() }

I personally use this on a div which plays audio when hovered over:

const App = () => {
  const [userInteracted, setUserInteracted] = useState(false)
  const audioRef = useRef(new Audio(BirdSinging))

  const playAudio = () => { if (audioRef.current && userInteracted && navigator.userActivation.hasBeenActive) audioRef.current.play() }

  const stopAudio = () => {
    if (audioRef.current && userInteracted) {
      audioRef.current.pause()
      audioRef.current.currentTime = 0
    }
  }

  // avoids play() failed because the user didn't interact with the document first
  useEffect(() => {
    const handleInteraction = (thing) => { setUserInteracted(true); console.log(thing); }
  
    document.addEventListener('click', handleInteraction, true)
    document.addEventListener('scroll', handleInteraction, true)
  
    return () => {
      document.removeEventListener('click', handleInteraction('clik'))
      document.removeEventListener('scroll', handleInteraction('scr'))
    }
  }, [])

  useEffect(() => {
    return () => {
      audioRef.current.pause()
    }
  }, [])

  return (
    <div className="logo" onMouseEnter={playAudio} onMouseLeave={stopAudio}>
      <img src={Logo} alt="Logo" />
    </div>
  )
}

Upvotes: 3

Dinesh Penugonda
Dinesh Penugonda

Reputation: 121

Look for user interaction with the window

var interacted = false;
function fun(){
   interacted = true;
   $(window).unbind("scroll");
   $(window).unbind("click");
   play();
}
$(window).bind("scroll click", fun);
function play(){
     if(interacted){
        //play audio or video
     }
}

Upvotes: 2

Related Questions