Jump to content
GreenSock

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

Loop draggable carousel

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi guys,

I am currently using draggable for a horizontal timeline and its working great. Is there a way of looping the content to the start onces i've gotten to the end or loop to the to the start at the end? would anyone please point me in the right direction.

 

Thanks

Link to comment
Share on other sites

Sounds a little tricky. Keep in mind that a timeline can not be at the end and the beginning at the same time. 

There may be a solution but it is going to depend on how your animation is built and what is happening visually.

It would really help if you could provide a very basic CodePen that illustrates the basic functionality

 

http://greensock.com/forums/topic/9002-read-this-first-how-to-create-a-codepen-demo/

Link to comment
Share on other sites

Thanks for the quick reply. Here is a sample codepen 

See the Pen akrkAJ by elololex (@elololex) on CodePen

I want it to be able to loop (Although i am using numbers, each div will contain images and text as well)

 

PS. The data will be loaded in from a database so the will be dynamic.

 

Thanks

Link to comment
Share on other sites

This is a little tricky but possible.

Take a look at our 1.19.0 release article: http://greensock.com/1-19-0/

 

Look at the section for the ModifiersPlugin and the Carousel Wrap.

That should start to explain how the looping animation can occur.

 

Making that controlled by Draggable isn't something I can create quickly for you, but you may want to start exploring the carousel wrap demo: http://codepen.io/GreenSock/pen/QEdpLe Just to see the basic theory of getting an element to wrap back to a starting value once it reaches a certain maximum value (handled by the modulus operation).

 

I suspect the solution will involve dragging one thing that applies new y values to each ".timeline" element and forces them into a certain range like between -200 and 1400px.

  • Like 3
Link to comment
Share on other sites

This is a little tricky but possible.

 

Remember how I said normalization is key to figuring out most animation problems? Just record a couple of start values and you're good to go. Note that you should not clamp the value because that will prevent it from looping.

See the Pen c8723bcdba9df92bc11fcfe062e01de8?editors=0010 by osublake (@osublake) on CodePen

  • Like 4
Link to comment
Share on other sites

Thanks guys, That's exactly what i wanted. I have try this ideas out and let you know.

 

Thanks again

Link to comment
Share on other sites

I am experience a massive performance hit due to having about 100 of this individual divs containing images and texts. Any other way of accomplishing this? Thanks

Link to comment
Share on other sites

That's awesome, Blake! Thanks.

I started down the path of normalizing the progress() but my head got wrapped a few times a long the way ;) Glad to see you take it the distance.

Link to comment
Share on other sites

Elolex,

 

Regarding performance, you may have your work cut out for you. You will probably get better results converting all this to canvas and using a hi-speed 2D renderer like pixi.js

 

 

Smooth scroll performance is very difficult to achieve with a large DOM structure (no fault of GSAP). Infinitely scrolling apps like twitter and facebook have gone to great lengths to get the best performance. 

 

In the case of infinite scroll for Facebook they do things like discard elements once you scroll past them and only bring "into view" elements that they know you are close to scrolling to. 

 

I know what you are doing isn't as complicated as scrolling through an infinite amount of data but you may be able to learn something from the techniques discussed in these articles:

 

http://engineering.flipboard.com/2015/02/mobile-web/

https://www.smashingmagazine.com/2013/05/infinite-scrolling-lets-get-to-the-bottom-of-this/'

http://www.pocketjavascript.com/blog/2015/2/3/the-quest-for-smooth-scrolling

https://engineering.linkedin.com/linkedin-ipad-5-techniques-smooth-infinite-scrolling-html5

  • Like 2
Link to comment
Share on other sites

Nice links, Carl!

 

Here's an obvious tip from the LinkedIn article. Hide stuff you can't see. 

 

I must say, using Draggable to manipulate a paused animation with the ModifiersPlugin works extremely well. Looping 100 images inside a responsive container...

See the Pen 2716a24249f67d1179c5bdb0e9eb3489?editors=0010 by osublake (@osublake) on CodePen

  • Like 4
Link to comment
Share on other sites

Another great demo, Blake. Was silky smooth on my phone and desktop.

Link to comment
Share on other sites

Guys, you've both been outstanding with the support and help. Thanks so much and i will share a link to the project once its completed. Thanks again!!

  • Like 1
Link to comment
Share on other sites

Hi guys, I have tried using this as a snap value

 

snap:{

x: function(endValue) {
var _snap = Math.round(endValue / boxWidth) * boxWidth;
            return _snap;
        }

     }

 

but after dragging a few times, it seems as if there is an offset been applied and doesn't snap to the middle.... In short, How do i go about add a snap that is consistent.

 

Thanks

Link to comment
Share on other sites

I'll look at this again and figure out the best way to incorporate snapping.

  • Like 1
Link to comment
Share on other sites

Gold!!!  This works perfectly. Outstanding stuff.

 

Thanks so much. 

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Hi Blake, Just another feature i am trying to add to this project. How would i go about adding a left and right button to this carousel and also how can i make the middle image scale up as it comes into the middle (like 0.8 scale on both sides and 1 in the middle).

 

