voronianski / swipe-js-iso

Universal (a.k.a isomorphic) version of Swipe.js
https://www.npmjs.com/package/swipe-js-iso
MIT License
187 stars 57 forks source link

Can't trigger audio/video .play on swipe #38

Closed jamesarosen closed 2 years ago

jamesarosen commented 2 years ago

Use-case

Play a video when the user swipes to it

Example Code

Swipe(document.getElementById('slider'), {
  callback: (i, el) => {
    const video = el.querySelector('video')
    if (video) { video.play() }
  }
});

Problem

Some browsers, notably Mobile Safari, throw a NotAllowedError if a script tries to call video.play() (or audio.play()) in a context that is not directly tied to a user action.

See Safari HTML5 Audio and Video Guide > iOS-Specific Considerations

Cause

I believe the problem is that swipe-js wraps callback in a setTimeout(callback, 0), which breaks the connection to the original event handling. This causes the browser to believe callback (and thus play()) is not called because of a user action.

jamesarosen commented 2 years ago

I tried changing

var offloadFn = function(fn) {
  setTimeout(fn || noop, 0);
}; // offload a functions execution

to

var offloadFn = function(fn) {
  (fn || noop)();
}; // offload a functions execution

locally to test this. The NotAllowedError remains. I reject my previous hypothesis.

My new hypothesis is that a touchend event cannot trigger play() on these devices.