MikeG95 Posted May 24, 2021 Share Posted May 24, 2021 Hey guys Im getting crazy with using Angular and Gsap. I recorded a video. Look at the markers. First-load without resize: https://gyazo.com/bc0061365a7614646806450e17f3c1f5 Resizing window https://gyazo.com/f259d4f0aebecd5acdd5152aa2dad6d2 I have multiples components and I want to use gsap on footer. The markers are wrong when i load my page but If i resize the window there are in the correct place and the animations works correctly. Im Using: Angular, Bootstrap and Gsap <div class=" container-fluid pb-0 mb-0 justify-content-center text-light " #footer> <footer #Infooter> <div class="row my-5 justify-content-center py-5"> <div class="col-11"> <div class="row "> <div class="col-xl-8 col-md-4 col-sm-4 col-12 my-auto mx-auto a"> <h3 class="text-muted mb-md-0 mb-5 bold-text">Pepper.</h3> </div> <div class="col-xl-2 col-md-4 col-sm-4 col-12"> <h6 class="mb-3 mb-lg-4 bold-text "><b>MENU</b></h6> <ul class="list-unstyled"> <li>Home</li> <li>About</li> <li>Blog</li> <li>Portfolio</li> </ul> </div> <div class="col-xl-2 col-md-4 col-sm-4 col-12"> <h6 class="mb-3 mb-lg-4 text-muted bold-text mt-sm-0 mt-5"><b>ADDRESS</b></h6> <p class="mb-1">605, RATAN ICON BUILDING</p> <p>SEAWOODS SECTOR</p> </div> </div> <div class="row "> <div class="col-xl-8 col-md-4 col-sm-4 col-auto my-md-0 mt-5 order-sm-1 order-3 align-self-end"> <p class="social text-muted mb-0 pb-0 bold-text"> <span class="mx-2"><i class="fa fa-facebook" aria-hidden="true"></i></span> <span class="mx-2"><i class="fa fa-linkedin-square" aria-hidden="true"></i></span> <span class="mx-2"><i class="fa fa-twitter" aria-hidden="true"></i></span> <span class="mx-2"><i class="fa fa-instagram" aria-hidden="true"></i></span> </p><small class="rights"><span>®</span> Pepper All Rights Reserved.</small> </div> <div class="col-xl-2 col-md-4 col-sm-4 col-auto order-1 align-self-end "> <h6 class="mt-55 mt-2 text-muted bold-text"><b>ANIRUDH SINGLA</b></h6><small> <span><i class="fa fa-envelope" aria-hidden="true"></i></span> anirudh@gmail.com</small> </div> <div class="col-xl-2 col-md-4 col-sm-4 col-auto order-2 align-self-end mt-3 "> <h6 class="text-muted bold-text"><b>RISHABH SHEKHAR</b></h6><small><span><i class="fa fa-envelope" aria-hidden="true"></i></span> rishab@gmail.com</small> </div> </div> </div> </div> </footer> </div> body { background: linear-gradient(0deg, #fff, 50%, #DEEEFE); background: #455A64; height: 100 !important } .container-fluid { background: #262626; color: #627482 !important; margin-bottom: 0; padding-bottom: 0 } small { font-size: calc(12px + (15 - 12) * ((100vw - 360px) / (1600 - 360))) !important } .bold-text { color: #989c9e !important } .mt-55 { margin-top: calc(50px + (60 - 50) * ((100vw - 360px) / (1600 - 360))) !important } h3 { font-size: calc(34px + (40 - 34) * ((100vw - 360px) / (1600 - 360))) !important } .social { font-size: 21px !important } .rights { font-size: calc(10px + (12 - 10) * ((100vw - 360px) / (1600 - 360))) !important } import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); @Component({ selector: 'app-footer', templateUrl: './footer.component.html', styleUrls: ['./footer.component.scss'] }) export class FooterComponent implements OnInit { @ViewChild ('footer', { static: true }) public footer: ElementRef<HTMLDivElement>; @ViewChild ('Infooter', { static: true }) public Infooter: ElementRef<HTMLDivElement>; constructor() {} ngOnInit(): void { this.initFooterAnimations(); } initFooterAnimations(): void { gsap.to(this.footer.nativeElement, { scrollTrigger: { trigger: this.footer.nativeElement, scrub: true, start: '40% bottom', }, duration: 0.6, y: -90, }); gsap.to(this.Infooter.nativeElement, { scrollTrigger: { trigger: this.Infooter.nativeElement, scrub: true, start: '-200px bottom', markers: true }, duration: 1, y: -190, }); } } There is my app.component angular html: <app-header></app-header> <app-body></app-body> <app-footer></app-footer> <router-outlet></router-outlet> Link to comment Share on other sites More sharing options...
Cassie Posted May 24, 2021 Share Posted May 24, 2021 I'm not an angular person but is there a way to check if the DOM content is loaded first before running the animtion code? 1 Link to comment Share on other sites More sharing options...
MikeG95 Posted May 24, 2021 Author Share Posted May 24, 2021 41 minutes ago, Cassie said: I'm not an angular person but is there a way to check if the DOM content is loaded first before running the animtion code? Im not an angular person too there is some info about angular lifecycle events. https://angular.io/guide/lifecycle-hooks I tried it with ngAfterview but not changes. Maybe im not writing it correctly. Link to comment Share on other sites More sharing options...
Cassie Posted May 24, 2021 Share Posted May 24, 2021 You're also animating the y position of the elements that you're using as triggers. Is that intentional? Maybe pop together a minimal demo and we'll see if we can help. Otherwise maybe one of these angular forums might be able to give you some pointers? gsap.to(this.footer.nativeElement, { scrollTrigger: { trigger: this.footer.nativeElement, scrub: true, start: '40% bottom', }, duration: 0.6, y: -90, }); gsap.to(this.Infooter.nativeElement, { scrollTrigger: { trigger: this.Infooter.nativeElement, scrub: true, start: '-200px bottom', markers: true }, duration: 1, y: -190, }); } Link to comment Share on other sites More sharing options...
MikeG95 Posted May 25, 2021 Author Share Posted May 25, 2021 17 hours ago, Cassie said: You're also animating the y position of the elements that you're using as triggers. Is that intentional? Maybe pop together a minimal demo and we'll see if we can help. Otherwise maybe one of these angular forums might be able to give you some pointers? gsap.to(this.footer.nativeElement, { scrollTrigger: { trigger: this.footer.nativeElement, scrub: true, start: '40% bottom', }, duration: 0.6, y: -90, }); gsap.to(this.Infooter.nativeElement, { scrollTrigger: { trigger: this.Infooter.nativeElement, scrub: true, start: '-200px bottom', markers: true }, duration: 1, y: -190, }); } Yes it is intentional, yep maybe asking on angular forums could help me, this is what I did to investigate when Gsap is loaded: I writed it to show in console import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; @Component({ selector: 'app-footer', templateUrl: './footer.component.html', styleUrls: ['./footer.component.scss'] }) export class FooterComponent implements AfterViewInit { @ViewChild ('footer', { static: true }) public footer: ElementRef<HTMLDivElement>; @ViewChild ('Infooter', { static: true }) public Infooter: ElementRef<HTMLDivElement>; constructor() {} ngOnInit(): void { gsap.registerPlugin(ScrollTrigger); console.log("onInit called") } ngDoCheck(){ console.log("do check") } ngAfterViewInit() { this.initFooterAnimations(); console.log("after view init") } initFooterAnimations(): void { gsap.to(this.Infooter.nativeElement, { scrollTrigger: { trigger: this.Infooter.nativeElement, scrub: true, start: '-200px bottom', markers: true }, duration: 1, y: -190, }); } } And there is the result: Link to comment Share on other sites More sharing options...
MikeG95 Posted May 25, 2021 Author Share Posted May 25, 2021 2 minutes ago, MikeG95 said: Yes it is intentional, yep maybe asking on angular forums could help me, this is what I did to investigate when Gsap is loaded: I writed it to show in console import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; @Component({ selector: 'app-footer', templateUrl: './footer.component.html', styleUrls: ['./footer.component.scss'] }) export class FooterComponent implements AfterViewInit { @ViewChild ('footer', { static: true }) public footer: ElementRef<HTMLDivElement>; @ViewChild ('Infooter', { static: true }) public Infooter: ElementRef<HTMLDivElement>; constructor() {} ngOnInit(): void { gsap.registerPlugin(ScrollTrigger); console.log("onInit called") } ngDoCheck(){ console.log("do check") } ngAfterViewInit() { this.initFooterAnimations(); console.log("after view init") } initFooterAnimations(): void { gsap.to(this.Infooter.nativeElement, { scrollTrigger: { trigger: this.Infooter.nativeElement, scrub: true, start: '-200px bottom', markers: true }, duration: 1, y: -190, }); } } And there is the result: In this proyect I m bringing any img(logos,background...) and Text(<p>) from my own api to <header> and <body>, maybe gsap is loading before than this api? Link to comment Share on other sites More sharing options...
GreenSock Posted May 25, 2021 Share Posted May 25, 2021 I'm not an Angular guy either, but it sure sounds like you must be loading things that affect layout AFTER the page's "load" event fires. So just make sure you call ScrollTrigger.refresh() after you're done adding/loading anything to the page that affects layout. 1 Link to comment Share on other sites More sharing options...
MikeG95 Posted May 25, 2021 Author Share Posted May 25, 2021 5 hours ago, GreenSock said: I'm not an Angular guy either, but it sure sounds like you must be loading things that affect layout AFTER the page's "load" event fires. So just make sure you call ScrollTrigger.refresh() after you're done adding/loading anything to the page that affects layout. It works but only if use ngAfterVIewChecked that is called every time Angular has finished running change detection on a component , now im sure that is a problem with angular but with this kind of call funcition is doing scrollrefresh in every component in the same load, its not a solution, it would works with ngAfterView but it desnt. I gonna post on Angular Forums and maybe i will come back with a solution. Thanks guys 2 Link to comment Share on other sites More sharing options...
NiceBone Posted May 26, 2021 Share Posted May 26, 2021 On 5/25/2021 at 12:44 PM, MikeG95 said: It works but only if use ngAfterVIewChecked that is called every time Angular has finished running change detection on a component , now im sure that is a problem with angular but with this kind of call funcition is doing scrollrefresh in every component in the same load, its not a solution, it would works with ngAfterView but it desnt. I gonna post on Angular Forums and maybe i will come back with a solution. Thanks guys Would be great if you share your solution.. Same problem. With ngAfterViewChecked it will work but the function triggers every ms on the site. I dont really know if its good for the performance on huge sites. Soft Reloads (only f5)/Routing changes will break the markers. I asked all my colleauges at work for a solution but no one got any solutions for this problem. Link to comment Share on other sites More sharing options...
NiceBone Posted May 26, 2021 Share Posted May 26, 2021 (edited) checked: boolean = false; ngAfterContentChecked(): void { if (!this.checked) { this.checked = true; setTimeout(() => { ScrollTrigger.refresh(); this.initScrollAnimation(); }, 1); } } ngOnInit(): void { this.initialAnimations(); } @MikeG95 If you use this code it will work but the solution is not that great... You will not notice the 1ms timeout on reloads/routing. You can change it to .1 or .0001 and it will work too. Dont forget to kill the triggers on each component when you got multiple components with animations. ngOnDestroy(): void { let triggers = ScrollTrigger.getAll(); triggers.forEach((trigger) => { trigger.kill(true); }); } Edited May 27, 2021 by NiceBone 1 Link to comment Share on other sites More sharing options...
MikeG95 Posted June 2, 2021 Author Share Posted June 2, 2021 On 5/26/2021 at 6:00 PM, NiceBone said: checked: boolean = false; ngAfterContentChecked(): void { if (!this.checked) { this.checked = true; setTimeout(() => { ScrollTrigger.refresh(); this.initScrollAnimation(); }, 1); } } ngOnInit(): void { this.initialAnimations(); } @MikeG95 If you use this code it will work but the solution is not that great... You will not notice the 1ms timeout on reloads/routing. You can change it to .1 or .0001 and it will work too. Dont forget to kill the triggers on each component when you got multiple components with animations. ngOnDestroy(): void { let triggers = ScrollTrigger.getAll(); triggers.forEach((trigger) => { trigger.kill(true); }); } I found the problem, but I coundt get the solution, the problem is that we are using an api and its loads after than ngAfterView I was consulting this problem on Angular Forums and they told my that I have to use rxjs with SwitchMap Tool to get our api petition before than ScrollRefresher, but Im noob on Angular, I being 4 days trying to do it work but imopssible for me maybe in the future I will undertand it https://i.gyazo.com/80761cf8cd9aa673e1ece1ba8ee6a36f.png Here is my post on Angular forums https://www.reddit.com/r/Angular2/comments/nlfkuw/i_need_to_execute_a_function_after_my_api/ Link to comment Share on other sites More sharing options...
OSUblake Posted June 2, 2021 Share Posted June 2, 2021 Hi @MikeG95 Can you make a demo on stackblitz showing the problem? https://stackblitz.com/ Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now