Ng-lazyload-image: Solicitud de función: obtenga acceso a la imagen en la creación observable

Creado en 3 feb. 2018  ·  4Comentarios  ·  Fuente: tjoskar/ng-lazyload-image

Motivación e implementación

En este momento, es posible pasar un observable, que es una excelente manera de ampliar la biblioteca. Sin embargo, es un poco limitado ya que los usuarios no pueden acceder a la imagen de forma sencilla.

Uno de los problemas más comunes es cuando el usuario no usa la ventana para desplazarse o usa una biblioteca de 3 partes que agrega capas de desplazamiento adicionales (por ejemplo, iónico, diseño de material ng, etc.), y a veces puede ser difícil de encontrar qué elemento se desplaza realmente. Una forma de resolver esto podría ser usar un Intersection Observer (que también puede aumentar el rendimiento). P.ej.

@Component({
  selector: 'intersection-observer',
  template: `<img #img [defaultImage]="defaultImage" [lazyLoad]="image" [scrollObservable]="subject">`,
})
export class IntersectionObserverComponent {
  @ViewChild('img') img;
  subject = new Subject();
  defaultImage = 'https://www.placecage.com/1000/1000';
  image = 'https://images.unsplash.com/photo-1467932760935-519284fc87fa?dpr=2&auto=compress,format&fit=crop&w=1199&h=800&q=80';

  ngAfterViewInit() {
    const config = {
      rootMargin: '50px 50px',
      threshold: 0.01
    };

    function onIntersection(entries) {
      entries.forEach(entry => {
        if (entry.intersectionRatio > 0) {
          observer.unobserve(entry.target);
          this.subject.next();
        }
      });
    }
    const observer = new IntersectionObserver(onIntersection, config);
    observer.observe(this.img.nativeElement);
  }
}

Sin embargo, esto es bastante engorroso.

Lo que podemos hacer es aceptar una función como scrollObservable , algo como:

if (!this.scrollObservable) {
  const windowTarget = isWindowDefined() ? window : undefined;
  scrollObservable = getScrollListener(this.scrollTarget || windowTarget);
} else if (typeof this.scrollObservable === 'function') {
  scrollObservable = this.scrollObservable(image, offset) // and maybe more
} else {
  scrollObservable = this.scrollObservable.startWith('');
}

No podemos reescribir el componente anterior a:

@Component({
  selector: 'intersection-observer',
  template: `<img [defaultImage]="defaultImage" [lazyLoad]="image"
 [scrollObservable]="startLazyload" offest="50">`,
})
export class IntersectionObserverComponent {
  defaultImage = 'https://www.placecage.com/1000/1000';
  image = 'https://images.unsplash.com/photo-1467932760935-519284fc87fa?dpr=2&auto=compress,format&fit=crop&w=1199&h=800&q=80';

  startLazyload(image, offset) {
    Observable.create(observer => {
      const intersectionObserver = new IntersectionObserver(entries => {
        entries.forEach(entry => {
          if (entry.intersectionRatio > 0) {
            observer.next();
          }
        });
      }, {
        rootMargin: offset ? `${offset}px` : undefined,
        threshold: 0.01
      });
      intersectionObserver.observe(image);
      return () => observer.unobserve(image);
    });
  }
}

Mejor pero aún un poco ruidoso, especialmente cuando el usuario quiere usar IntersectionObserver en todas las imágenes.

Una forma de resolver esto podría ser pasar un Observable predeterminado en NgModule :

import { intersectionObserverLazyLoad } from 'some-place';

@NgModule({
    declarations: [ AppComponent ],
    imports: [ BrowserModule, lazyLoadImage({
      observable: intersectionObserverLazyLoad
    })],
    bootstrap: [ AppComponent ]
})
export class MyAppModule {}

No podemos reescribir el componente anterior para:

@Component({
  selector: 'intersection-observer',
  template: `<img [defaultImage]="defaultImage" [lazyLoad]="image" offest="50">`,
})
export class IntersectionObserverComponent {
  defaultImage = 'https://www.placecage.com/1000/1000';
  image = 'https://images.unsplash.com/photo-1467932760935-519284fc87fa?dpr=2&auto=compress,format&fit=crop&w=1199&h=800&q=80';
}

La capacidad de pasar funciones predeterminadas en NgModule también podría abrir puertas para crear funciones personalizadas para isVisible y loadImage pero esa es una historia posterior.

Resolvería: # 287, # 195, # 286, # 285, # 275, # 259 y más. La mayoría de los problemas se resuelven de otras formas, pero sería bueno si pudiéramos darle al usuario más flexibilidad al crear un observable.

¿Qué opinas @sapierens , @rimlin?

help wanted

Comentario más útil

@tjoskar, según scrollObservable proporcionando la función como opción para scrollObservable , que devolverá Observable, ¿quién es responsable de emitir el evento de carga de imagen? Si es así, ¡creo que es una idea genial!
Pero creo que es mejor usar el objeto en lugar de enumerar los argumentos:

...
} else if (typeof this.scrollObservable === 'function') {
  scrollObservable = this.scrollObservable({
    image, 
    offset
  });
} else {
...

Todos 4 comentarios

@tjoskar, según scrollObservable proporcionando la función como opción para scrollObservable , que devolverá Observable, ¿quién es responsable de emitir el evento de carga de imagen? Si es así, ¡creo que es una idea genial!
Pero creo que es mejor usar el objeto en lugar de enumerar los argumentos:

...
} else if (typeof this.scrollObservable === 'function') {
  scrollObservable = this.scrollObservable({
    image, 
    offset
  });
} else {
...

proporcionar función como opción para scrollObservable, que devolverá Observable, que es responsable de emitir un evento de carga de imagen

Correcto, es posible que también desee cambiar el nombre de scrollObservable pero eso sería un cambio importante.

Creo que es mejor usar un objeto en lugar de enumerar argumentos.

¡Estar de acuerdo!

Creo que esta es una buena idea, especialmente pasar un observador predeterminado.

Creo que es mejor usar un objeto en lugar de enumerar argumentos.

Yo también estoy de acuerdo con ésto.

Corregido en # 365 y en la versión 2.1.0

¿Fue útil esta página
0 / 5 - 0 calificaciones