//Matthew Shotton, R&D User Experience,© BBC 2015
import SourceNode, { SOURCENODESTATE } from "./sourcenode";
const TYPE = "CanvasNode";
class ImageNode extends SourceNode {
/**
* Initialise an instance of an ImageNode.
* This should not be called directly, but created through a call to videoContext.createImageNode();
*/
constructor(src, gl, renderGraph, currentTime, preloadTime = 4, attributes = {}) {
super(src, gl, renderGraph, currentTime);
this._preloadTime = preloadTime;
this._attributes = attributes;
this._textureUploaded = false;
this._displayName = TYPE;
}
get elementURL() {
return this._elementURL;
}
_load() {
if (this._image !== undefined) {
for (var key in this._attributes) {
this._image[key] = this._attributes[key];
}
return;
}
if (this._isResponsibleForElementLifeCycle) {
super._load();
this._image = new Image();
this._image.setAttribute("crossorigin", "anonymous");
// It's important to set the `onload` event before the `src` property
// https://stackoverflow.com/questions/12354865/image-onload-event-and-browser-cache?answertab=active#tab-top
this._image.onload = () => {
this._ready = true;
if (window.createImageBitmap) {
window
.createImageBitmap(this._image, { imageOrientation: "flipY" })
.then(imageBitmap => {
this._element = imageBitmap;
this._triggerCallbacks("loaded");
});
} else {
this._element = this._image;
this._triggerCallbacks("loaded");
}
};
this._image.src = this._elementURL;
this._image.onerror = () => {
console.error("ImageNode failed to load. url:", this._elementURL);
};
for (let key in this._attributes) {
this._image[key] = this._attributes[key];
}
}
this._image.onerror = () => {
console.debug("Error with element", this._image);
this._state = SOURCENODESTATE.error;
//Event though there's an error ready should be set to true so the node can output transparenn
this._ready = true;
this._triggerCallbacks("error");
};
}
_unload() {
super._unload();
if (this._isResponsibleForElementLifeCycle) {
if (this._image !== undefined) {
this._image.src = "";
this._image.onerror = undefined;
this._image = undefined;
delete this._image;
}
if (this._element instanceof window.ImageBitmap) {
this._element.close();
}
}
this._ready = false;
}
_seek(time) {
super._seek(time);
if (this.state === SOURCENODESTATE.playing || this.state === SOURCENODESTATE.paused) {
if (this._image === undefined) this._load();
}
if (
(this._state === SOURCENODESTATE.sequenced || this._state === SOURCENODESTATE.ended) &&
this._element !== undefined
) {
this._unload();
}
}
_update(currentTime) {
//if (!super._update(currentTime)) return false;
if (this._textureUploaded) {
super._update(currentTime, false);
} else {
super._update(currentTime);
}
if (
this._startTime - this._currentTime <= this._preloadTime &&
this._state !== SOURCENODESTATE.waiting &&
this._state !== SOURCENODESTATE.ended
)
this._load();
if (this._state === SOURCENODESTATE.playing) {
return true;
} else if (this._state === SOURCENODESTATE.paused) {
return true;
} else if (this._state === SOURCENODESTATE.ended && this._image !== undefined) {
this._unload();
return false;
}
}
}
export { TYPE as IMAGETYPE };
export default ImageNode;