UNPKG

5.63 kBJavaScriptView Raw
1import { Ticker } from '@pixi/ticker';
2import { BaseImageResource } from './BaseImageResource.mjs';
3
4const _VideoResource = class extends BaseImageResource {
5 constructor(source, options) {
6 options = options || {};
7 if (!(source instanceof HTMLVideoElement)) {
8 const videoElement = document.createElement("video");
9 videoElement.setAttribute("preload", "auto");
10 videoElement.setAttribute("webkit-playsinline", "");
11 videoElement.setAttribute("playsinline", "");
12 if (typeof source === "string") {
13 source = [source];
14 }
15 const firstSrc = source[0].src || source[0];
16 BaseImageResource.crossOrigin(videoElement, firstSrc, options.crossorigin);
17 for (let i = 0; i < source.length; ++i) {
18 const sourceElement = document.createElement("source");
19 let { src, mime } = source[i];
20 src = src || source[i];
21 const baseSrc = src.split("?").shift().toLowerCase();
22 const ext = baseSrc.slice(baseSrc.lastIndexOf(".") + 1);
23 mime = mime || _VideoResource.MIME_TYPES[ext] || `video/${ext}`;
24 sourceElement.src = src;
25 sourceElement.type = mime;
26 videoElement.appendChild(sourceElement);
27 }
28 source = videoElement;
29 }
30 super(source);
31 this.noSubImage = true;
32 this._autoUpdate = true;
33 this._isConnectedToTicker = false;
34 this._updateFPS = options.updateFPS || 0;
35 this._msToNextUpdate = 0;
36 this.autoPlay = options.autoPlay !== false;
37 this._load = null;
38 this._resolve = null;
39 this._onCanPlay = this._onCanPlay.bind(this);
40 this._onError = this._onError.bind(this);
41 if (options.autoLoad !== false) {
42 this.load();
43 }
44 }
45 update(_deltaTime = 0) {
46 if (!this.destroyed) {
47 const elapsedMS = Ticker.shared.elapsedMS * this.source.playbackRate;
48 this._msToNextUpdate = Math.floor(this._msToNextUpdate - elapsedMS);
49 if (!this._updateFPS || this._msToNextUpdate <= 0) {
50 super.update();
51 this._msToNextUpdate = this._updateFPS ? Math.floor(1e3 / this._updateFPS) : 0;
52 }
53 }
54 }
55 load() {
56 if (this._load) {
57 return this._load;
58 }
59 const source = this.source;
60 if ((source.readyState === source.HAVE_ENOUGH_DATA || source.readyState === source.HAVE_FUTURE_DATA) && source.width && source.height) {
61 source.complete = true;
62 }
63 source.addEventListener("play", this._onPlayStart.bind(this));
64 source.addEventListener("pause", this._onPlayStop.bind(this));
65 if (!this._isSourceReady()) {
66 source.addEventListener("canplay", this._onCanPlay);
67 source.addEventListener("canplaythrough", this._onCanPlay);
68 source.addEventListener("error", this._onError, true);
69 } else {
70 this._onCanPlay();
71 }
72 this._load = new Promise((resolve) => {
73 if (this.valid) {
74 resolve(this);
75 } else {
76 this._resolve = resolve;
77 source.load();
78 }
79 });
80 return this._load;
81 }
82 _onError(event) {
83 this.source.removeEventListener("error", this._onError, true);
84 this.onError.emit(event);
85 }
86 _isSourcePlaying() {
87 const source = this.source;
88 return !source.paused && !source.ended && this._isSourceReady();
89 }
90 _isSourceReady() {
91 const source = this.source;
92 return source.readyState > 2;
93 }
94 _onPlayStart() {
95 if (!this.valid) {
96 this._onCanPlay();
97 }
98 if (this.autoUpdate && !this._isConnectedToTicker) {
99 Ticker.shared.add(this.update, this);
100 this._isConnectedToTicker = true;
101 }
102 }
103 _onPlayStop() {
104 if (this._isConnectedToTicker) {
105 Ticker.shared.remove(this.update, this);
106 this._isConnectedToTicker = false;
107 }
108 }
109 _onCanPlay() {
110 const source = this.source;
111 source.removeEventListener("canplay", this._onCanPlay);
112 source.removeEventListener("canplaythrough", this._onCanPlay);
113 const valid = this.valid;
114 this.resize(source.videoWidth, source.videoHeight);
115 if (!valid && this._resolve) {
116 this._resolve(this);
117 this._resolve = null;
118 }
119 if (this._isSourcePlaying()) {
120 this._onPlayStart();
121 } else if (this.autoPlay) {
122 source.play();
123 }
124 }
125 dispose() {
126 if (this._isConnectedToTicker) {
127 Ticker.shared.remove(this.update, this);
128 this._isConnectedToTicker = false;
129 }
130 const source = this.source;
131 if (source) {
132 source.removeEventListener("error", this._onError, true);
133 source.pause();
134 source.src = "";
135 source.load();
136 }
137 super.dispose();
138 }
139 get autoUpdate() {
140 return this._autoUpdate;
141 }
142 set autoUpdate(value) {
143 if (value !== this._autoUpdate) {
144 this._autoUpdate = value;
145 if (!this._autoUpdate && this._isConnectedToTicker) {
146 Ticker.shared.remove(this.update, this);
147 this._isConnectedToTicker = false;
148 } else if (this._autoUpdate && !this._isConnectedToTicker && this._isSourcePlaying()) {
149 Ticker.shared.add(this.update, this);
150 this._isConnectedToTicker = true;
151 }
152 }
153 }
154 get updateFPS() {
155 return this._updateFPS;
156 }
157 set updateFPS(value) {
158 if (value !== this._updateFPS) {
159 this._updateFPS = value;
160 }
161 }
162 static test(source, extension) {
163 return globalThis.HTMLVideoElement && source instanceof HTMLVideoElement || _VideoResource.TYPES.includes(extension);
164 }
165};
166let VideoResource = _VideoResource;
167VideoResource.TYPES = ["mp4", "m4v", "webm", "ogg", "ogv", "h264", "avi", "mov"];
168VideoResource.MIME_TYPES = {
169 ogv: "video/ogg",
170 mov: "video/quicktime",
171 m4v: "video/mp4"
172};
173
174export { VideoResource };
175//# sourceMappingURL=VideoResource.mjs.map