現在、ライブラリを拡張するための優れた方法であるオブザーバブルを渡すことが可能です。 ただし、使用者が簡単な方法で画像にアクセスできないため、少し制限があります。
最も一般的な問題の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でデフォルト関数を渡す機能は、 isVisible
とloadImage
カスタム関数を作成するための扉を開くこともできますが、それは後の話です。
解決します:#287、#195、#286、#285、#275、#259など。 ほとんどの問題は他の方法で解決されますが、オブザーバブルを作成するときにユーザーに柔軟性を与えることができれば素晴らしいと思います。
@ sapierens 、@ rimlinはどう思いますか?
@tjoskarは、 scrollObservable
オプションとして関数を提供することで、 scrollObservable
を拡張したいことを理解しています。これにより、画像の読み込みイベントを発行するObservableが返されますか? もしそうなら、私は本当にクールなアイデアだと思います!
しかし、引数を列挙する代わりにオブジェクトを使用する方が良いと思います。
...
} else if (typeof this.scrollObservable === 'function') {
scrollObservable = this.scrollObservable({
image,
offset
});
} else {
...
scrollObservableのオプションとして関数を提供します。これにより、画像の読み込みイベントを発行するObservableが返されます。
正解です。 scrollObservable
名前を変更したい場合もありますが、これは重大な変更になります。
引数を列挙する代わりにオブジェクトを使用する方が良いと思います
同意する!
これは、特にデフォルトのオブザーバーを渡すのは良い考えだと思います。
引数を列挙する代わりにオブジェクトを使用する方が良いと思います
私もこれに同意します。
#365およびバージョン2.1.0で修正済み
最も参考になるコメント
@tjoskarは、
scrollObservable
オプションとして関数を提供することで、scrollObservable
を拡張したいことを理解しています。これにより、画像の読み込みイベントを発行するObservableが返されますか? もしそうなら、私は本当にクールなアイデアだと思います!しかし、引数を列挙する代わりにオブジェクトを使用する方が良いと思います。