Jump to content

Search In
  • More options...
Find results that contain...
Find results in...

Help with multiple instances of GSAP Draggable

Recommended Posts

Hi there, this is my first post so hopefully I'm in the right place.


I've recently started using GSAP Draggable to create draggable/scrollable sections on a website I'm working on.


I have 3 elements per instance, a scroll bar, which houses the draggable scroll handle, and a corresponding scroll container which slides left and right as the handle is dragged to reveal more inner items.


I got it working the way I wanted and everything seemed to be going well until I tried to scale it up to easily include multiple instances.


This issue I'm facing is that while each of the draggable scroll bars seem to work as expected (in that dragging the handle of one does not move the handle of any of the others), however the scroll container that they correspond with seems to be overwritten recursively so that all handles affect only the final container rather than the container they are paired with.


I assume by issue is with my draggable.create and would appreciate any help.


I've provided my code below:


$( window ).on( 'resize load', function( e ) {
		scrollGroupID = $(this).attr( 'data-draggable-id' );
		scrollHandle = $( '#draggable-' + scrollGroupID );
		scrollBar =  $( '#draggable-bar-' + scrollGroupID );
		scrollGroup = $( '#' + scrollGroupID );
		scrollGroupWidth = scrollGroup.width();
		scrollMax = 0;
		$(scrollGroup).children().each(function () { scrollMax = scrollMax + $(this).outerWidth(); });
		scrollMax = scrollMax - scrollGroupWidth;
		maxScroll = scrollBar.outerWidth(); 
		barLength = maxScroll - scrollHandle.outerWidth(); 
		barDifference = scrollMax / maxScroll;

		Draggable.create(scrollHandle, {
			type: 'x',
			bounds: scrollBar,
			throwProps: true,
			onDrag:function() {
				gsap.to(scrollGroup, {x: (-this.x / barLength * maxScroll) * barDifference});


Link to comment
Share on other sites

Hey there @Conal - Welcome to the forums. ☺️

Can you please put together a minimal demo for us so we can help you with this. 


Link to comment
Share on other sites


I think this is bad idea to create Draggable every time on resize, better on resize check is Draggable was created - then .update(), else -.create()

If you use resize event on mobile, it will be fired every time when browser adress bar is hidden or showed (scroll up / scroll down page)
Also you can use optimizedResize (based on requestAnimationFrame + customEvent) check MDN russian version examples part (did't find on english version MDN site)

  • Like 1
Link to comment
Share on other sites

Hi @Cassie here is the demo as requested 

See the Pen xxPOQEo by ConalBirtles (@ConalBirtles) on CodePen


The bottom one works as I want but the 2 proceeding it don't.


@_Greg _ Absolutelly, I agree. That was just something I had on while I was testing. My next port of call would be to only run the Draggable update at the end of a resize or delayed on some form of throttling. Thanks for the tip!

Link to comment
Share on other sites

30 minutes ago, Conal said:

The bottom one works as I want but the 2 proceeding it don't.

This issue not with GSAP or Draggable.


As i understand, please correct me if i'm wrong

You create global variables (without declaration) so on every interation you rewrite it
Read about closure And about scoping rules for let
You create variable in window (window.scrollGroupID) not inside function, if you declared variable let scrollGroupID you create scoped variable


See the Pen MWOezVZ?editors=0011 by gregOnCodePen (@gregOnCodePen) on CodePen

  • Like 3
Link to comment
Share on other sites

Ah ok! I get what you're doing.

Seems like the scrollGroup variable is always the last scrollGroup, I'm not really hot on jQuery so I don't know why it's not scoped.  ¯\_(ツ)_/¯

If you get the target you can grab the data attr from that and use that to target the correct container in the tween. Something like this?

onDrag:function() {
  console.log(this.target.dataset.draggableId, scrollGroup)
  gsap.to(`#${this.target.dataset.draggableId}`, {
    x: (-this.x / barLength * maxScroll) * barDifference


  • Like 3
Link to comment
Share on other sites

Hi @Conal,


It's looks like you were almost there. The issue is with the onDrag function. You'll want to set your tween separate from the CB function, as it looses it's target's context when you're calling it 'onDrag'. Note: I just used -500 for the x amount, cause I didn't look at the math for the actual value. (You'll also want to add an onThrowUpdate to make sure it syncs with the inertia plugin)


See the Pen podbqjm?editors=1011 by elegantseagulls (@elegantseagulls) on CodePen

  • Like 3
Link to comment
Share on other sites

Wow this is great! I'm still something of a novice when it comes to JS/Jquery so I'm going to dig through the examples this evening as see if i can get my head around your suggestions.


Thanks again!

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.