How to check the element is in viewport on angular

2019-06-11 17:13发布

问题:

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?

回答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]



回答2:

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" />