[SOLVED] Image Only Loads Once From URL

Hi,

I’m loading images into my app from URL’s using Yaustar’s example here. I’ve slightly modified the script to work with UI images, rather than model textures.

I have two buttons that cycle forwards and backwards through the images. This works great the first time each image is shown. However, if I try to go back to an image that was previously shown, it doesn’t load. I’m not getting any errors, and everything else functions normally.

Any ideas on why it wouldn’t be loading an image from the same URL twice?

Here’s the code I’m using:

ImageViewer.prototype.loadImageFromURL = function(imageURL)
{
    var target = this.PreviewImage;
    
    this.app.loader.getHandler("texture").crossOrigin = "anonymous";
        
    var asset = new pc.Asset("imagePreview", "texture", {
        url: imageURL
    });
    
    this.app.assets.add(asset);
    
    asset.on("error", function (message) {
        console.log(message);
    });
    
    asset.on("load", function (asset) {
        
        target.element.texture = this.resource;
    });
    
    this.app.assets.load(asset);
};

Hi @RipcordDev, are you using that method more than once for the same image url?

Your method creates an asset each time and adds it to the assets registry. Normally you should do that once for each image url on init time and reuse those assets later instead of creating one each time you render an image.

Hi Leonidas, thanks for the reply!

Yes, I’m using this method for than once for each URL. Since I’m dealing with a large database of images, I thought it would be best to load the images as needed, rather than grabbing them all at once at the beginning. I guess this isn’t the right approach.

How would I reuse this image once it’s been loaded the first time?

Good, you can still continue doing what you do to load the images on the fly as you go.

What you could do to avoid creating duplicate assets when trying to reload an image is check first if your asset already exists before creating it. If it exists bypass your creation code and reuse that same asset in place.

Something like this (haven’t tested it, you can get the idea):

ImageViewer.prototype.loadImageFromURL = function(imageURL)
{

    var target = this.PreviewImage;
    var asset = this.app.assets.getByUrl(imageURL);

    if( asset ){
        target.element.texture = asset.resource;
    }else{
    
        this.app.loader.getHandler("texture").crossOrigin = "anonymous";
            
        asset = new pc.Asset("imagePreview", "texture", {
            url: imageURL
        });
        
        this.app.assets.add(asset);
        
        asset.on("error", function (message) {
            console.log(message);
        });
        
        asset.on("load", function (asset) {
            
            target.element.texture = this.resource;
        });
    
        this.app.assets.load(asset);
    }
};

Thanks for suggestion! This seems like it should work, but I’m getting the same behaviour.

I’ve tried a few things to debug the problem. In the IF statement, I tried applying the found texture to a new object and it works.

Here’s where I’m at. In the IF statement I apply the found texture to a new image element called TEST. This works every time I go to an image that’s already been loaded (exactly as it should).

I’ve also added a line to create a new texture asset for each image that’s created. (I’m not sure if this is the most efficient way of doing things, but it’s not hurting performance at least)

If I change this line target.element.texture = this.resource; to this.PreviewImage.element.texture or this.TEST.element.texture I get an undefined error. I don’t understand why. I feel like this may be the part of the issue I’m having.

Any suggestions on this one?

Thanks!

var target = this.PreviewImage;
var asset = this.app.assets.getByUrl(imageURL);

if (asset) {
    //target.element.texture = asset.resource;
    this.TEST.element.texture = asset.resource;
}
else {
    this.app.loader.getHandler("texture").crossOrigin = "anonymous";
        
    var textureName = 'tex.' + imageURL.substring(imageURL.lastIndexOf('/') +1);
        
    asset = new pc.Asset(textureName, "texture", {
        url: imageURL
    });
    
    this.app.assets.add(asset);
    
    asset.on("error", function (message) {
        console.log(message);
    });
        
    asset.on("load", function (asset) {
        target.element.texture = this.resource;
    });
        
    this.app.assets.load(asset);
}    

Mmm, not sure what is wrong. It seems more of an issue with how you apply the loaded texture and not so much with the code above.

@RipcordDev can you share a project to take a look?

Hi @Leonidas, thanks for your help with this one! I had to step away from this project for a bit, but when I came back to it, I realized it was an issue with how I was applying the loaded texture, as you suggested.

The code above now works as it should.

Thanks again!

1 Like