Reputation: 1318
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
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
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
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
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