Jump to content
GreenSock

mathias5

Change element

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

In an init() function i declare these two tweens. 

var tweenLeft = new TweenLite.to($(".card"), 0.6, { rotationY: '+='+rotVal, transformStyle:"preserve-3d",ease:Back.easeOut,perspectiveOrigin:'50% 50% 0px', paused:true, perspective:1000});
var tweenRight = new TweenLite.to($(".card"), 0.6, { rotationY: '-='+rotVal, transformStyle:"preserve-3d",ease:Back.easeOut,perspectiveOrigin:'50% 50% 0px', paused:true,perspective:1000});
        

Later on in a drag() function i run this to start the tweens:

tweenRight.restart();
tweenLeft.restart();

When i start to drag the ".card" all of them gets the tween. I have 20 of these cards and want the tween to be applied individually on each of them. Is it possible to somehow on the fly just change the element in the tween?

 

Link to comment
Share on other sites

Hello.. im trying to understand what your trying to do.. i see that you are using a class as your target element, which would target all elements with that class. You might have to pass a this reference to it so it only targets that specific .card element

 

is it possible to create a reduced example codepen or jsfiddle of your issue so we can better see the exact issue your having?

 

See the Pen by pen (@pen) on CodePen

http://jsfiddle.net

 

thx :)

  • Like 1
Link to comment
Share on other sites

Hi,

 

thanks for your answer. The thing is that i can't pass THIS. thats because i run the tweens in a jquery draggable and the tweens is declared outside of that scope. I can try to put it on a fiddle.

Link to comment
Share on other sites

Here is a fiddle. What i need help with is so i can run the tweens multiple elements of the class.

Lets say I'm looping out 20 cards. Then i want the tweens to be applied individually.

 

http://jsfiddle.net/nPM5V/

Link to comment
Share on other sites

have you tried setting a global this variable?

 

basically you can setup a global $card variable and a click event. .. Every time .card is clicked, the $card variable will be set to the current .card element

var $card = $(".card:first");

$("body").bind("click", ".card", function(){
    $card = $(this);
    return false;
});

// use $card instead of card variable in the to() target
var tweenLeft = new TweenLite.to($card, 1, { rotationY: '-=180', transformStyle:"preserve-3d",ease:Back.easeOut,perspectiveOrigin:'50% 50% 0px', paused:true, onComplete:function(){}});
var tweenRight = new TweenLite.to($card, 1, { rotationY: '+=180', transformStyle:"preserve-3d",ease:Back.easeOut,perspectiveOrigin:'50% 50% 0px', paused:true, onComplete:function(){}});

// draggable code goes here

I noticed your example only had one .card element... so i couldn't really see what your trying to achieve..

 

also you could try placing your Tweens inside your draggable events. Is it possible to add another .card element to your jsfiddle so we can see more what your trying to do when multiple .card elements are on the page and dragged

 

thx

  • Like 1
Link to comment
Share on other sites

Hi,

 

Thanks!

Here is an updated example with 3 cards. Now you can more see what the problem is. When dragging a card and the flip-tween runs it flips all cards. Its suppose to only flip the current.

 

http://jsfiddle.net/AFU3T/11/

Link to comment
Share on other sites

Hi,

 

Maybe you could create a loop and assign every card it's own draggable instance. Right now you're adding the same draggable instance to all the elements contained in the JQuery object, so when the event is triggered it affects all the elements in the JQuery object (which in this case acts like an array).

 

Try something like this:

$.each($(".cardContainer"), function(index, element)
{
  $(element).draggable
  ({
    //Draggable stuff here
  });
});

And as Jonathan suggested put the tweens inside the draggable callback or create a function to call the tweens passing the target and rotation direction as arguments to the tween.

 

Keep in mind too that by default the transform origin values are "50% 50% 0px" so there's no need to define that and pass the extra code to the CSS plugin, just in case you have more things tweening in your app.

 

Also never use the same ID in more than one element, that's a very important no-no when it comes to coding (whether is JS, AS, PHP, etc), ID's should be unique and are useful to identify every element independently of the rest, while classes are useful when the code must be applied in more than one object, independent of it's ID.

 

Rodrigo.

  • Like 1
Link to comment
Share on other sites

Hi,

 

I've tried to make it a loop instead but it did not work. The problem was the same.

 

I can't put the tweens in the draggable callback since i do -=180 and +=180 in the tweens which will make the element to move continuously.

 

Hm,to create a function and pass target and rotation sound like the way to go maybe. How would i do that?

Link to comment
Share on other sites

Hi,
 
Remember that you have this on your code:

if(tweenLeft.isActive() || tweenRight.isActive())
{
  return false;   
}

So basically if any tween is being played no other will be triggered, so instead of checking if the tween is active you can check if the target element is being tweened using the isTweening() method:

if(TweenMax.isTweening($this))
{
  return false;
}

Now you just create a global function that handles the tween:

function rotateCard(target, angle)
{
  TweenLite.to(target, 1, { rotationY: angle, transformStyle:"preserve-3d",ease:Back.easeOut, paused:true);
}

Finally in the draggable function instead of calling tweenLeft or tweenRight you call the function and pass the target (that'll be the card being dragged) and the angle (which will depend on the drag direction), like this:

if(dirX == "right")
{
  rotateCard($this, '+=180');
}

if(dirX == "left")
{
  rotateCard($this, '-=180');
}

Like only the current card being dragged will rotate and you avoid the behaviour you get by using restart(), which basically takes the tween to the starting point everytime, so it doesn't seems to be a continuous rotation.
 

function rotateCard(target, angle)
{
  TweenLite.to(target, 1, { rotationY: angle, transformStyle:"preserve-3d",ease:Back.easeOut, paused:true, onComplete:function(){});
}

$.each($(".cardContainer"), function(index, element)
{
$(element).draggable({
    helper: function(){
        return $('<div></div>').css('opacity',0);
    },
    start: function(event,ui){
        xPos = ui.helper.position().left;
        yPos = ui.helper.position().top;
    },
    create: function(){
        var $this = $(element);
        $this.css("z-index", z++)
        $this.data('starttop',$this.position().top);
        $this.data('startleft',$this.position().left);
    },
    drag: function(event, ui){
        $(element).stop().animate({
            top: ui.helper.position().top,
            left: ui.helper.position().left
        },500,'easeOutCirc',function(){
            
        });
      
        if(prevXPos > event.pageX) {
            dirX = "left"; 
        }
        else if(prevXPos < event.pageX) { 
            dirX = "right";
        }
        prevXPos = event.pageX;
        
        if(TweenMax.isTweening($this))
        {
           return false;
        }
      
        if(dirX == "right")
        {
           rotateCard($this, '+=180');
        } 
        if(dirX == "left")
        {
           rotateCard($this, '-=180'); 
        }    
    },

    start: function( event, ui ) {
        prevXPos = event.pageX;
        dirX = "";
    }
});
}

I also took the liberty to remove some stuff from your code that aren't needed like the transform origin and the empty onComplete call.

 

Give that code a try and let us know.

 

Rodrigo.

  • Like 1
Link to comment
Share on other sites

Hi, thank you!

 

I have tested your code now. When i now start to drag one card i get this error:

 

ReferenceError: $this is not defined. Its on line 38 in your code, the if statements.

Any idea?

if(TweenMax.isTweening($this))
Link to comment
Share on other sites

Doh!!!

 

I forgot to add the closing bracket on the each loop and the tween in the rotateCard function tween.

 

Also you have this in the code:

create: function(){
        var $this = $(this);
        $this.css("z-index", z++)
        $this.data('starttop',$this.position().top);
        $this.data('startleft',$this.position().left);
    },

But z is not defined, thus breaking the loop, I corrected all those errors and is working now:

 

http://jsfiddle.net/AFU3T/22/

 

You still need to tinker a little bit the z-index  in order to get the current card on top of the rest though, but is a minor tweak.

 

Rodrigo.

  • Like 1
Link to comment
Share on other sites

I haven't had time to read through this whole thread (let me know if you still need help), but I did notice something early on that I wanted to point out:

//BAD (invalid):
var tweenLeft = new TweenLite.to(...);

//GOOD:
var tweenLeft = new TweenLite(...);

//ALSO GOOD:
var tweenLeft = TweenLite.to(...);

You can either use "new TweenLite(...)" or "TweenLite.to(...)" but you cannot combine them. Remember, TweenLite.to() returns a new TweenLite instance. 

 

Again, I haven't had time to read all the responses but I assume you guys have it figured out - let me know if you still need help with something. 

  • Like 1
Link to comment
Share on other sites

Hi,

 

Rodrigo's last answer did the job! Thank you guys!

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