0

I am a Jquery novice, and would have thought the solution to my problem to be quite simple, however I have tried a million permutations of this code and I can't solve it.

I am using Scrollmagic and GSAP, and want to trigger three tweens from the same point, so that they fire one after the other (with a slight overlap). The scenes have duration: 0 so that the user only starts the animation, but does not control its progress. Each tween contains a css transform, to work on the same object (#boxes3d).

The effect I am going for is :
1) The boxes start flat, but are exploded into 3D by changing the css perspective value to 850px.
2) The boxes rotate 180 degrees by changing the css transform value.
3) The boxes are collapsed again by reverting to perspective: 50000.
[ 4) The animation reverses when the user scrolls back past the trigger.]

The complication is that the transform value must also incorporate a dynamic scale value in order to make the absolutely positioned divs inside #boxes3d fit the frame at any screen size. The scale value (and therefore the whole transform) is set dynamically by another Jquery function: scaleDiv() which contains the nested rotate3D() and reverse3D() functions.

I think I need to create a timelineMax (or Lite) to queue the tweens, but I am having problems putting dynamic css values into the timeline.

I have created a jsfiddle with the tweens/transitions that I want to string together, along with the scaleDiv function that must be incorporated into the second tween. At present they have separate scenes, but I want to put them all into one scene/timeline.

Here is the fiddle: http://jsfiddle.net/gbinning/vccxufou/13/. I would really really appreciate some guidance! Thank you v much!

Edit: I haven't quite set up the scaleDiv function correctly, you need to slightly resize the window to trigger it.

