@@ -37,6 +37,9 @@ declare global {
37
37
interface Window { YT : typeof YT | undefined ; }
38
38
}
39
39
40
+ export const DEFAULT_PLAYER_WIDTH = 640 ;
41
+ export const DEFAULT_PLAYER_HEIGHT = 390 ;
42
+
40
43
// The native YT.Player doesn't expose the set videoId, but we need it for
41
44
// convenience.
42
45
interface Player extends YT . Player {
@@ -71,6 +74,29 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy {
71
74
72
75
private _videoId = new EventEmitter < string | undefined > ( ) ;
73
76
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
+
74
100
/** The element that will be replaced by the iframe. */
75
101
@ViewChild ( 'youtube_container' , { static : false } ) youtubeContainer : ElementRef | undefined ;
76
102
private _youtubeContainer = new EventEmitter < HTMLElement > ( ) ;
@@ -84,17 +110,24 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy {
84
110
'Please install the YouTube Player API Reference for iframe Embeds: ' +
85
111
'https://developers.google.com/youtube/iframe_api_reference' ) ;
86
112
}
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 ) ) ;
87
116
88
117
/** An observable of the currently loaded player. */
89
118
const playerObs =
90
119
createPlayerObservable (
91
120
this . _youtubeContainer ,
92
121
this . _videoId ,
122
+ widthObs ,
123
+ heightObs ,
93
124
) . pipe ( waitUntilReady ( ) , takeUntil ( this . _destroyed ) , publish ( ) ) ;
94
125
95
126
/** Set up side effects to bind inputs to the player. */
96
127
playerObs . subscribe ( player => this . _player = player ) ;
97
128
129
+ bindSizeToPlayer ( playerObs , widthObs , heightObs ) ;
130
+
98
131
bindCueVideoCall ( playerObs , this . _videoId , this . _destroyed ) ;
99
132
100
133
// After all of the subscriptions are set up, connect the observable.
@@ -117,6 +150,16 @@ export class YouTubePlayer implements AfterViewInit, OnDestroy {
117
150
}
118
151
}
119
152
153
+ /** Listens to changes to the given width and height and sets it on the player. */
154
+ function bindSizeToPlayer (
155
+ playerObs : Observable < YT . Player | undefined > ,
156
+ widthObs : Observable < number > ,
157
+ heightObs : Observable < number >
158
+ ) {
159
+ return combineLatest ( playerObs , widthObs , heightObs )
160
+ . subscribe ( ( [ player , width , height ] ) => player && player . setSize ( width , height ) ) ;
161
+ }
162
+
120
163
/**
121
164
* Returns an observable that emits the loaded player once it's ready. Certain properties/methods
122
165
* won't be available until the iframe finishes loading.
@@ -161,12 +204,15 @@ function fromPlayerOnReady(player: UninitializedPlayer): Observable<Player> {
161
204
function createPlayerObservable (
162
205
youtubeContainer : Observable < HTMLElement > ,
163
206
videoIdObs : Observable < string | undefined > ,
207
+ widthObs : Observable < number > ,
208
+ heightObs : Observable < number > ,
164
209
) : Observable < UninitializedPlayer | undefined > {
165
210
166
211
const playerOptions =
167
212
videoIdObs
168
213
. pipe (
169
- map ( ( videoId ) => videoId ? { videoId} : undefined ) ,
214
+ withLatestFrom ( combineLatest ( widthObs , heightObs ) ) ,
215
+ map ( ( [ videoId , [ width , height ] ] ) => videoId ? ( { videoId, width, height} ) : undefined ) ,
170
216
) ;
171
217
172
218
return combineLatest ( youtubeContainer , playerOptions )
0 commit comments