Jump to content
Search Community

Recreating GSAP Project in Angular

JustinNobles test
Moderator Tag

Recommended Posts

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

Link to comment
Share on other sites

I noticed a few problems:

  1. You set up your "barLength" as an element instead of a number
  2. You're not setting the barLength properly
  3. 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
Link to comment
Share on other sites

  • 2 weeks later...
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
    }
});

 

  • Like 1
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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(). 

  • Like 1
Link to comment
Share on other sites

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();
    }
  }
}

 

 

  • Like 1
Link to comment
Share on other sites

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. 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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(...)

 

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...