์ง๊ธ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฅํ๋ ์ข์ ๋ฐฉ๋ฒ ์ธ Observable์ ์ ๋ฌํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ฉ์ด ๊ฐ๋จํ ๋ฐฉ๋ฒ์ผ๋ก ์ด๋ฏธ์ง์ ์ก์ธ์ค ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ์ ํ์ ์ ๋๋ค.
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ์ค ํ๋๋ ์ฌ์ฉ์๊ฐ ์ฐฝ์ ์ฌ์ฉํ์ฌ ์คํฌ๋กคํ์ง ์๊ฑฐ๋ ์ถ๊ฐ ์คํฌ๋กค ๋ ์ด์ด (์ : ionic, ng material design ๋ฑ)๋ฅผ ์ถ๊ฐํ๋ 3 ๋ถ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ์ด๋ฉฐ ๋๋ก๋ ์ฐพ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ์ค์ ๋ก ์คํฌ๋กค๋๋ ์์. ์ด๋ฅผ ํด๊ฒฐํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ 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 ๋ฑ. ๋๋ถ๋ถ์ ๋ฌธ์ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ํด๊ฒฐ๋์ง๋ง Observable์ ๋ง๋ค ๋ ์ฌ์ฉ์์๊ฒ ๋ ๋ง์ ์ ์ฐ์ฑ์ ์ ๊ณต ํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
@sapierens , @rimlin ์ด๋ป๊ฒ ์๊ฐํ์ธ์?
@tjoskar ๋ ๋น์ ์ด ํฅ์ ํ ์ดํด scrollObservable
์ ๋ํ ์ต์
์ผ๋ก ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ scrollObservable
๋ฐ๊ด ์ด๋ฏธ์ง๋ก๋ ์ด๋ฒคํธ์ ์ฑ
์์ด ๊ด์ฐฐ ๊ฐ๋ฅํ ๋ฐํํฉ๋๋ค? ๊ทธ๋ ๋ค๋ฉด ์ ๋ง ๋ฉ์ง ์์ด๋์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค!
ํ์ง๋ง ์ธ์๋ฅผ ์ด๊ฑฐํ๋ ๋์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค.
...
} else if (typeof this.scrollObservable === 'function') {
scrollObservable = this.scrollObservable({
image,
offset
});
} else {
...
scrollObservable์ ๋ํ ์ต์ ์ผ๋ก ํจ์๋ฅผ ์ ๊ณตํฉ๋๋ค.์ด ์ต์ ์ ์ด๋ฏธ์ง๋ก๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๋ Observable์ ๋ฐํํฉ๋๋ค.
๋ง์ต๋๋ค. scrollObservable
์ด๋ฆ์ ๋ฐ๊พธ๊ณ ์ถ์ ์๋ ์์ง๋ง ์ด๋ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์
๋๋ค.
์ธ์๋ฅผ ์ด๊ฑฐํ๋ ๋์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋์ํ๋ค!
ํนํ ๊ธฐ๋ณธ ๊ด์ฐฐ์๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด ์ข์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ธ์๋ฅผ ์ด๊ฑฐํ๋ ๋์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ์ด๊ฒ์ ๋์ํฉ๋๋ค.
# 365 ๋ฐ ๋ฒ์ 2.1.0์์ ์์ ๋จ
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
@tjoskar ๋ ๋น์ ์ด ํฅ์ ํ ์ดํด
scrollObservable
์ ๋ํ ์ต์ ์ผ๋ก ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌscrollObservable
๋ฐ๊ด ์ด๋ฏธ์ง๋ก๋ ์ด๋ฒคํธ์ ์ฑ ์์ด ๊ด์ฐฐ ๊ฐ๋ฅํ ๋ฐํํฉ๋๋ค? ๊ทธ๋ ๋ค๋ฉด ์ ๋ง ๋ฉ์ง ์์ด๋์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค!ํ์ง๋ง ์ธ์๋ฅผ ์ด๊ฑฐํ๋ ๋์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค.