@@ -37,6 +37,9 @@ declare global {
3737 interface Window { YT : typeof YT | undefined ; }
3838}
3939
40+ export const DEFAULT_PLAYER_WIDTH = 640 ;
41+ export const DEFAULT_PLAYER_HEIGHT = 390 ;
42+
4043// The native YT.Player doesn't expose the set videoId, but we need it for
4144// convenience.
4245interface Player extends YT . Player {
@@ -71,6 +74,29 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy {
7174
7275 private _videoId = new EventEmitter < string | undefined > ( ) ;
7376
77+ /** Height of video player */
78+ get height ( ) : number | undefined {
79+ return this . _height ;
80+ }
81+
82+ @Input ( ) set height ( height : number | undefined ) {
83+ this . _height = height || DEFAULT_PLAYER_HEIGHT ;
84+ this . _heightObs . emit ( this . _height ) ;
85+ }
86+ private _height = DEFAULT_PLAYER_HEIGHT ;
87+ private _heightObs = new EventEmitter < number > ( ) ;
88+
89+ /** Width of video player */
90+ get width ( ) : number | undefined {
91+ return this . _width ;
92+ }
93+ @Input ( ) set width ( width : number | undefined ) {
94+ this . _width = width || DEFAULT_PLAYER_WIDTH ;
95+ this . _widthObs . emit ( this . _width ) ;
96+ }
97+ private _width = DEFAULT_PLAYER_WIDTH ;
98+ private _widthObs = new EventEmitter < number > ( ) ;
99+
74100 /** The element that will be replaced by the iframe. */
75101 @ViewChild ( 'youtube_container' , { static : false } ) youtubeContainer : ElementRef | undefined ;
76102 private _youtubeContainer = new EventEmitter < HTMLElement > ( ) ;
@@ -84,17 +110,24 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy {
84110 'Please install the YouTube Player API Reference for iframe Embeds: ' +
85111 'https://developers.google.com/youtube/iframe_api_reference' ) ;
86112 }
113+ // Add initial values to all of the inputs.
114+ const widthObs = this . _widthObs . pipe ( startWith ( this . _width ) ) ;
115+ const heightObs = this . _heightObs . pipe ( startWith ( this . _height ) ) ;
87116
88117 /** An observable of the currently loaded player. */
89118 const playerObs =
90119 createPlayerObservable (
91120 this . _youtubeContainer ,
92121 this . _videoId ,
122+ widthObs ,
123+ heightObs ,
93124 ) . pipe ( waitUntilReady ( ) , takeUntil ( this . _destroyed ) , publish ( ) ) ;
94125
95126 /** Set up side effects to bind inputs to the player. */
96127 playerObs . subscribe ( player => this . _player = player ) ;
97128
129+ bindSizeToPlayer ( playerObs , widthObs , heightObs ) ;
130+
98131 bindCueVideoCall ( playerObs , this . _videoId , this . _destroyed ) ;
99132
100133 // After all of the subscriptions are set up, connect the observable.
@@ -117,6 +150,15 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy {
117150 }
118151}
119152
153+ function bindSizeToPlayer (
154+ playerObs : Observable < YT . Player | undefined > ,
155+ widthObs : Observable < number > ,
156+ heightObs : Observable < number >
157+ ) {
158+ return combineLatest ( playerObs , widthObs , heightObs )
159+ . subscribe ( ( [ player , width , height ] ) => player && player . setSize ( width , height ) ) ;
160+ }
161+
120162/**
121163 * Returns an observable that emits the loaded player once it's ready. Certain properties/methods
122164 * won't be available until the iframe finishes loading.
@@ -161,12 +203,15 @@ function fromPlayerOnReady(player: UninitializedPlayer): Observable<Player> {
161203function createPlayerObservable (
162204 youtubeContainer : Observable < HTMLElement > ,
163205 videoIdObs : Observable < string | undefined > ,
206+ widthObs : Observable < number > ,
207+ heightObs : Observable < number > ,
164208) : Observable < UninitializedPlayer | undefined > {
165209
166210 const playerOptions =
167211 videoIdObs
168212 . pipe (
169- map ( ( videoId ) => videoId ? { videoId} : undefined ) ,
213+ withLatestFrom ( combineLatest ( widthObs , heightObs ) ) ,
214+ map ( ( [ videoId , [ width , height ] ] ) => videoId ? ( { videoId, width, height} ) : undefined ) ,
170215 ) ;
171216
172217 return combineLatest ( youtubeContainer , playerOptions )
0 commit comments