Ng-lazyload-image: 機能のリクエスト:観察可能な作成で画像へのアクセスを取得します

作成日 2018年02月03日  ·  4コメント  ·  ソース: tjoskar/ng-lazyload-image

動機と実装

現在、ライブラリを拡張するための優れた方法であるオブザーバブルを渡すことが可能です。 ただし、使用者が簡単な方法で画像にアクセスできないため、少し制限があります。

最も一般的な問題の1つは、ユーザーがウィンドウを使用してスクロールしない場合、またはスクロールレイヤーを追加する3部構成のライブラリ(イオン、マテリアルデザインなど)を使用する場合であり、見つけるのが難しい場合があります。実際にスクロールする要素を調べます。 これを解決する1つの方法は、 Intersection Observerを使用することです(これにより、パフォーマンスが向上する可能性もあります)。 例えば。

@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);
  }
}

ただし、これは非常に面倒です。

私たちにできることは、次のような関数をscrollObservableとして受け入れることです。

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('');
}

上記のコンポーネントを次のように書き換えることはできません。

@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);
    });
  }
}

特にユーザーがすべての画像でIntersectionObserverを使用したい場合は、より良いですが、それでも少しうるさいです。

これを解決する方法は、 NgModuleデフォルトのObservableを渡すこともできます。

import { intersectionObserverLazyLoad } from 'some-place';

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

上記のコンポーネントを次のように書き換えることはできません。

@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';
}

NgModuleでデフォルト関数を渡す機能は、 isVisibleloadImageカスタム関数を作成するための扉を開くこともできますが、それは後の話です。

解決します:#287、#195、#286、#285、#275、#259など。 ほとんどの問題は他の方法で解決されますが、オブザーバブルを作成するときにユーザーに柔軟性を与えることができれば素晴らしいと思います。

@ sapierens 、@ rimlinはどう思いますか?

help wanted

最も参考になるコメント

@tjoskarは、 scrollObservableオプションとして関数を提供することで、 scrollObservableを拡張したいことを理解しています。これにより、画像の読み込みイベントを発行するObservableが返されますか? もしそうなら、私は本当にクールなアイデアだと思います!
しかし、引数を列挙する代わりにオブジェクトを使用する方が良いと思います。

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

全てのコメント4件

@tjoskarは、 scrollObservableオプションとして関数を提供することで、 scrollObservableを拡張したいことを理解しています。これにより、画像の読み込みイベントを発行するObservableが返されますか? もしそうなら、私は本当にクールなアイデアだと思います!
しかし、引数を列挙する代わりにオブジェクトを使用する方が良いと思います。

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

scrollObservableのオプションとして関数を提供します。これにより、画像の読み込みイベントを発行するObservableが返されます。

正解です。 scrollObservable名前を変更したい場合もありますが、これは重大な変更になります。

引数を列挙する代わりにオブジェクトを使用する方が良いと思います

同意する!

これは、特にデフォルトのオブザーバーを渡すのは良い考えだと思います。

引数を列挙する代わりにオブジェクトを使用する方が良いと思います

私もこれに同意します。

#365およびバージョン2.1.0で修正済み

このページは役に立ちましたか?
0 / 5 - 0 評価