# All files / ngui-inview/src ngui-inview.component.ts

97.3% Statements 36/37
74.07% Branches 20/27
100% Functions 7/7
97.14% Lines 34/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103

    1x

    1x

    6x
    6x
    6x

    5x

    5x

    5x
    5x
    5x

    1x
    1x
    1x
    1x

    1x
    5x

    2x
    2x
    2x
    1x
    1x
    1x

    1x

    1x
    2x

    2x
    1x
    1x
    1x
    1x

    1x
    1x

    1x

    1x
     import {
        Component,
        ContentChild,
        ElementRef,
        EventEmitter,
        Inject,
        Input,
        OnDestroy,
        OnInit,
        Output,
        PLATFORM_ID,
        Renderer2,
        TemplateRef
    } from '@angular/core';

    import {isPlatformBrowser} from '@angular/common';

    /**
     * An element that listens to viewport positioning and fires inView and notInview events
     * ### example
     * ```ts
     * <ngui-in-view [options]="myOptions" (inView)="doA()" (notInview)="doB()">
     *   <img *ngIf src="https://picsum.photos/800/300?image=1>
     * </ngui-in-view>
     * ```
     */
    @Component({
        selector: 'ngui-inview',
        template: `
            <ng-container *ngIf="isInview" [ngTemplateOutlet]="template">
            </ng-container>
        `,
        styles: [':host {display: block;}']
    })
    export class NguiInviewComponent implements OnInit, OnDestroy {
        /** <ng-template> reference */
        @ContentChild(TemplateRef) template: TemplateRef<any>;
        /** IntersectionObserver options */
        @Input() options: any = {threshold: [.1, .2, .3, .4, .5, .6, .7, .8]};
        @Output() inview: EventEmitter<any> = new EventEmitter();
        @Output() notInview: EventEmitter<any> = new EventEmitter();

        observer: IntersectionObserver;
        /** indicates that this element is in viewport */
        isInview = false;
        /** indicates that this element is 80% in viewport. Used by the default callback */
        once80PctVisible = false;

        constructor(
            private element: ElementRef,
            private renderer: Renderer2,
            @Inject(PLATFORM_ID) private platformId: any) {
        }

        /** Starts IntersectionObserver */
        ngOnInit(): void {
            Eif (isPlatformBrowser(this.platformId)) {
                this.observer = new IntersectionObserver(this.handleIntersect.bind(this), this.options);
                this.observer.observe(this.element.nativeElement);
            }
        }

        /** stop IntersectionObserver */
        ngOnDestroy(): void {
            this.observer.disconnect();
        }

        /** fires (inview) and (notInview) events when this component is visible or not visible  */
        handleIntersect(entries): void {
            entries.forEach((entry: IntersectionObserverEntry) => {
                if (entry['isIntersecting']) {
                    this.isInview = true;
                    this.defaultInviewHandler(entry);
                    this.inview.emit(entry);
                } else {
                    this.notInview.emit(entry);
                }
            });
        }

        /**
         * default intersection handler, which sets blur dependes on intersection ratio
         * this won't be invoked if user provides any (inview) event. e.g. (inview)="something()"
         */
        defaultInviewHandler(entry): any {
            Iif (this.once80PctVisible || this.inview.observers.length) {
                return;
            }

            if (entry.intersectionRatio < 0.8) {
                const opacity = entry.intersectionRatio * (1 / 0.8);
                const blur = 20 - Math.floor(entry.intersectionRatio * 10) * 4;
                const filter = `blur(${blur}px)`;
                Object.assign(entry.target.style, {opacity, filter});
            } else {
                entry.target.style.opacity = 1;
                entry.target.style.filter = 'unset';

                this.once80PctVisible = true;
            }
        }
    }