Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bind:currentTime and bind:duration for media elements #406

Closed
Rich-Harris opened this issue Mar 26, 2017 · 1 comment
Closed

bind:currentTime and bind:duration for media elements #406

Rich-Harris opened this issue Mar 26, 2017 · 1 comment

Comments

@Rich-Harris
Copy link
Member

This might be fairly niche, but I've had to implement custom controls for audio and video elements a lot of times, and it's always a bit finicky. In particular, the timeupdate event fires surprisingly infrequently during playback, meaning your progress bar (or whatever else is synced to the currentTime) moves in a choppy fashion.

I'd love to be able to just do this:

<audio bind:currentTime='time' bind:duration src='thing.mp3'/>
<Controls
  :time
  :duration
  on:play='refs.audio.play()' 
  on:pause='refs.audio.pause()' 
/>

(The refs.audio.play() thing is made up, I couldn't be bothered to write the relevant <script>. But maybe we should do that too...)

Binding to currentTime would add something like this:

function audioCurrentTimeUpdate () {
  if ( audio.playing ) requestAnimationFrame( audioCurrentTimeUpdate );
  component.set({ time: audio.currentTime }); // mutatis mutandis inside each-blocks
}

audio.addEventListener( 'play', audioCurrentTimeUpdate );
audio.addEventListener( 'timeupdate', audioCurrentTimeUpdate );

(The timeupdate listener is still necessary, since it's possible for currentTime to be affected externally, e.g. if it has built-in controls that the user drags.)

bind:duration would presumably look something like this...

audio.addEventListener( 'durationchange', function () {
  component.set({ duration: this.duration });
});

...except in dev mode, where we can write code that reflects its read-only nature:

let duration_updating = false;

audio.addEventListener( 'durationchange', function () {
  duration_updating = true;
  component.set({ duration: this.duration });
  duration_updating = false;
});

component.observe( 'duration', function () {
  if ( !duration_updating ) {
    throw new Error( '<audio> duration is read-only' );
  }
});

Not a super high priority, just something that would add a touch of delight when developing these sorts of apps.

Rich-Harris added a commit that referenced this issue Apr 19, 2017
Rich-Harris added a commit that referenced this issue Apr 19, 2017
Implement media element bindings
@Rich-Harris
Copy link
Member Author

Implemented in 1.17:

https://svelte.technology/repl?version=1.17.0&example=binding-media-elements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant