Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added method addMoreFrames #39

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ This method stops playing the image sequence.
sequence.stop();
```

### addMoreFrames(moreFrames: number)

This method adds more frames to the image sequence.

```typescript
sequence.addMoreFrames(moreFrames);
```

### playing

This getter method returns a boolean indicating whether the image sequence is playing.
Expand Down Expand Up @@ -282,7 +290,7 @@ tarball and implement the `imageURL` to return the URL of an image in the tarbal
### How can I create a tar file (tarball) with images?

I created an easy-to-use online tool for this: [Tar File Creator](https://reindernijhoff.net/tools/tar/). Drag and drop your selection of images onto the page, and a tar file will be generated that you can download.
You can also use a tar tool to create the tar file yourself.
You can also use a tar tool to create the tar file yourself.

### I want to download just 8 frames first and preload the rest of the images later. How can I do this?

Expand Down Expand Up @@ -322,7 +330,7 @@ const sequence = new FastImageSequence(containerElement, options);

### Can I download a tar file myself and use it with FastImageSequence?

Yes, you can download the tar file yourself and create a data URL from it. You can then use this data URL as the `tarURL` option.
Yes, you can download the tar file yourself and create a data URL from it. You can then use this data URL as the `tarURL` option.
See this [example](https://github.com/mediamonks/fast-image-sequence/blob/main/example/src/exampleLoadTar.js) for more information.


Expand Down
112 changes: 79 additions & 33 deletions src/lib/FastImageSequence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export class FastImageSequence {
private initialized: boolean = false;
private posterImage: HTMLImageElement | undefined;
private timeFrameVisible: number = 0;
private time: number = 0;

/**
* Creates an instance of FastImageSequence.
Expand Down Expand Up @@ -120,15 +121,12 @@ export class FastImageSequence {
display: 'block',
});

this.container.appendChild(this.canvas);

this.resizeObserver = new ResizeObserver(() => {
this.clearCanvas = true;
if (this.lastFrameDrawn < 0 && this.posterImage) {
this.drawImage(this.posterImage);
}
});
this.resizeObserver.observe(this.canvas);

this.mutationObserver = new MutationObserver(() => {
if (!this.container.isConnected) {
Expand All @@ -138,37 +136,10 @@ export class FastImageSequence {
});
this.mutationObserver.observe(container, {childList: true});

// init all frames
this.frames = Array.from({length: this.options.frames}, (_, index) => new Frame(index));
this.log = this.options.showDebugInfo ? console.log : () => {
};

// init all input sources
const sources = this.options.src instanceof Array ? this.options.src : [this.options.src];
this.sources = sources.map((src, index) => {
if (src.tarURL !== undefined) {
return new ImageSourceTar(this, index, src);
} else if (src.imageURL !== undefined) {
return new ImageSourceFetch(this, index, src);
} else {
return new ImageSource(this, index, src);
}
});

this.loadResources().then(() => {
this.initialized = true;

this.log('Frames', this.frames);
this.log('Options', this.options);

if (this.options.showDebugInfo) {
this.logElement = createLogElement();
this.container.appendChild(this.logElement);
this.tick(() => this.logDebugStatus(this.logElement as HTMLDivElement));
}

this.drawingLoop(-1);
});
this.struct();
}

/**
Expand Down Expand Up @@ -261,6 +232,22 @@ export class FastImageSequence {
this.speed = 0;
}

/**
* Add more frames to the image sequence.
* @param {number} moreFrames - The number of frames to add.
*/
public addMoreFrames(moreFrames: number) {
if (moreFrames < 0) {
throw new Error('FastImageSequence: moreFrames must be greater than or equal to 0');
}

if (moreFrames === 0) {
return;
}

this.struct(moreFrames);
}

/**
* Get the image of a specific frame.
* @param {number} index - The index of the frame.
Expand Down Expand Up @@ -298,8 +285,9 @@ export class FastImageSequence {

/**
* Destruct the FastImageSequence instance.
* @param {boolean} [isAddMoreFrames=false] - Whether the destruct is called to add more frames.
*/
public destruct() {
public destruct(isAddMoreFrames: boolean = false) {
if (this.destructed) {
return;
}
Expand All @@ -313,7 +301,7 @@ export class FastImageSequence {
this.mutationObserver.disconnect();

this.container.removeChild(this.canvas);
if (this.logElement) {
if (this.logElement && !isAddMoreFrames) {
this.container.removeChild(this.logElement);
this.logElement = undefined;
}
Expand All @@ -335,6 +323,62 @@ export class FastImageSequence {
this.clearCanvas = true;
}

/**
* Struct the FastImageSequence instance.
* If moreFrames is provided, it will add more frames to the sequence. Otherwise, it will initialize the sequence.
* @param moreFrames
*/
private struct(moreFrames?: number) {
if (moreFrames !== undefined) {
this.options.frames += moreFrames;
this.destruct();
}

this.container.appendChild(this.canvas);
this.resizeObserver.observe(this.canvas);
this.mutationObserver.observe(this.container, {childList: true});

// init all frames
this.frames = Array.from({length: this.options.frames}, (_, index) => new Frame(index));

// init all input sources
const sources = this.options.src instanceof Array ? this.options.src : [this.options.src];
this.sources = sources.map((src, index) => {
if (src.tarURL !== undefined) {
return new ImageSourceTar(this, index, src);
} else if (src.imageURL !== undefined) {
return new ImageSourceFetch(this, index, src);
} else {
return new ImageSource(this, index, src);
}
});

if (moreFrames !== undefined) {
this.destructed = false;
}

this.loadResources().then(() => {
if (moreFrames === undefined) {
this.initialized = true;
}

this.log('Frames', this.frames);
this.log('Options', this.options);

if (this.options.showDebugInfo && moreFrames === undefined) {
this.logElement = createLogElement();
this.container.appendChild(this.logElement);
this.tick(() => this.logDebugStatus(this.logElement as HTMLDivElement));
}

if (moreFrames !== undefined) {
this.drawingLoop(this.time);
} else {
this.drawingLoop(-1);
}
});
}

private setLoadingPriority() {
const priorityIndex = this.index;// this.wrapIndex(Math.min(this.spread / 2 - 2, (this.frame - this.prevFrame) * (dt * 60)) + this.frame);
this.frames.forEach((image) => {
Expand Down Expand Up @@ -379,6 +423,8 @@ export class FastImageSequence {
return;
}

this.time = time;

time /= 1000;

const dt = this.initialized ? this.startTime < 0 ? 1 / 60 : Math.min(time - this.startTime, 1 / 30) : 0;
Expand Down