var BaseTexture = require('./BaseTexture'), Texture = require('./Texture'), utils = require('../utils'); /** * A texture of a [playing] Video. * * See the ["deus" demo](http://www.goodboydigital.com/pixijs/examples/deus/). * * @class * @extends BaseTexture * @namespace PIXI * @param source {HTMLVideoElement} * @param [scaleMode] {number} See {@link scaleModes} for possible values */ function VideoTexture(source, scaleMode) { if (!source){ throw new Error('No video source element specified.'); } // hook in here to check if video is already available. // BaseTexture looks for a source.complete boolean, plus width & height. if ((source.readyState === source.HAVE_ENOUGH_DATA || source.readyState === source.HAVE_FUTURE_DATA) && source.width && source.height) { source.complete = true; } BaseTexture.call(this, source, scaleMode); this.autoUpdate = false; this.updateBound = this._onUpdate.bind(this); if (!source.complete) { this._onCanPlay = this.onCanPlay.bind(this); source.addEventListener('canplay', this._onCanPlay); source.addEventListener('canplaythrough', this._onCanPlay); // started playing.. source.addEventListener('play', this.onPlayStart.bind(this)); source.addEventListener('pause', this.onPlayStop.bind(this)); } } VideoTexture.prototype = Object.create(BaseTexture.prototype); VideoTexture.prototype.constructor = VideoTexture; module.exports = VideoTexture; VideoTexture.prototype._onUpdate = function () { if (this.autoUpdate) { window.requestAnimationFrame(this.updateBound); this.dirty(); } }; VideoTexture.prototype.onPlayStart = function () { if (!this.autoUpdate) { window.requestAnimationFrame(this.updateBound); this.autoUpdate = true; } }; VideoTexture.prototype.onPlayStop = function () { this.autoUpdate = false; }; VideoTexture.prototype.onCanPlay = function () { if (event.type === 'canplaythrough') { this.hasLoaded = true; if (this.source) { this.source.removeEventListener('canplay', this._onCanPlay); this.source.removeEventListener('canplaythrough', this._onCanPlay); this.width = this.source.videoWidth; this.height = this.source.videoHeight; // prevent multiple loaded dispatches.. if (!this.__loaded){ this.__loaded = true; this.dispatchEvent({ type: 'loaded', content: this }); } } } }; VideoTexture.prototype.destroy = function () { if (this.source && this.source._pixiId) { utils.BaseTextureCache[ this.source._pixiId ] = null; delete utils.BaseTextureCache[ this.source._pixiId ]; this.source._pixiId = null; delete this.source._pixiId; } BaseTexture.prototype.destroy.call(this); }; /** * Mimic Pixi BaseTexture.from.... method. * * @static * @param video {HTMLVideoElement} * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values * @return {VideoTexture} */ VideoTexture.baseTextureFromVideo = function (video, scaleMode) { if (!video._pixiId) { video._pixiId = 'video_' + utils.TextureCacheIdGenerator++; } var baseTexture = utils.BaseTextureCache[ video._pixiId ]; if (!baseTexture) { baseTexture = new VideoTexture(video, scaleMode); utils.BaseTextureCache[ video._pixiId ] = baseTexture; } return baseTexture; }; /** * Mimic Pixi BaseTexture.from.... method. * * @static * @param video {HTMLVideoElement} * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values * @return {Texture} A Texture, but not a VideoTexture. */ VideoTexture.textureFromVideo = function (video, scaleMode) { var baseTexture = VideoTexture.baseTextureFromVideo(video, scaleMode); return new Texture(baseTexture); }; /** * Mimic Pixi BaseTexture.from.... method. * * @static * @param videoSrc {string} The URL for the video. * @param scaleMode {number} See {{#crossLink "PIXI/scaleModes:property"}}scaleModes{{/crossLink}} for possible values * @return {VideoTexture} */ VideoTexture.fromUrl = function (videoSrc, scaleMode) { var video = document.createElement('video'); video.src = videoSrc; video.autoPlay = true; video.play(); return VideoTexture.textureFromVideo(video, scaleMode); };