Jump to content
GreenSock

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

Struggling with enabling vertical and horizontal scrolling

Recommended Posts

I'm trying to build a site that has a few requirements which include dragging 'cards' vertically and also scrolling them horizontally.

 

Please see here: 

See the Pen Dlmzn by markmacumber (@markmacumber) on CodePen

 

The demo works by adding cards to a bottom aligned panel, that gradually push them out of screen to the right (this site will work on mobile and desktop browsers), I had to use css tables to get it to work with bottom alignment since my width/height variables are very random (since it will be seen on mobile devices of all shapes and sizes) and I cannot hard code div positions using absolute values.

 

As you can see from the demo, this mostly works. I just need to be able to enable horizontal scrolling when the elements get too far outside the viewport.

 

As you can see by the demo, I have tried to create a draggable element, but it screws up the layout...

  scroller = new Draggable(".cardCollection", { type: "scrollLeft", edgeResistance: 0.75 });
Can anyone please help me get this to work? I simpy want to be able to freely scroll the cards horizontally without sacrificing the layout.
 
Perhaps I have fundamentally setup the page wrong?
 
Thanks for any help you can give :)
Link to comment
Share on other sites

Sorry for the late answer, this one slipped away.

 

I believe the main issue is your CSS markup and the fact that you're creating the scroll draggable on the cards parent element.

 

When you add a card the cards parent's(lets call it parent1) width is increased. While parent1 width enhances it disappears to the right side. It is parent1's parent(lets call it mainParent) the one that should have scrollbar appearing, so the scroll change during draggable should be on that one, not the cards parent.

 

Also creating a new draggable instance, when you can use the calibrate method is a little cumbersome.

 

Try the following code:

CSS

#cardsContainer {
    
    height: 100%;
    overflow-x: auto;
    padding-left: 73px;
    padding-bottom: 20px;
}

.cardCollection {
    display: inline-block;
}

JS

var scroller = Draggable.create("#cardsContainer", { type: "scrollLeft", edgeResistance: 0.75 });;

function addItem(){
  var newElement = $.parseHTML('<div class="cardHolder"><div class="productCard"></div></div>');
  $(".cardCollection").prepend(newElement);
  var newDraggable = new Draggable(newElement, {type: "y"}); 
  TweenLite.from(newElement, 1.4, { y: -200, ease: Expo.easeInOut });
  
  scroller[0].scrollProxy.calibrate(true);
}

And let us know how it goes.

 

Rodrigo.

  • Like 1
Link to comment
Share on other sites

Thanks Rodrigo, that's a great.

 

I had to fix up one line of your code:

scroller.scrollProxy.calibrate(true);

(removed the [0])

 

also, now I have a couple of extra problems

 

firstly, now the cards are top aligned, how can I make them bottom aligned? This is one reason why I had the table-layout property set on the cardscontainer class.

 

second, when I scroll horizontally, I dont want to cards to move at all vertically, only horizontally, can this be done?

 

see here for new version:

See the Pen KgIaJ by markmacumber (@markmacumber) on CodePen

 

Thanks again!!

Link to comment
Share on other sites

Hi,

 

This code solves the issue of the elements alignment:

CSS

#cardsContainer {
    height: 100%;
    overflow-x: auto;
    padding-left: 73px;
    padding-bottom: 20px;
}

.cardCollection {
    display: table;
    height: 100%;
}
.cardHolder {
    display: table-cell;
    vertical-align: bottom;
    height: 100%;
    padding-left: 3px;
}

Also there's a div element showing between ".cardCollection" and "#cardsContainer" since that is not in the CSS and doesn't have a height property the styles don't work as expected, so using jquery you can select it and set it's height:

TweenLite.set($("#cardsContainer").children(), {height:"100%"});

The downside of this layout is that you need an extra element in order to prevent activating both draggable instances at the same time, using the trigger var:

var scroller = Draggable.create("#cardsContainer", 
      { 
        type: "scrollLeft", 
        edgeResistance: 0.75,
        throwProps:true,
        trigger:$("#scrollTrigger")
      });

I've forked your codepen so you can see it. The scroll draggable will work only if you drag on the purple element. Also if you drag vertically on that element the card won't move. This is because since your cards has a height of 100% is impossible to not trigger both, since the cards use all the available vertical space in its parent element.

 

See the Pen eCfkb by rhernando (@rhernando) on CodePen

 

Another solution could be to use regular inline-block display for the cards and position them using JS to calculate the correct positioning and GSAP to give the elements that position.

 

Also when you store a draggable instance in a variable and you call on that variable, it returns an array that has the draggable instance in it, most exactly at index 0, that's why my code has [0] in it, in order to get the scrollProxy element and call the calibrate method on it. Without the index it returns an undefined element, which obviously doesn't have a calibrate() method. If you check the console in your codepen you'll see the error.

 

Rodrigo.

  • Like 3
Link to comment
Share on other sites

  • 1 month later...

Hi guys, 

 

Looking at Marks last codepen (

See the Pen KgIaJ by markmacumber (@markmacumber) on CodePen

) is there a way to get the dominant direction x or y and enable or disable the parent or child. So for example:

 

I drag a card to the left so the parent scrolls and disables any children?

Or

I drag a card up so the child scrolls and the parent gets disabled?

 

I have seen this:

onDragStart : function() {
     parent.disable();
},
onDragEnd:function() {
     parent.enable();
}

and it works well for disabling the parent. But it will always disable the parent. So I need to find out if x direction is dominant so i can disable the child and not the parent.

 

Hopefully that makes sense.

 

Thanks,

Chris

Link to comment
Share on other sites

Yep that pretty much does it, glad that you figured it out and thanks for sharing it.

 

Another option is use the onPress and onRelease events. The difference those will trigger immediately while onDragStart will trigger once the element is moved more than 2 pixels in the directions defined in the Draggable instance, just so you can keep those methods in mind if you need them:

 

http://api.greensock.com/js/com/greensock/utils/Draggable.html

 

Although in your particular scenario your solution is the best, since one of the Draggable targets is a children of the other, so basically the onPress and onRelease events will create quite a mess, because the mouse down event will propagate and it'll trigger on both elements, so you'll have to stop the event from bubbling up, but like that you'll never reach the parent element with the event. But if you have a scenario where the child is floating in the parent you could use onPress and onRelease.

 

Rodrigo.

Link to comment
Share on other sites

If anyone else tries to implement it and has issues, I have found that it breaks by adding edgeResistance to the child Draggable

var parent = Draggable.create("#parentContainer", 
{
    type:"x",
    onDragStart:function()
    {
     child[0].disable();
    },
    onDragEnd:function()
    {
      child[0].enable();
    }
});
var child = Draggable.create("#childContainer", 
  {
    type:"scrollTop",
    edgeResistance: 0.75,
    onDragStart:function()
    {
     parent[0].disable();
    },
    onDragEnd:function()
    {
      parent[0].enable();
    }
  });
Link to comment
Share on other sites

Thanks for posting the solution to this ChrisA, really great stuff!

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