martis

render smooth animations on elements inside a force3D:true object

Recommended Posts

Hey guys,

 

Been struggling with this one, would love any suggestions at this point.

 

I am using draggable with throwprops to create a mobile site that can be scrolled with animations (iOS does not allow DOM updates during native scrolling)

 

All my elements inside the force3D:true scroll container animate chunky, but the container itself scrolls beautifully.

 

Can anyone think of a work around method where I can de-couple the elements inside the scroll container so they don't live inside the force3D:true container? I created 2 simple examples below:

 

*** Please use ipad or iphone to view (shows the results clearly)

 

force3D:false on the container: smooth drag animations, sluggish throwProps flick

http://thegeminisociety.com/dragTest_no3D/

 

force3D:true: chunky animations on drag, smooth throwProps flick

http://thegeminisociety.com/dragTest_3D/

 

I feel like I am so close, I really want to figure out how to get the best of both worlds!

Share this post


Link to post
Share on other sites

Sorry for the late response - this one slipped through the cracks. I tried opening both links on my iPad and nothing showed at all. White, blank screen. Refreshed 10 times. Am I doing something wrong?

 

UPDATE: sorry, I just realized that I had to switch orientation - it only works in portrait mode. Stand by...

Share this post


Link to post
Share on other sites

A few ideas for you to try:

  1. Animate the scaleX instead of the width on the child elements (because transforms are much faster for iOS to paint than changing width, calculating reflow, etc.). I'm not sure if this is possible in your real-world scenario. 
  2. Don't nest the objects inside the element that Draggable is controlling - instead, use a transparent element (or an element that's the same color as your background - the point is to make it invisible to the user) and then use an onDrag and/or onThrowUpdate to call a method that moves your REAL elements based on the fake/proxy/invisible element's position. 
  3. I'm not sure if it'd help, but you could use "scrollTop" instead of doing a "y" type. Obviously wrap it in a DIV or something that is sized to the viewport. 

Share this post


Link to post
Share on other sites

Thanks Jack,

 

Really appreciate your advice, I am going to try the things you mentioned above.

 

Quick question: Do you have some sort of list that details which attributes (ie. scaleX vs width) perform better than others? Would be great to know which attributes perform the best, especially on mobile.

 

UPDATE:

 

Good news: I had success using the proxy method... smooth drag, smooth animations/scroll on flick.

 

Bad news: Since I have the proxy dragger on top of my content I am not able to interact with the site layer (click on the first box). If I have put the proxy under the site layer I cannot interact with the proxy :)

 

http://thegeminisociety.com/dragTest_proxy/

 

Performance is good, now to solve the interaction problem. Suggestions? :)

Share this post


Link to post
Share on other sites

Well,

 

I have tried a few things and cannot figure out how to get interactions on a layer UNDER a draggable object or vice versa, how to get interactions on the draggable with a layer OVER it.

 

Is there any hope in using the onClick callback and define the scope of the site? or is that only for child elements of the draggable object?

 

I have an idea to put the drag (without throwprops) functionality on the actual site layer then onDragEnd create a custom throwProps on an invisible bottom 3D layer that moves that layer smoothly and updates the site layer to its position... Not quite sure how to work this out, suggestions on either onClick or this method?

Share this post


Link to post
Share on other sites

Hi,

 

To drag the element under another layer you can use the trigger property in the vars of the draggable instance.

 

Like that you can control the element's drag even without being able to interact with it. You can see a simple example here:

 

http://codepen.io/rhernando/pen/IiHgq

 

Best,

Rodrigo.

Share this post


Link to post
Share on other sites

I got the trigger working... which now allows interaction to come through, but for some reason the trigger (site) is performing like it has force3D:true on it, even though it is only the trigger?

 

Does Draggable automatically make the Drag object AND the trigger force3D true when it updates?

 

Getting closer...   http://thegeminisociety.com/dragTest_proxy2/

// Setup Draggable
function setupDraggable() {

    TweenMax.set($proxy, {css:{height:$site.height()}});
            
    Draggable.create('#proxy', {
        type:"y",
        bounds:$('#proxyContainer'),
        force3D:true,
        trigger:$('#site'),
        zIndexBoost:false,
        edgeResistance:0.5,
        throwProps:true,
    
        onDrag:function () {
            processMobileTimeline(this.y);
        },
                    
        onThrowUpdate:function() {
            processMobileTimeline(this.y);     
        },
    
    
    });

    //TweenMax.set($proxy, {force3D:true});    
}

Share this post


Link to post
Share on other sites

Hi,

 

What I think could be the reason is that even if the element and the trigger are two different DOM element they're both targets of the same draggable instance and since the instance has a force3D:true var in it, this applies for every target.

 

Maybe you could try a TweenMax.set() instance to change the force3D of the trigger using the onDragStart callback. Although, and here we're going to need Carl's or Jack's advice, I don't know if in the next update of the draggable instance the force3D will come back to true.

 

Best,

Rodrigo.

Share this post


Link to post
Share on other sites

Thanks Rodrigo,

 

Will give this a shot! Is there a way to check the force3D setting on an object?

 

UPDATE: I tried this and am still seeing that the Site Layer is rendering as if its a force3D:true object

 

http://thegeminisociety.com/dragTest_proxy4/

// Setup Draggable
function setupDraggable() {
	
	TweenMax.set($proxy, {css:{height:$site.height()}});
				
	Draggable.create('#proxy', {
		type:"y", 
		bounds:$('#proxyContainer'),
		force3D:true,
		trigger:$('#site'),
		zIndexBoost:false,
		edgeResistance:0.5, 
		throwProps:true,
		
		onDragStart:function () {
			TweenMax.set($site, {force3D:false});	
		},
		
		onDrag:function () {
			processMobileTimeline(this.y); 
			TweenMax.set($site, {force3D:false});	
		}, 
						
		onThrowUpdate:function() {
			processMobileTimeline(this.y); 	
			TweenMax.set($site, {force3D:false});	
			
		},
		
		
	});
}

Jack, any clue why the trigger is performing like a force3D object? Thanks.

Share this post


Link to post
Share on other sites

I just tried your code with the latest version of Draggable and I can't seem to replicate that behavior - could you post a simple codepen or jsfiddle that demonstrates the issue? 

Share this post


Link to post
Share on other sites

Hey, this issue resolved with the new draggable... thanks

  • Like 1

Share this post


Link to post
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.