GBin
  • 31
  • 7
  • Take a look at **[this](http://jsfiddle.net/tahirahmed/rkapdyud/2/)**. It doesn't account for `window.resize` yet but I wanted to know if I was going in the right direction. Let me know if you want me to continue. – Tahir Ahmed Nov 10 '15 at 18:14
  • Looking now, will report back asap. Thanks Tahir – GBin Nov 10 '15 at 18:18
  • .. neither does it accommodate the `rotate3D`, `reverse3D` and `scaleDiv` methods you had. I am still trying to figure out what exactly are you trying to achieve in order to present you with an alternative approach. – Tahir Ahmed Nov 10 '15 at 18:25
  • I think I confused you when I said explode - I don't want the faces of the boxes to break apart - just for the depth of the boxes to be revealed when the perspective changes. So I'm happy with the transitions on the fiddle I posted, but the problem I have been having is including dynamic values - ie the `translateX(' + parentWidth + 'px) ` and `scaleY(' + scale + ') scaleX(' + scale + ')` - inside the tween. I then want to join the three scenes together using a timeline so there is only one trigger and a duration of 0px (but should run for a few seconds). _continued in next comment..._ – GBin Nov 10 '15 at 18:39
  • Your code looks much more promising than mine though - am I right in thinking it works more quickly if you set the css values with `TweenMax.set`? In order to see `rotate3D` / `reverse3D` working you have to slightly resize the window before scrolling past the second trigger - though the function should really be called at the same time as the `scaleDiv` function at `window.onload` - it's just my crumby coding. – GBin Nov 10 '15 at 18:47
  • I figured I would have to scale `boxes3D` dynamically depending on window size because the child divs are absolutely positioned and have fixed px values, but then the css scale instruction is included with the other transforms and cannot be set independently from the `rotateX(-180deg) rotateZ(-180deg)` values - and that's how I got into this mess. – GBin Nov 10 '15 at 18:53
  • I kind-a get what you mean. Let me give it a few more tries. Will get back. Re using `TweenMax.set`, I have personally found that it is always best to let `TweenMax` handle all of the styling, including the initial ones. I just find it a bit easier to manage, and it avoids conflicts later on. Plus, I always try not to mingle CSS' `transitions` with tweens from `TweenMax`. That just produces confusing results in final outputs of animations. When `TweenMax` is there, it is best to let it handle all of it. – Tahir Ahmed Nov 10 '15 at 19:17
  • Yes I see. I have suffered this confusion which you mention acutely! – GBin Nov 10 '15 at 19:28
  • One more thing. My `ScrollMagic` knowledge is a bit meh! if you are looking into triggering animations at certain points while scrolling, may I suggest to simply use `scroll` events of `window` object (with _debouncing_ of course) or is there any particular reason of using `ScrollMagic` that I am not able to see? Also, I find that having an HTML `div` element layer on top of `boxes3d` element would help in order to control `scale` (and `rotate` etc) and let `boxes3d` only handle the change in `perspective` animation. This way, you have dedicated layers. Does that make sense? – Tahir Ahmed Nov 10 '15 at 19:40
  • The fiddle I have put up is actually just a small part of a scrolling animation I am making - which pretty much requires `scrollmagic`. For your interest here is the fiddly for the full thing : http://jsfiddle.net/gbinning/5mahcv3L/ . I see what you mean about the dedicated layers, if it works, and the effect is the same, then that is probably the way to go... – GBin Nov 10 '15 at 19:52
  • Understood. Let me see what I can do. – Tahir Ahmed Nov 10 '15 at 20:23
  • Hey Tahir, did you get any further with it? If you've given up let me know, but otherwise please don't waste too much of your time on this problem! – GBin Nov 12 '15 at 18:23
  • Got busy afterwards. I will try to tackle this over the weekend. It is an interesting problem. But yeah, don't keep your hopes high. – Tahir Ahmed Nov 12 '15 at 19:23
  • Ok cool, really appreciate everything you've done so far, and value your help on this one. – GBin Nov 13 '15 at 21:55
  • If you can't solve the dynamic tween problem, please let me know the issue, so that I can carry on where you left off. Cheers. – GBin Nov 13 '15 at 21:58
  • progress: **[link](http://jsfiddle.net/tahirahmed/rkapdyud/6/)**. cannot really explain for now because it is still work in progress. the idea though is to first create the desired final state (i.e. how the cubes will look like when `perspective` is animated) and to place them properly and exactly on those positions. – Tahir Ahmed Nov 15 '15 at 18:33

2 Answers2

0

So you want it to rotate, transform and scale, dynamically? I'm doing the same thing in my project.. here's how I do it. Maybe it will help you.

http://jsfiddle.net/xko7gjty/1/

$("#abox").addClass("rotate");

var dynamicx = Math.random()*300;
var dynamicy = Math.random()*300;
var dynamicscale = Math.random();
var tween = new TweenMax("#abox", 1, {
            top: dynamicx+"px",
            left:dynamicy+"px",
            scale:dynamicscale,
            //ease: Linear.easeNone,
            delay:.2
        }); 

FYI, you have to create a new tween every time. The way gsap works is, when you create a tween, it uses the CSS values at that moment. If you changed your css, the original tween will only do the original location

john k
  • 6,268
  • 4
  • 55
  • 59
0

*If you don't want my story go to the bottom marked with Bold for a short answer. The person who posted this question might have long forgotten about this question, but for anyone to come here, this is my solution. I will be using gsap3 in my answer as that is the current. I was working on a scroll-based animation when I came across this problem. What I wanted to do in my animations as you might see in the code is have an entry animation on a div based on a scroll. The problem is the following CSS

transform: translate(314.18px, 244.9px) rotate(295deg) 

should have different x and y coordinates depending on the screen size. So for example, if the user started on a full screen and then resized the window that would distort the animation, so I would like to update the coordinates on window resize. To solve the problem, I set the x and y coordinates to be returned values of different functions width() and height() hoping the gsap.to function will store the function as its value in the key-value pair but as mentioned in the above answer not only does it store variable values once but it turns out it also stores the returned value of functions rather than the functions themselves, so I tried something else. That is to put all the animation in one function and call it every time the window is resized. The before and after code looked like the following.

Before the solution

var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
var vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
function updateDimention() {
    vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
    vh = Math.max(document.documentElement.clienthHeight || 0, window.innerHeight || 0)
}
window.onresize=updateDimention;
let height = function(){return vh};
let width = function(){return vw};

gsap.registerPlugin(ScrollTrigger, MotionPathPlugin);
const entryAnim = gsap.timeline(
        {
            scrollTrigger:{
                scrub:true,
                pin:true,
                trigger:".main",
                start:"top top",
                end:"+=6000px",
            },
            // yoyo:true,
        }
        );
        entryAnim.pause()
        entryAnim.to(
            ".pic1",{
            motionPath:{
                path:[{x:0,y:0,},{x:0.155*width(),y:0.2*height()},{x:0.18*width(),y:0.25*height()},{x:0.23*width(),y:0.395*height()}],
                // type:"cubic",
                autorotate:true,
            }, 
            
        }).to(
            ".pic2",{
            motionPath:{
                path:[{x:0.18*width(),y:0,},{x:0.15*width(),y:0.21*height()},{x:0*width(),y:0.40*height()},{x:-0.000503*width(),y:0.75*height()}],
                // type:"cubic",
                autorotate:true,
            }, 
        
        }).to(
            ".pic3",{
            motionPath:{
                path:[{x:-0.15*width(),y:-0.10,},{x:-0.10*width(),y:-0.5*height()},{x:0*width(),y:0*height()},{x:0.4245*width(),y:0.324*height()}],
                // type:"cubic",
                autorotate:false,
            }, 
        
        })
        
        
        const rotationAnim = gsap.timeline(
        {
            scrollTrigger:{
                trigger:".main",
                start:"top top",
                end:"+=6000px",
                pin:true,
                scrub:true
            },
            // yoyo:true,
        }
        );
        rotationAnim.pause()
        rotationAnim.to(".pic1",{
            rotation:295,
        }).to(
            ".pic2",{
                rotation:329,
            }
        ).to(".pic3",{
            rotation:48,
        })

After the solution

var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
var vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
function updateDimention() {
    vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
    vh = Math.max(document.documentElement.clienthHeight || 0, window.innerHeight || 0)
}
let height = function(){return vh};
let width = function(){return vw};

gsap.registerPlugin(ScrollTrigger, MotionPathPlugin);
function Animation(){
    const entryAnim = gsap.timeline(
        {
            scrollTrigger:{
                scrub:true,
                pin:true,
                trigger:".main",
                start:"top top",
                end:"+=6000px",
            },
            // yoyo:true,
        }
        );
        entryAnim.pause()
        entryAnim.to(
            ".pic1",{
            motionPath:{
                path:[{x:0,y:0,},{x:0.155*width(),y:0.2*height()},{x:0.18*width(),y:0.25*height()},{x:0.23*width(),y:0.395*height()}],
                // type:"cubic",
                autorotate:true,
            }, 
            
        }).to(
            ".pic2",{
            motionPath:{
                path:[{x:0.18*width(),y:0,},{x:0.15*width(),y:0.21*height()},{x:0*width(),y:0.40*height()},{x:-0.000503*width(),y:0.75*height()}],
                // type:"cubic",
                autorotate:true,
            }, 
        
        }).to(
            ".pic3",{
            motionPath:{
                path:[{x:-0.15*width(),y:-0.10,},{x:-0.10*width(),y:-0.5*height()},{x:0*width(),y:0*height()},{x:0.4245*width(),y:0.324*height()}],
                // type:"cubic",
                autorotate:false,
            }, 
        
        })
        
        
        const rotationAnim = gsap.timeline(
        {
            scrollTrigger:{
                trigger:".main",
                start:"top top",
                end:"+=6000px",
                pin:true,
                scrub:true
            },
            // yoyo:true,
        }
        );
        rotationAnim.pause()
        rotationAnim.to(".pic1",{
            rotation:295,
        }).to(
            ".pic2",{
                rotation:329,
            }
        ).to(".pic3",{
            rotation:48,
        })
}

Animation()
function updateAnimation (){
    updateDimention();
    Animation();

}

window.onresize=updateAnimation;

In short

so as a conclusion what you want to do is the following,

function Animation(){
        //in here put all your gsap related animations
    }
    //then down here call the Animation function every time values are changed so that
    //the gap animation can be redefined. In this case I am going to do it in window resize.
    window.onresize = Animation;
EHM
  • 877
  • 1
  • 7
  • 28