1.2.0 • Published 3 years ago

@eutrepe/ng-ep-intersection-observer v1.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

Build Statuscodecov semantic-release GitHub


NgxEutrepeIsInViewport

  • Directive for Angular 10+ based on Intersection Observer to detect element in viewport.

Installation

npm i --save @eutrepe/@eutrepe/ng-ep-intersection-observer

You also need polyfill

npm i --save intersection-observer

and add this in your src/polyfills.ts file

import 'intersection-observer';

Usage

1) Register the EpIntersectionObserverModule in your app module.

import { EpIntersectionObserverModule } from '@eutrepe/ng-ep-intersection-observer'

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

import { EpIntersectionObserverModule } from '@eutrepe/ng-ep-intersection-observer';

@NgModule({
   declarations: [
     AppComponent
   ],
   imports:      [
       BrowserModule,
       EpIntersectionObserverModule
   ],
    providers: [],
   bootstrap: [ AppComponent ],
   exports: []
})
export class AppModule { }

2) Use the directive ep-io

If element is visible in viewport the directive add in-viewport class to the element or custom class

Basic

<section class="section1" ep-io>
 <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Harum, facere.</p>
</section>

Advanced

<section class="section1"
   [ep-io]="{threshold: [0, 0.5, 1]}"
   [epIoOnActive]="onActive.bind(this, param1, param2, ...)"
   [epIoOnUnactive]="onUnactive.bind(this, param1, param2, ...)"
   [epIoInvokeOnce]="true"
   [epIoWaitFor]="event"
   [epIoGroupName]="'myGroupName'"
   [epIoActiveClass]="'my-class'"
   [epIoRemoveClassAfterLeaving]="false"
   (epIoViewportChange)="onChanage($event)"
   >
 <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Harum, facere.</p>
</section>

<!-- Use .bind(this) for callbacks if you want use scoped variables -->

Advanced 'Lazy'

If you have multiple directives in the same options you can use global configuration per module or per component using INTERSECTION_OBSERVE_GLOBAL_CONFIG in providers array. Unfortunately here you can't use this or other dependency inside epIoOnActive and epIoOnUnactive functions but you can use subscription from NgEpIOStatusService service and manually control this logic.

<section class="section1" 
 ep-io
 (epIoViewportChange)="onChanage($event)">
 <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Harum, facere.</p>
</section>
import { Component, OnInit } from '@angular/core';
import { INTERSECTION_OBSERVE_GLOBAL_CONFIG, EpIntersectionObserverStatusService, IntersectionObserverEvent } from '@eutrepe/ng-ep-intersection-observer';

@Component({
  selector: 'app-io-event-example',
  templateUrl: './io-event-example.component.html',
  styleUrls: ['./io-event-example.component.scss'],
  providers: [
    {
      provide: INTERSECTION_OBSERVE_GLOBAL_CONFIG, useValue: {
        intersectionConfig: {
          rootMargin: '-20% 0px -20% 0px',
          threshold: [0, 0.5, 1]
        },
        epIoGroupName: 'myGroupName',
        epIoWaitFor: 'event',
        epIoOnActive: () => {console.log('Yoy can\'t use here "this" operator')}
        epIoOnUnactive: () => {console.log('Yoy can\'t use here "this" operator')}
        epIoInvokeOnce: true,
        epIoActiveClass: 'my-class',
        epIoRemoveClassAfterLeaving: false
      }
    }
  ]
})
export class IoEventExampleComponent implements OnInit {

  constructor(private ngEpIOStatusService: EpIntersectionObserverStatusService) { }

  ngOnInit(): void {  

    this.ngEpIOStatusService.get().subscribe((event: IntersectionObserverEvent) => {
      console.log(event.el);
      console.log(event.status);
    });
  }
}

If you want run directive logic after event (for example load all images, videos etc.) you should set property epIoWaitFor to event and use NgEpIOService. Also if you have multiple directive with multiple events you need add epIoGroupName to each directive. If you have multiple directive but all waiting for the same event you can omit this property and run send function from NgEpIOService invoke without parameter

import { Component, OnInit } from '@angular/core';
import { EpIntersectionObserverWatchService, INTERSECTION_OBSERVE_GLOBAL_CONFIG } from '@eutrepe/ng-ep-intersection-observer';

@Component({
  selector: 'app-io-event-example',
  templateUrl: './io-event-example.component.html',
  styleUrls: ['./io-event-example.component.scss'],

  providers: [
    {
      provide: INTERSECTION_OBSERVE_GLOBAL_CONFIG, useValue: {
        intersectionConfig: {
          rootMargin: '-20% 0px -20% 0px',
        },
        epIoGroupName: 'myGroupName',
        epIoWaitFor: 'event'
      }
    }
  ]
})
export class IoEventExampleComponent implements OnInit {

  constructor(private ngEpIOWatchService: EpIntersectionObserverWatchService) { }

  ngOnInit(): void {
    // Intersection Observer will start work after 5 sec. *****
    setTimeout(() => {
      this.ngEpIOWatchService.start('myGroupName');
    }, 5000);
  }
}

API

Directive:

InputTypeRequiredDescription
ep-ioIIntersectionObserveConfigYES , default Intersection Observe configuration*Run the plugin with user configuration or default configuration
epIoInvokeOncebooleanOptional, default: falseIf true directive invoke just once
epIoOnActiveFunctionOptional, default: nullThe function is invoked when element is in viewport
epIoOnUnactiveFunctionOptional, default: nullThe function is invoked when element is out viewport
epIoWaitForstringOptional, default: noneInform directive when invoke self logic. none - immediately, media - after loading all images, videos, audios INSIDE every SINGLE directive, event - waiting for event from service
epIoGroupNamestringOptional, default: (empty string) | After send event to invoke directive logic, all directives with matched group name will start. This property set group name for directive
epIoActiveClassstringOptional, default: 'in-viewport'Custom class for visible element
epIoRemoveClassAfterLeavingbooleanOptional, default: trueIf set true directive remove CSS class after leaving viewport

*Intersection Observe: developer.mozilla.org

Services:

EpIntersectionObserverWatchService:

This function inform directive when start self logic if property epIoWaitFor is set to event

get(): Observable<string>
  • Observer for event. Used inside directive
start(groupName?: string = ''): void
  • When you run this function directive will start self logic. In params you can send groupName what decide which directives can run. Property epIoGroupName in directive must set for the same value
EpIntersectionObserverStatusService:
get(): Observable<IntersectionObserverEvent>
  • Observer for event
send(status: IntersectionObserverEvent): void
  • Sending event when visibility status was changed. Used inside directive

types

export type IntersectionObserveConfig = {
  root?: HTMLElement;
  rootMargin?: string;
  threshold?: Array<number>;
}


export type IntersectionObserverEvent = {
  el: HTMLElement;
  status: boolean;
}


export type IntersectionObserveGlobalConfig = {
  intersectionConfig?: IntersectionObserveConfig;
  epIoOnActive?: (...args: any[] | null) => void;
  epIoOnUnactive?: (...args: any[] | null) => void;
  epIoInvokeOnce?: boolean;
  epIoWaitFor?: string;
  epIoActiveClass?: string;
  epIoGroupName?: string;
  epIoRemoveClassAfterLeaving?: boolean;
}

Intersection Observe default config:

const defaultConfig: IntersectionObserveConfig = {
    root: null,
    rootMargin: '0px 0px 0px 0px',
    threshold: [0.0]
  }