1

How to check element is in viewport in angular 2?. I have tried with many npm packages. But not working. How to check the element is in viewport?. I want to call API on page scroll if element is in viewport?

I have three tabs. I have to check if tab is active and element is in viewport. How to check?

Mistalis
  • 17,793
  • 13
  • 73
  • 97
Vel
  • 9,027
  • 6
  • 34
  • 66

3 Answers3

1

I used 'jQuery-viewport-checker' to perform various tasks if elements are on viewport. It worked for me. This may help you:

Follow this if you don't have "jQuery" working in your angular 2 project: https://stackoverflow.com/a/42295505/7532440

You'll have to install the 'jQuery-viewport-checker' using 'Bower' and add it to 'Scripts' in 'angular-cli.json' file like the way you have installed the 'jQuery' in the link I have provided.

cmd:

bower install jQuery-viewport-checker

in 'angular-cli.json':

"scripts": [
      "../bower_components/jquery/dist/jquery.min.js",
      "../bower_components/jQuery-viewport-checker/dist/jquery.viewportchecker.min.js"
  ]

Now you can use 'jQuery-viewport-checker'

More info on: https://github.com/dirkgroenen/jQuery-viewport-checker

Your app.component.ts will look like this:

import { Component, OnInit } from '@angular/core';
declare var $:any;

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 title = 'app works!';

 ngOnInit(){

        $(document).ready(function(){
        $("p").click(function(){
        $(this).hide();
    });
    });


        $('.dummy').viewportChecker({
            classToAdd: 'visible', // Class to add to the elements when they are visible,
            classToAddForFullView: 'full-visible', // Class to add when an item is completely visible in the viewport
            classToRemove: 'invisible', // Class to remove before adding 'classToAdd' to the elements
            removeClassAfterAnimation: false, // Remove added classes after animation has finished
            offset: [100], // The offset of the elements (let them appear earlier or later). This can also be percentage based by adding a '%' at the end
            invertBottomOffset: true, // Add the offset as a negative number to the element's bottom
            repeat: false, // Add the possibility to remove the class if the elements are not visible
            callbackFunction: function(elem, action){}, // Callback to do after a class was added to an element. Action will return "add" or "remove", depending if the class was added or removed
            scrollHorizontal: false // Set to true if your website scrolls horizontal instead of vertical.
    });
 }

}

Here class 'visible' will be added on ".dummy" class in an element once it's in the ViewPort. You should explore it more(other parameters) according to your need Accordingly you can code your HTML. I Hope it helps.

Update:

If it gives error try the following (as these worked for the author of the question):

1): try changing the port ng serve --port 4200 to 4208 (or any other port)

2): put viewport checker code inside document ready like this:

jQuery(document).ready(function(){ 
      $('.dummy').viewportChecker({
            classToAdd: 'visible', // Class to add to the elements when they are visible,
            classToAddForFullView: 'full-visible', // Class to add when an item is completely visible in the viewport
            classToRemove: 'invisible', // Class to remove before adding 'classToAdd' to the elements
            removeClassAfterAnimation: false, // Remove added classes after animation has finished
            //offset: [100], // The offset of the elements (let them appear earlier or later). This can also be percentage based by adding a '%' at the end
            invertBottomOffset: true, // Add the offset as a negative number to the element's bottom
            repeat: false, // Add the possibility to remove the class if the elements are not visible
            callbackFunction: function(elem, action){}, // Callback to do after a class was added to an element. Action will return "add" or "remove", depending if the class was added or removed
            scrollHorizontal: false // Set to true if your website scrolls horizontal instead of vertical.
    });
 });

and remove offset: [100]

Community
  • 1
  • 1
AmanDeepSharma
  • 2,138
  • 4
  • 20
  • 34
  • I'm using npm and bower both, please check this link http://stackoverflow.com/a/42295505/7532440 – AmanDeepSharma May 03 '17 at 10:16
  • You should use Bower for web related packages. – AmanDeepSharma May 03 '17 at 10:18
  • Did you follow all steps for installing jQuery? And path in "scripts" (in angular-cli.json) should point correctly to jquery.min.js file. First check is your simple jQuery is wrking the then try for viewPortChecker – AmanDeepSharma May 03 '17 at 11:59
  • Make sure you use "declare var $:any;" (with declare) – AmanDeepSharma May 03 '17 at 12:01
  • `bower install jquery --save bower jquery#* cached https://github.com/jquery/jquery-dist.git#3.2.1 bower jquery#* validate 3.2.1 against https://github.com/jquery/jquery-dist.git#* bower jquery#>=1.9.0 || >=2.0.0 cached https://github.com/jquery/jquery-dist.git#3.2.1 bower jquery#>=1.9.0 || >=2.0.0 validate 3.2.1 against https://github.com/jquery/jquery-dist.git#>=1.9.0 || >=2.0.0 bower no-json No bower.json file to save to, use bower init to create one` – Vel May 03 '17 at 12:05
  • Do you see a bower.json file in your project? – AmanDeepSharma May 03 '17 at 12:08
  • You didn't follow bower init, it creates this file...as I mentioned in that link https://ibb.co/jqTXD5 – AmanDeepSharma May 03 '17 at 12:20
  • You should be inside your root folder to install bower, I'm just using angular cli https://ibb.co/g0FZRQ This is my folder structure – AmanDeepSharma May 03 '17 at 12:28
  • It seems..this is the issue with git bash. Try to check this with 'angular cli' in a simple demo project just for this purpose. https://cli.angular.io/ – AmanDeepSharma May 03 '17 at 12:37
  • reinstall bower : "npm i -g bower" (I think its not installed globally) check if its giving version: "bower --v" then try bower init – AmanDeepSharma May 03 '17 at 12:43
  • Sure, I'll have a look on this. – AmanDeepSharma May 03 '17 at 14:59
0

I didn't use this for a while, but might be what you're looking for (refactor it to fit your needs):

export function getY(element: HTMLElement) {
  let y = element.offsetTop;

  while (element.offsetParent && element.offsetParent != document.body) {
    element = <HTMLElement>element.offsetParent;
    y += element.offsetTop;
  }
  return y;
}

export function getElementOnScreen(selector: string, delta: number = 0.3): any {
  let windowH = self.innerHeight;
  let windowY = self.pageYOffset;
  let margin = windowH * delta;

  return Array
    .from(document.querySelectorAll(selector))
    .find(el => {
      let elementY = getY(el as HTMLElement);
      let elementH = el.clientHeight;

      let topOnScreen = (elementY - windowY) <= margin;
      let bottomOnScreen = (windowY + margin) <= (elementY + elementH);

      return topOnScreen && bottomOnScreen;
    });
}

export function onScreen$(selector: string): Observable<boolean> {
  return Observable
    .fromEvent(window, 'scroll')
    .throttleTime(100)
    .map(event => getElementOnScreen(selector))

    .do(element => call.api(element))

    .map(Boolean)
    .distinctUntilChanged()
}

example use:

<div id="test" [class.i-am-in-viewport]="onScreen$('div#test') |async" />
Sasxa
  • 40,334
  • 16
  • 88
  • 102
0

Using jQuery inside angular is not a good method.

You can make use of intersection-observer API to achieve this.

I have created a demo app using Youtube Iframe API, which plays when the video is in viewport and pause when it's out of the viewport.

Working demo

Live Demo:- https://angular-viewport-intersection-observer-youtube.stackblitz.io

Live Edit:- https://stackblitz.com/edit/angular-viewport-intersection-observer-youtube

Package Used

https://github.com/thisissoon/angular-inviewport

Rameez Rami
  • 5,322
  • 2
  • 29
  • 36