Thanks so much for your help so far.

 

Cheers

Link to comment
Share on other sites

Hi guys,

 

Any ideas regarding my previous question?

 

Thanks

Link to comment
Share on other sites

Hi elololex,

 

We really do our best to help everyone (paying and non-paying users) understand how the GSAP API works, but it can be quite time-consuming.

Blake is a volunteer around here with many projects of his own and he's already gone above and beyond in helping with this project. There is a fine line between pointing folks in the right direction to solve a problem directly related to the GSAP API and being involved with every aspect of a complex project that comes up. 

Unfortunately we just don't have the bandwidth for the latter. I'm sure if Blake has a quick solution and the time he will help, but I suspect he is very busy and what you are asking for isn't something trivial.

 

I can't fork his private pen, but here is a little something that will help with the buttons.

 

replace the js code in his demo with:

 

var $overflow = $("#overflow");
var $viewport = $(".viewport");
var $wrapper  = $(".wrapper");
var $boxes    = $(".boxes");
var $proxy    = $("<div/>");


var numBoxes  = 100;  
var boxWidth  = 350;
var boxHeight = 250;  
var imgWidth  = boxWidth  - 6;
var imgHeight = boxHeight - 14;
var viewWidth = $viewport.width();
var wrapWidth = numBoxes * boxWidth;
var progress  = 0;


var xMin = 0;
var xMax = 0;


TweenLite.set([$wrapper, $viewport], { height: boxHeight, xPercent: -50 });
TweenLite.set($boxes, { left: -boxWidth });


for (var i = 1; i <= numBoxes; i++) {


  var src = "https://unsplash.it/" + imgWidth + "/" + imgHeight + "?random=" + i;
  var num = $("<div class='num'/>").text(i);    
  var img = $("<img />", { src: src, width: imgWidth, height: imgHeight });
  var box = $("<div class='box'/>").append(img).append(num).appendTo($boxes);


  TweenLite.set(box, { x: i * boxWidth, width: boxWidth, height: boxHeight });
}


var animation = TweenMax.to(".box", 1, {
  x: "+=" + wrapWidth, 
  ease: Linear.easeNone,
  paused: true,
  repeat: -1,
  modifiers: {
    x: function(x, target) {
      x = x % wrapWidth;
      target.style.visibility = x - boxWidth > viewWidth ? "hidden" : "visible";
      return x;
    }
  }
});


var d = Draggable.create($proxy, {
  type: "x",
  trigger: ".wrapper",
  throwProps: true,
  // onDragStart: setRange,
  onDrag: updateProgress,
  onThrowUpdate: updateProgress,
  snap: { 
    x: snapX 
  }
})[0];


$overflow.on("change", applyOverflow);
$(window).resize(resize);


// function setRange() {   
  
//   // We really don't care what the draggable values are. 
//   // We just need a starting point to use in the normalize function
//   // to figure out how much change there has been
//   // xMin = this.x;
//   // xMax = xMin + wrapWidth;
//   // progress = animation.progress();
// }


function snapX(x) {
  return Math.round(x / boxWidth) * boxWidth;
}


function updateProgress() {  
  console.log("update progress")
  animation.progress(this.x / wrapWidth);
}






// function normalize(value, min, max) {
//   return (value - min) / (max - min);
// }


function resize() {
  viewWidth = $viewport.width();
  animation.render(animation.time(), false, true);
}


function applyOverflow() {
  if($overflow.prop("checked")){
    TweenLite.set(".wrapper", {overflow:"visible"});
  }else {
    TweenLite.set(".wrapper", {overflow:"hidden"});
  }
}




function updateDraggable() {
  d.update();
  animation.progress(d.x / wrapWidth);
}
TweenLite.to(d.target, 1, {x:"-=700", onUpdate:updateDraggable, delay:2});

 

Pay attention to the code at the bottom.

 

it illustrates how you can tween the x value on the target of the Draggable named "d" (see line 47) and then create an onUpdate function that updates the Draggable and tween's the progress of the animation that drives the whole thing. It isn't necessarily pretty but its all I had time to do.

 

The animation will start after 2 seconds

 

 

  • Like 3
Link to comment
Share on other sites

Hi Carl,

 

I have been playing around with the code snippet you sent and i am heading in the right direction of achieving the effect we wanted.

 

Thanks so much for all your help. You guys have been super helpful and i do appreciate all the time.

 

Thanks again.

Link to comment
Share on other sites

  • 2 months later...

Yes, you could do the same thing with a mousemove event. I don't have to set that up for you, but you could detect how far from the center of the container the mouse is, and have it set the progress of the timeline based on that.

  • Like 1
Link to comment
Share on other sites

  • 3 years later...
On 8/17/2016 at 1:42 PM, OSUblake said:

 

Remember how I said normalization is key to figuring out most animation problems? Just record a couple of start values and you're good to go. Note that you should not clamp the value because that will prevent it from looping.

 

 

Hi @OSUblake,

Can you point me how to integrate also mouse scroll on this carousel? Thank you

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.
×