Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

FilmStrip.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /* global $, interfaceConfig */
  2. import UIEvents from "../../../service/UI/UIEvents";
  3. import UIUtil from "../util/UIUtil";
  4. const FilmStrip = {
  5. /**
  6. *
  7. * @param eventEmitter the {EventEmitter} through which {FilmStrip} is to
  8. * emit/fire {UIEvents} (such as {UIEvents.TOGGLED_FILM_STRIP}).
  9. */
  10. init (eventEmitter) {
  11. this.iconMenuDownClassName = 'icon-menu-down';
  12. this.iconMenuUpClassName = 'icon-menu-up';
  13. this.filmStrip = $('#remoteVideos');
  14. this.eventEmitter = eventEmitter;
  15. this._initFilmStripToolbar();
  16. this.registerListeners();
  17. },
  18. /**
  19. * Initializes the filmstrip toolbar
  20. */
  21. _initFilmStripToolbar() {
  22. let toolbar = this._generateFilmStripToolbar();
  23. let container = document.querySelector('.filmstrip');
  24. UIUtil.prependChild(container, toolbar);
  25. let iconSelector = '#hideVideoToolbar i';
  26. this.toggleFilmStripIcon = document.querySelector(iconSelector);
  27. },
  28. /**
  29. * Generates HTML layout for filmstrip toolbar
  30. * @returns {HTMLElement}
  31. * @private
  32. */
  33. _generateFilmStripToolbar() {
  34. let container = document.createElement('div');
  35. let isVisible = this.isFilmStripVisible();
  36. container.className = 'filmstrip__toolbar';
  37. container.innerHTML = `
  38. <button id="hideVideoToolbar">
  39. <i class="icon-menu-${isVisible ? 'down' : 'up'}">
  40. </i>
  41. </button>
  42. `;
  43. return container;
  44. },
  45. /**
  46. * Attach 'click' listener to "hide filmstrip" button
  47. */
  48. registerListeners() {
  49. let toggleFilmstripMethod = this.toggleFilmStrip.bind(this);
  50. let selector = '#hideVideoToolbar';
  51. $('#videospace').on('click', selector, toggleFilmstripMethod);
  52. },
  53. /**
  54. * Changes classes of icon for showing down state
  55. */
  56. showMenuDownIcon() {
  57. let icon = this.toggleFilmStripIcon;
  58. icon.classList.add(this.iconMenuDownClassName);
  59. icon.classList.remove(this.iconMenuUpClassName);
  60. },
  61. /**
  62. * Changes classes of icon for showing up state
  63. */
  64. showMenuUpIcon() {
  65. let icon = this.toggleFilmStripIcon;
  66. icon.classList.add(this.iconMenuUpClassName);
  67. icon.classList.remove(this.iconMenuDownClassName);
  68. },
  69. /**
  70. * Toggles the visibility of the film strip.
  71. *
  72. * @param visible optional {Boolean} which specifies the desired visibility
  73. * of the film strip. If not specified, the visibility will be flipped
  74. * (i.e. toggled); otherwise, the visibility will be set to the specified
  75. * value.
  76. */
  77. toggleFilmStrip(visible) {
  78. let isVisibleDefined = typeof visible === 'boolean';
  79. if (!isVisibleDefined) {
  80. visible = this.isFilmStripVisible();
  81. } else if (this.isFilmStripVisible() === visible) {
  82. return;
  83. }
  84. this.filmStrip.toggleClass("hidden");
  85. if (!visible) {
  86. this.showMenuDownIcon();
  87. } else {
  88. this.showMenuUpIcon();
  89. }
  90. // Emit/fire UIEvents.TOGGLED_FILM_STRIP.
  91. var eventEmitter = this.eventEmitter;
  92. if (eventEmitter) {
  93. eventEmitter.emit(
  94. UIEvents.TOGGLED_FILM_STRIP,
  95. this.isFilmStripVisible());
  96. }
  97. },
  98. /**
  99. * Shows if filmstrip is visible
  100. * @returns {boolean}
  101. */
  102. isFilmStripVisible() {
  103. return !this.filmStrip.hasClass('hidden');
  104. },
  105. setupFilmStripOnly() {
  106. this.filmStrip.css({
  107. padding: "0px 0px 18px 0px",
  108. right: 0
  109. });
  110. },
  111. /**
  112. * Returns the height of filmstrip
  113. * @returns {number} height
  114. */
  115. getFilmStripHeight() {
  116. if (this.isFilmStripVisible()) {
  117. return this.filmStrip.outerHeight();
  118. } else {
  119. return 0;
  120. }
  121. },
  122. /**
  123. * Returns the width of filmstip
  124. * @returns {number} width
  125. */
  126. getFilmStripWidth() {
  127. return this.filmStrip.innerWidth()
  128. - parseInt(this.filmStrip.css('paddingLeft'), 10)
  129. - parseInt(this.filmStrip.css('paddingRight'), 10);
  130. },
  131. /**
  132. * Calculates the size for thumbnails: local and remote one
  133. * @returns {*|{localVideo, remoteVideo}}
  134. */
  135. calculateThumbnailSize() {
  136. let availableSizes = this.calculateAvailableSize();
  137. let width = availableSizes.availableWidth;
  138. let height = availableSizes.availableHeight;
  139. return this.calculateThumbnailSizeFromAvailable(width, height);
  140. },
  141. /**
  142. * Normalizes local and remote thumbnail ratios
  143. */
  144. normalizeThumbnailRatio() {
  145. let remoteHeightRatio = interfaceConfig.REMOTE_THUMBNAIL_RATIO_HEIGHT;
  146. let remoteWidthRatio = interfaceConfig.REMOTE_THUMBNAIL_RATIO_WIDTH;
  147. let localHeightRatio = interfaceConfig.LOCAL_THUMBNAIL_RATIO_HEIGHT;
  148. let localWidthRatio = interfaceConfig.LOCAL_THUMBNAIL_RATIO_WIDTH;
  149. let commonHeightRatio = remoteHeightRatio * localHeightRatio;
  150. let localRatioCoefficient = localWidthRatio / localHeightRatio;
  151. let remoteRatioCoefficient = remoteWidthRatio / remoteHeightRatio;
  152. remoteWidthRatio = commonHeightRatio * remoteRatioCoefficient;
  153. remoteHeightRatio = commonHeightRatio;
  154. localWidthRatio = commonHeightRatio * localRatioCoefficient;
  155. localHeightRatio = commonHeightRatio;
  156. let localRatio = {
  157. widthRatio: localWidthRatio,
  158. heightRatio: localHeightRatio
  159. };
  160. let remoteRatio = {
  161. widthRatio: remoteWidthRatio,
  162. heightRatio: remoteHeightRatio
  163. };
  164. return { localRatio, remoteRatio };
  165. },
  166. /**
  167. * Calculates available size for one thumbnail according to
  168. * the current window size
  169. * @returns {{availableWidth: number, availableHeight: number}}
  170. */
  171. calculateAvailableSize() {
  172. let availableHeight = interfaceConfig.FILM_STRIP_MAX_HEIGHT;
  173. let thumbs = this.getThumbs(true);
  174. let numvids = thumbs.remoteThumbs.length;
  175. let localVideoContainer = $("#localVideoContainer");
  176. /**
  177. * If the videoAreaAvailableWidth is set we use this one to calculate
  178. * the filmStrip width, because we're probably in a state where the
  179. * film strip size hasn't been updated yet, but it will be.
  180. */
  181. let videoAreaAvailableWidth
  182. = UIUtil.getAvailableVideoWidth()
  183. - UIUtil.parseCssInt(this.filmStrip.css('right'), 10)
  184. - UIUtil.parseCssInt(this.filmStrip.css('paddingLeft'), 10)
  185. - UIUtil.parseCssInt(this.filmStrip.css('paddingRight'), 10)
  186. - UIUtil.parseCssInt(this.filmStrip.css('borderLeftWidth'), 10)
  187. - UIUtil.parseCssInt(this.filmStrip.css('borderRightWidth'), 10)
  188. - 5;
  189. let availableWidth = videoAreaAvailableWidth;
  190. // If local thumb is not hidden
  191. if(thumbs.localThumb) {
  192. availableWidth = Math.floor(
  193. (videoAreaAvailableWidth - (
  194. UIUtil.parseCssInt(
  195. localVideoContainer.css('borderLeftWidth'), 10)
  196. + UIUtil.parseCssInt(
  197. localVideoContainer.css('borderRightWidth'), 10)
  198. + UIUtil.parseCssInt(
  199. localVideoContainer.css('paddingLeft'), 10)
  200. + UIUtil.parseCssInt(
  201. localVideoContainer.css('paddingRight'), 10)
  202. + UIUtil.parseCssInt(
  203. localVideoContainer.css('marginLeft'), 10)
  204. + UIUtil.parseCssInt(
  205. localVideoContainer.css('marginRight'), 10)))
  206. );
  207. }
  208. // If the number of videos is 0 or undefined we don't need to calculate
  209. // further.
  210. if (numvids) {
  211. let remoteVideoContainer = thumbs.remoteThumbs.eq(0);
  212. availableWidth = Math.floor(
  213. (videoAreaAvailableWidth - numvids * (
  214. UIUtil.parseCssInt(
  215. remoteVideoContainer.css('borderLeftWidth'), 10)
  216. + UIUtil.parseCssInt(
  217. remoteVideoContainer.css('borderRightWidth'), 10)
  218. + UIUtil.parseCssInt(
  219. remoteVideoContainer.css('paddingLeft'), 10)
  220. + UIUtil.parseCssInt(
  221. remoteVideoContainer.css('paddingRight'), 10)
  222. + UIUtil.parseCssInt(
  223. remoteVideoContainer.css('marginLeft'), 10)
  224. + UIUtil.parseCssInt(
  225. remoteVideoContainer.css('marginRight'), 10)))
  226. );
  227. }
  228. let maxHeight
  229. // If the MAX_HEIGHT property hasn't been specified
  230. // we have the static value.
  231. = Math.min(interfaceConfig.FILM_STRIP_MAX_HEIGHT || 120,
  232. availableHeight);
  233. availableHeight
  234. = Math.min(maxHeight, window.innerHeight - 18);
  235. return { availableWidth, availableHeight };
  236. },
  237. /**
  238. * Takes the available size for thumbnail and calculates
  239. * final size of thumbnails
  240. * @param availableWidth
  241. * @param availableHeight
  242. * @returns {{localVideo, remoteVideo}}
  243. */
  244. calculateThumbnailSizeFromAvailable(availableWidth, availableHeight) {
  245. let { localRatio, remoteRatio } = this.normalizeThumbnailRatio();
  246. let { remoteThumbs } = this.getThumbs(true);
  247. let remoteProportion = remoteRatio.widthRatio * remoteThumbs.length;
  248. let widthProportion = remoteProportion + localRatio.widthRatio;
  249. let heightUnit = availableHeight / localRatio.heightRatio;
  250. let widthUnit = availableWidth / widthProportion;
  251. if (heightUnit < widthUnit) {
  252. widthUnit = heightUnit;
  253. }
  254. else
  255. heightUnit = widthUnit;
  256. let localVideo = {
  257. thumbWidth: widthUnit * localRatio.widthRatio,
  258. thumbHeight: heightUnit * localRatio.heightRatio
  259. };
  260. let remoteVideo = {
  261. thumbWidth: widthUnit * remoteRatio.widthRatio,
  262. thumbHeight: widthUnit * remoteRatio.heightRatio
  263. };
  264. return {
  265. localVideo,
  266. remoteVideo
  267. };
  268. },
  269. /**
  270. * Resizes thumbnails
  271. * @param local
  272. * @param remote
  273. * @param animate
  274. * @param forceUpdate
  275. * @returns {Promise}
  276. */
  277. resizeThumbnails(local, remote,
  278. animate = false, forceUpdate = false) {
  279. return new Promise(resolve => {
  280. let thumbs = this.getThumbs(!forceUpdate);
  281. if(thumbs.localThumb)
  282. thumbs.localThumb.animate({
  283. height: local.thumbHeight,
  284. width: local.thumbWidth
  285. }, {
  286. queue: false,
  287. duration: animate ? 500 : 0,
  288. complete: resolve
  289. });
  290. if(thumbs.remoteThumbs)
  291. thumbs.remoteThumbs.animate({
  292. height: remote.thumbHeight,
  293. width: remote.thumbWidth
  294. }, {
  295. queue: false,
  296. duration: animate ? 500 : 0,
  297. complete: resolve
  298. });
  299. this.filmStrip.animate({
  300. // adds 2 px because of small video 1px border
  301. height: remote.thumbHeight + 2
  302. }, {
  303. queue: false,
  304. duration: animate ? 500 : 0
  305. });
  306. if (!animate) {
  307. resolve();
  308. }
  309. });
  310. },
  311. /**
  312. * Returns thumbnails of the filmstrip
  313. * @param only_visible
  314. * @returns {object} thumbnails
  315. */
  316. getThumbs(only_visible = false) {
  317. let selector = 'span';
  318. if (only_visible) {
  319. selector += ':visible';
  320. }
  321. let localThumb = $("#localVideoContainer");
  322. let remoteThumbs = this.filmStrip.children(selector)
  323. .not("#localVideoContainer");
  324. // Exclude the local video container if it has been hidden.
  325. if (localThumb.hasClass("hidden")) {
  326. return { remoteThumbs };
  327. } else {
  328. return { remoteThumbs, localThumb };
  329. }
  330. }
  331. };
  332. export default FilmStrip;