JustinNobles Posted March 29, 2021 Posted March 29, 2021 I am having trouble trying to recreate this codepen from codepen url above in angular. The scroll isn't moving together with the drag in the stackblitz demo when I converted the original codepen javascript code to typescript code. Here is the stackblitz I am using to recreate the codepen project in Angular. Any help would be appreciated! https://stackblitz.com/edit/angular-simultaneous-scrolltrigger-draggable?file=src/app/app.component.ts See the Pen 896549f0a83297debd9111fe9b205a97 by GreenSock (@GreenSock) on CodePen.
GreenSock Posted March 30, 2021 Posted March 30, 2021 I noticed a few problems: You set up your "barLength" as an element instead of a number You're not setting the barLength properly The scope ("this") inside the callbacks isn't what you think it is. Draggable callbacks are scoped to the Draggable instance itself. Maybe you should use arrow functions to lock the scope to your component, or create local variables to reference things
JustinNobles Posted April 9, 2021 Author Posted April 9, 2021 Here is the updated stackblitz after applying what you said. I only have one problem left as I can't wrap my head around it. I am getting the error Property 'trigger' does not exist on type 'AppComponent'. https://stackblitz.com/edit/angular-ivy-a2re99?file=src/app/app.component.ts
OSUblake Posted April 9, 2021 Posted April 9, 2021 1 hour ago, JustinNobles said: Here is the updated stackblitz after applying what you said. I only have one problem left as I can't wrap my head around it. I am getting the error Property 'trigger' does not exist on type 'AppComponent'. Looks like you have some bad scoping going on here. You're using a regular function, so it's scoped to the draggable instance. That means you can't access stuff on the component, like trigger, barLength, maxScroll, etc. I would probably do it like this. This assumes there is only 1 element with the .handler class in your entire document at a given time. I would highly suggest using the element reference instead. Same goes for .container. draggable = new Draggable(".handler", { type: "x", bounds: ".container", onDrag: () => { this.trigger.scroll((this.draggable.x / this.barLength) * this.maxScroll); // when dragging, scroll the page to the corresponding ratio } }); 1
JustinNobles Posted April 14, 2021 Author Posted April 14, 2021 I implemented that draggable code you wrote in and tried to do the same for the scrolltrigger code it didn't work. Now I am getting the error Expected 0 arguments, but got 2. https://stackblitz.com/edit/angular-ivy-a2re99?file=src/app/app.component.ts
GreenSock Posted April 14, 2021 Posted April 14, 2021 That's incorrect syntax. I'm curious why you're trying to create a ScrollTrigger using "new ScrollTrigger(...)" instead of ScrollTrigger.create(). // BAD trigger = new ScrollTrigger(".container", { onRefresh: this.onResize, onUpdate: this.updateHandler }); // GOOD trigger = ScrollTrigger.create({ trigger: ".container", onRefresh: this.onResize, onUpdate: this.updateHandler }); I'm just assuming you meant for ".container" to be the trigger, but I'm not really sure. Maybe you meant it to be the scroller. In any case, I'd strongly recommend reading the docs or at least watching the video: Happy scrolling!
JustinNobles Posted April 14, 2021 Author Posted April 14, 2021 I had scrolltrigger.create() before but I keep getting Error: Cannot read property 'trigger' of undefined https://stackblitz.com/edit/angular-ivy-a2re99?file=src/app/app.component.ts
GreenSock Posted April 14, 2021 Posted April 14, 2021 That looks like a scope issue. "this" inside your function is undefined. Also, I think you're creating your Draggable using selector text on an element that doesn't even exist yet at that point, so the target is null. I'm not an Angular guy at all, but I think you've gotta tuck all that stuff inside a lifecycle method, perhaps ngOnInit(). 1
OSUblake Posted April 14, 2021 Posted April 14, 2021 4 hours ago, JustinNobles said: I had scrolltrigger.create() before but I keep getting Error: Cannot read property 'trigger' of undefined trigger is just set as a property on your class. You need to put the creation of it inside one of the lifecycle methods, like ngOnInit. Same with the draggable. <div #container class="container"> <div class="handler" #handler></div> <div class="slider" #slider></div> </div> <div style="height: 2000px"></div> This will get rid of some of your errors. You'll need to fix the rest. maxScroll and barLength are undefined at the start. @Component({ selector: "my-app", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"] }) export class AppComponent implements OnInit { @ViewChild("container", { static: true }) container: ElementRef; @ViewChild("handler", { static: true }) handler: ElementRef; @ViewChild("slider", { static: true }) slider: ElementRef; maxScroll: number; barLength: number; draggable: Draggable; trigger; ngOnInit(): void { this.trigger = ScrollTrigger.create({ trigger: this.container.nativeElement, onRefresh: () => this.onResize, onUpdate: () => this.updateHandler }); this.draggable = new Draggable(this.handler.nativeElement, { type: "x", bounds: this.container.nativeElement, onDrag: () => { this.trigger.scroll( (this.draggable.x / this.barLength) * this.maxScroll ); // when dragging, scroll the page to the corresponding ratio } }); } updateHandler() { // move the handler to the corresponding ratio according to the page's scroll position. gsap.set(this.handler.nativeElement, { x: (this.barLength * this.trigger.scroll()) / this.maxScroll }); } onResize() { if (this.trigger) { this.maxScroll = ScrollTrigger.maxScroll(window as any); // record the maximum scroll value for the page this.barLength = this.slider.nativeElement.offsetWidth - this.handler.nativeElement.offsetWidth; this.updateHandler(); } } } 1
JustinNobles Posted April 21, 2021 Author Posted April 21, 2021 I still couldn't get it to work. I watched so many videos, looked at tons of tutorials, etc and couldn't figure it out. If you could please help me get this working I would greatly appreciate it
GreenSock Posted April 21, 2021 Posted April 21, 2021 Bummer. Sorry to hear about the challenges, @JustinNobles. Unfortunately, this sounds like much more of an Angular issue - we just don't have the resources to provide free troubleshooting for other frameworks. We'd be happy to answer any GSAP-specific questions, though. Perhaps @OSUblake has some other suggestions, but I'm definitely not an Angular guy.
OSUblake Posted April 21, 2021 Posted April 21, 2021 It works here. https://stackblitz.com/edit/angular-simultaneous-scrolltrigger-draggable-wcwbbk?file=src/app/app.component.ts 2
JustinNobles Posted April 23, 2021 Author Posted April 23, 2021 That is awesome! Thank you so much. I took that same demo and tried to do my original side project and for some reason when implementing the dragging of my scrollbar div using gsap.to(".gallery", { x: -this.draggable.x }); to move my .gallery div caused alot of unexpected problems in the css as well as the typescript as my goal of understanding the original demo was to have a scrollbar div that moves a gallery horizontally on drag and scroll here is the main demo I was trying to achieve https://stackblitz.com/edit/angular-ivy-fyaz7w?file=src/app/app.component.ts
OSUblake Posted April 23, 2021 Posted April 23, 2021 This should put you in the right direction. Basically, the horizontally movement is a paused animation, and we just set the progress of that animation to the ratio of how far it's been dragged/scrolled. https://stackblitz.com/edit/angular-ivy-qjqa2k?file=src/app/app.component.ts 2
JustinNobles Posted April 25, 2021 Author Posted April 25, 2021 Wow that is exactly what I was looking for. I would have never thought of having a paused animation like that thanks again! I just have a question on the equation + "vh" on the X value of galleryAnimation. In this example I have 5 thumbnails * 95vw = 475vw so I initially changed the equation to 475 + "vw" thinking it would work as 475vw but I didn't get the desired outcome. After fiddling with numbers I got it looking the way I needed it to but just wondering if you could break that down for me https://stackblitz.com/edit/scrollbargsapfinal?file=src/app/app.component.ts
OSUblake Posted April 26, 2021 Posted April 26, 2021 Oh, I just did a quick estimate to get it working... and I probably used "vh" by accident. Either way, using vh/vw units probably isn't ideal because the gap between the slides looks like a px value. You would probably have to calculate the amount on every resize. Assuming your component is the entire width of the screen, you could get the bounding rect of the last slide and subtract the screen width from it to get how far the slides need to animate. const { left, width } = lastSlide.getBoundingClientRect(); const totalWidth = (left + width); const screenWidth = window.innerWidth; this.galleryAnim.progress(0); // create new animation this.galleryAnim = gsap.to(...)
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