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