Ng-lazyload-image: ๊ธฐ๋Šฅ ์š”์ฒญ : ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ์ƒ์„ฑ์—์„œ ์ด๋ฏธ์ง€์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ ์–ป๊ธฐ

์— ๋งŒ๋“  2018๋…„ 02์›” 03์ผ  ยท  4์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: tjoskar/ng-lazyload-image

๋™๊ธฐ ๋ถ€์—ฌ ๋ฐ ๊ตฌํ˜„

์ง€๊ธˆ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™•์žฅํ•˜๋Š” ์ข‹์€ ๋ฐฉ๋ฒ• ์ธ 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 ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”?

help wanted

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@tjoskar ๋‚œ ๋‹น์‹ ์ด ํ–ฅ์ƒ ํ•  ์ดํ•ด scrollObservable ์— ๋Œ€ํ•œ ์˜ต์…˜์œผ๋กœ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ scrollObservable ๋ฐœ๊ด‘ ์ด๋ฏธ์ง€๋กœ๋“œ ์ด๋ฒคํŠธ์— ์ฑ…์ž„์ด ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค? ๊ทธ๋ ‡๋‹ค๋ฉด ์ •๋ง ๋ฉ‹์ง„ ์•„์ด๋””์–ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค!
ํ•˜์ง€๋งŒ ์ธ์ˆ˜๋ฅผ ์—ด๊ฑฐํ•˜๋Š” ๋Œ€์‹  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚ซ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

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

๋ชจ๋“  4 ๋Œ“๊ธ€

@tjoskar ๋‚œ ๋‹น์‹ ์ด ํ–ฅ์ƒ ํ•  ์ดํ•ด scrollObservable ์— ๋Œ€ํ•œ ์˜ต์…˜์œผ๋กœ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ scrollObservable ๋ฐœ๊ด‘ ์ด๋ฏธ์ง€๋กœ๋“œ ์ด๋ฒคํŠธ์— ์ฑ…์ž„์ด ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค? ๊ทธ๋ ‡๋‹ค๋ฉด ์ •๋ง ๋ฉ‹์ง„ ์•„์ด๋””์–ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค!
ํ•˜์ง€๋งŒ ์ธ์ˆ˜๋ฅผ ์—ด๊ฑฐํ•˜๋Š” ๋Œ€์‹  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚ซ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

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

scrollObservable์— ๋Œ€ํ•œ ์˜ต์…˜์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.์ด ์˜ต์…˜์€ ์ด๋ฏธ์ง€๋กœ๋“œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” Observable์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋งž์Šต๋‹ˆ๋‹ค. scrollObservable ์ด๋ฆ„์„ ๋ฐ”๊พธ๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ด๋Š” ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

์ธ์ˆ˜๋ฅผ ์—ด๊ฑฐํ•˜๋Š” ๋Œ€์‹  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚ซ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋™์˜ํ•˜๋‹ค!

ํŠนํžˆ ๊ธฐ๋ณธ ๊ด€์ฐฐ์ž๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ธ์ˆ˜๋ฅผ ์—ด๊ฑฐํ•˜๋Š” ๋Œ€์‹  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚ซ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋„ ์ด๊ฒƒ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

# 365 ๋ฐ ๋ฒ„์ „ 2.1.0์—์„œ ์ˆ˜์ • ๋จ

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