graphics/webvideo.js

  1. 'use strict';
  2. var Thing = require('./thing.js');
  3. var DEFAULT_WIDTH = 150;
  4. var DEFAULT_HEIGHT = (DEFAULT_WIDTH * 3) / 4;
  5. const WEBCAM_INDICATOR = 'WEBCAM';
  6. /**
  7. * @constructor
  8. * @augments Thing
  9. * @param {string} filename - Filepath to the video
  10. */
  11. function WebVideo(filename) {
  12. if (typeof filename !== 'string') {
  13. throw new TypeError(
  14. 'You must pass a string to <span class="code">' +
  15. "new WebVideo(filename)</span> that has the video's location."
  16. );
  17. }
  18. Thing.call(this);
  19. var self = this;
  20. var vid = document.createElement('video');
  21. this.width = DEFAULT_WIDTH;
  22. this.height = DEFAULT_HEIGHT;
  23. this.type = 'WebVideo';
  24. this.isWebCam = filename === WEBCAM_INDICATOR;
  25. this.browserSupportsVideo = !!vid.canPlayType;
  26. if (this.browserSupportsVideo) {
  27. this.video = vid;
  28. if (!this.isWebCam) {
  29. this.video.src = filename;
  30. } else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  31. navigator.mediaDevices
  32. .getUserMedia({video: true})
  33. .then(function(stream) {
  34. self.video.srcObject = stream;
  35. self.video.play();
  36. })
  37. .catch(function(error) {
  38. throw new Error('Web camera access was denied: ' + error);
  39. });
  40. } else {
  41. throw new TypeError('Your browser does not support web camera access');
  42. }
  43. this.filename = filename;
  44. this.video.autoplay = true;
  45. this.video.loop = false;
  46. // Treat cross origin URLs as same origin. Allows for videos from different
  47. // origins to be loaded and played, as long as that origin allows us to load
  48. // the given video resource.
  49. this.video.crossOrigin = 'anonymous';
  50. }
  51. }
  52. WebVideo.WEBCAM = WEBCAM_INDICATOR;
  53. WebVideo.prototype = new Thing();
  54. WebVideo.prototype.constructor = WebVideo;
  55. /**
  56. * Draws the WebVideo in the canvas.
  57. *
  58. * @param {CodeHSGraphics} __graphics__ - Instance of the __graphics__ module.
  59. */
  60. WebVideo.prototype.draw = function(__graphics__) {
  61. if (this.browserSupportsVideo) {
  62. var context = __graphics__.getContext('2d');
  63. // Scale and translate
  64. // X scale, X scew, Y scew, Y scale, X position, Y position
  65. context.setTransform(1, 0, 0, 1, this.x + this.width / 2, this.y + this.height / 2);
  66. context.rotate(this.rotation);
  67. context.drawImage(this.video, -this.width / 2, -this.height / 2, this.width, this.height);
  68. // Reset transformation matrix
  69. // X scale, X scew, Y scew, Y scale, X position, Y position
  70. context.setTransform(1, 0, 0, 1, 0, 0);
  71. }
  72. };
  73. /**
  74. * Checks if the passed point is contained in the WebVideo.
  75. *
  76. * @param {number} x - The x coordinate of the point being tested.
  77. * @param {number} y - The y coordinate of the point being tested.
  78. * @returns {boolean} Whether the passed point is contained in the WebVideo.
  79. */
  80. WebVideo.prototype.containsPoint = function(x, y) {
  81. if (this.browserSupportsVideo) {
  82. return x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height;
  83. }
  84. return false;
  85. };
  86. /**
  87. * Gets the width of the WebVideo.
  88. *
  89. * @returns {number} Width of the WebVideo.
  90. */
  91. WebVideo.prototype.getWidth = function() {
  92. return this.width;
  93. };
  94. /**
  95. * Gets the height of the WebVideo.
  96. *
  97. * @returns {number} Height of the WebVideo.
  98. */
  99. WebVideo.prototype.getHeight = function() {
  100. return this.height;
  101. };
  102. /**
  103. * Sets the size of the WebVideo.
  104. *
  105. * @param {number} width - The desired width of the resulting WebVideo.
  106. * @param {number} height - The desired height of the resulting WebVideo.
  107. */
  108. WebVideo.prototype.setSize = function(width, height) {
  109. this.width = width;
  110. this.height = height;
  111. };
  112. /**
  113. * Sets whether the WebVideo should start playing automatically once loaded.
  114. *
  115. * @param {boolean} autoplay - True/false whether the video should start playing automatically.
  116. */
  117. WebVideo.prototype.setAutoplay = function(autoplay) {
  118. if (this.browserSupportsVideo) {
  119. this.video.autoplay = autoplay;
  120. }
  121. };
  122. /**
  123. * Sets whether the WebVideo should loop and play again once finished.
  124. *
  125. * @param {boolean} loop - True/false whether the video should loop.
  126. */
  127. WebVideo.prototype.setLoop = function(loop) {
  128. if (this.browserSupportsVideo) {
  129. this.video.loop = loop;
  130. }
  131. };
  132. /**
  133. * Sets whether the WebVideo is muted or not.
  134. *
  135. * @param {boolean} muted - True/false whether the video should be muted.
  136. */
  137. WebVideo.prototype.setMuted = function(muted) {
  138. if (this.browserSupportsVideo) {
  139. this.video.muted = muted;
  140. }
  141. };
  142. /**
  143. * Starts playing the WebVideo.
  144. */
  145. WebVideo.prototype.play = function() {
  146. if (this.browserSupportsVideo) {
  147. this.video.play();
  148. }
  149. };
  150. /**
  151. * Pauses the WebVideo.
  152. */
  153. WebVideo.prototype.pause = function() {
  154. if (this.browserSupportsVideo) {
  155. this.video.pause();
  156. }
  157. };
  158. /**
  159. * Stops the WebVideo.
  160. */
  161. WebVideo.prototype.stop = function() {
  162. if (this.browserSupportsVideo) {
  163. this.video.pause();
  164. this.video.currentTime = 0;
  165. if (this.isWebCam && this.video.srcObject) {
  166. this.video.srcObject.getTracks().forEach(function(track) {
  167. track.stop();
  168. });
  169. }
  170. }
  171. };
  172. /**
  173. * Returns whether the WebVideo is currently playing.
  174. *
  175. * @returns {boolean} True if the video is playing, false if it is not.
  176. */
  177. WebVideo.prototype.isPlaying = function() {
  178. if (this.browserSupportsVideo) {
  179. return !(this.video.paused || this.video.ended);
  180. }
  181. return false;
  182. };
  183. /**
  184. * Returns whether the WebVideo is currently muted.
  185. *
  186. * @returns {boolean} True if the video is muted, false if it is not.
  187. */
  188. WebVideo.prototype.isMuted = function() {
  189. if (this.browserSupportsVideo) {
  190. return this.video.muted;
  191. }
  192. return false;
  193. };
  194. /**
  195. * Defines a function to call once the video has loaded enough and is ready to play.
  196. * @param {Function} fn A function to call when the video is ready to play.
  197. */
  198. WebVideo.prototype.onReadyToPlay = function(fn) {
  199. if (this.browserSupportsVideo) {
  200. this.video.oncanplay = fn;
  201. }
  202. };
  203. module.exports = WebVideo;