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

Support webp background images #322

Closed
DominikTrenz opened this issue Mar 8, 2018 · 4 comments · Fixed by #365
Closed

Support webp background images #322

DominikTrenz opened this issue Mar 8, 2018 · 4 comments · Fixed by #365

Comments

@DominikTrenz
Copy link

I'm using webp format images as background images, which needs a fallback for browsers that doesn't support it.
The fallback looks like this:

background-image: url('/assets/image.jpg');
@supports (background-image: -webkit-image-set(url(/assets/image.webp') 1x)) {
   background-image: -webkit-image-set(url(/assets/image.webp') 1x)
}

Can you support this?

@tjoskar
Copy link
Owner

tjoskar commented Mar 24, 2018

This could be supported by passing a custom function, something like:

This is not implemented yet

@Component({
    selector: 'image',
    template: `
        <div [lazyLoad]="image" [setBackgroudImage]="setBackgroudImage"></div>
    `
})
class ImageComponent {
    image = 'https://image.jpg';
    setBackgroudImage = (element, imagePath) => {
      if (window.CSS.supports(`background-image`, `-webkit-image-set(url('${imagePath}') 1x)`) {
        element.style.backgroundImage = `-webkit-image-set(url('${imagePath}') 1x)`; 
      } else {
        element.style.backgroundImage = `url('${imagePath}')`;  
      }
    }
}

I guess however that you want to set a default function instead of setting this for every image. In order to fix that we need to fix #323, #304 first.

@tjoskar tjoskar added the Blocked Waiting for an other issue to be resolved label Oct 31, 2018
@tjoskar tjoskar mentioned this issue Nov 2, 2018
@tjoskar tjoskar reopened this Nov 7, 2018
@tjoskar
Copy link
Owner

tjoskar commented Nov 7, 2018

@DominikTrenz
You should be able to use this in version 2.1.0

Declare your custom setLoadedImage:

function setLoadedImage({ element, imagePath, useSrcset }) {
  if (window.CSS.supports(`background-image`, `-webkit-image-set(url('${imagePath}') 1x)`) {
    element.style.backgroundImage = `-webkit-image-set(url('${imagePath}') 1x)`; 
  } else {
    element.style.backgroundImage = `url('${imagePath}')`;  
  }
}

And then give it to LazyLoadImageModule in your NgModule:

@NgModule({
  declarations: [ AppComponent ],
  imports: [
    BrowserModule,
    LazyLoadImageModule.forRoot({ setLoadedImage })
  ],
  bootstrap: [ AppComponent ]
})

Let me know if you run into any problems.

@tjoskar tjoskar closed this as completed Nov 7, 2018
@Kolotovkina
Copy link

Kolotovkina commented Jan 18, 2019

Hi! Do you have any updates? Does ng-lazyload-image support using image-set for background images?

@tjoskar
Copy link
Owner

tjoskar commented Jan 25, 2019

Hi @Kolotovkina,
Unfortunately no. Not completely. There is no way to tell if a background image was loaded or not, form my understanding.

So we can define our own setLoadedImage to something like this:

function setLoadedImage({ element, imagePath, useSrcset }) {
  if (window.CSS.supports(`background-image`, `image-set(url('${imagePath}') 1x)`) {
    element.style.backgroundImage = `image-set(url('${imagePath}') 1x)`; 
  } else {
    element.style.backgroundImage = `url('${imagePath}')`;  
  }
}

But what if we want to use 2x and maybe 3x: image-set("cat.png" 1x, "cat-2x.png" 2x, "cat-3x.png" 3x);. In that case, do we have to create a loadImage function:

function loadImage({ imagePath }: { imagePath: string }) {
  // imagePath is a string. And can be: '"cat.png" 1x, "cat-2x.png" 2x, "cat-3x.png" 3x'
  // get devicePixelRatio (window.devicePixelRatio)
  // create a regex to pick the right image
  // load it:
  return new Promise((resolve, reject) => {
    img = new Image();
    img.src = theRightImage;
    img.onload = () => resolve(imagePath);
    img.onerror = (error: Error) => reject(error);
  });
}

And then we can use the image:

function setLoadedImage({ element, imagePath, useSrcset }) {
  if (window.CSS.supports(`background-image`, `image-set(${imagePath})`) {
    element.style.backgroundImage = `image-set(${imagePath})`; 
  } else {
    const deafultImage = pick1xImage(imagePath); // Create this function
    element.style.backgroundImage = `url('${deafultImage}')`;  
  }
}

And then pass to to ng-lazyload:

@NgModule({
  declarations: [ AppComponent ],
  imports: [
    BrowserModule,
    LazyLoadImageModule.forRoot({ loadImage, setLoadedImage })
  ],
  bootstrap: [ AppComponent ]
})

and in the template:

<img [defaultImage]="defaultImage" [lazyLoad]="`"cat.png" 1x, "cat-2x.png" 2x, "cat-3x.png" 3x'`">

So it should be possible but you have to do some work.

@tjoskar tjoskar removed the Blocked Waiting for an other issue to be resolved label Jan 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants