Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Gary Horsman

Concatenating a relative percentage value for tweening

Recommended Posts

I'm not sure how to concatenate a percentage value into a GSAP tween.
 

buttonBritney.addEventListener("click", function() {
callSlideIndex = 0;
var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
TweenLite.to(slideContainer, 2, {left:"\"" + leftPercentage + "%" + "\""});
currentSlideIndex = 0;
}, false);

 
So far, this doesn't work. Maybe there's something in the syntax I'm doing wrong?

 

I realize that we cannot use absolute percentage values, but we can use relative percentages. So I'm trying to calculate a percentage mathematically before entering into the tween function. But I assume there should be quotes added that need to be escaped with a percentage symbol just before the ending quote. But this doesn't seem to have any effect.

 

Your help is appreciated.

 

LONGER, DETAILED EXPLANATION FOR CONTEXT

 

I have a webpage with an image that must fill up the full width of the window. But, there are five more images off-screen that need to be called by a series of buttons along the bottom. Each button calls up a different image and that image should slide into place, taking up the full width of the viewport.

 

I managed to do this by placing the six slides inside a slide container set to 600% the width of a div that is itself 100% of the browser window. Let's call that the slide viewport. It's big enough to just show one slide at a time.

 

In the CSS, I set the slide viewport to overflow=hidden. By setting the left value to a multiple of 100%, I can shift the slide container so that a single slide fits right inside the viewport. Left: -100% shows the second slide, left:-200% shows the third slide, and so on.

 

But I can't specify

TweenLite.to(slideContainer, 2, {left:-100%});

because that's not permitted. But depending on which slide is currently showing and which one is next being called, I need an absolute percentage value, not a relative one. Thus, I came up with a formula that figures out a percentage value by assigning index numbers to each slide and then plugging that value into the tween.

 

But it doesn't seem to work. I suspect it's a syntax problem, but I'm not sure how GSAP concatenates relative values, especially if it's a calculated percentage value.

 

For context, here's the HTML/CSS

... DOCTYPE ...
<title>GSAP test</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>
<script src="js/gsap_test_07.js"></script>

<style type="text/css">
body {
background-color: #000;
margin: 0px;
padding: 0px;
width: 100%;
}
#slideviewport {
margin: 0px;
padding: 0px;
width: 100%;
overflow: hidden;
}
#slidecontainer {
width: 600%;
position: relative;
}
.slideimage {
width: 16.65%;
float: left;
}
#nav {
width: 100%;
}
#nav img {
width: 16.65%;
cursor: pointer;
}
</style>
</head>

<body>
<div id="slideviewport">
  <div id="slidecontainer">
... six slide images ...
  <!--ends div#slidecontainer --></div>
<!--ends div#slideviewport --></div>
<div id="nav">
... button images ... 
  <!--ends div#nav --></div>
</body>
</html>

 

And here's the JS

// JavaScript Document


//in order to get all the JS actively running, you must 'init' upon window load
window.onload = init;


//enclose all functionality inside the init function and wrap around everything
function init() {


//establish variable for slide container
var slideContainer = document.getElementById("slidecontainer");


//establish variable for slide index numbers
var currentSlideIndex = 0;
var callSlideIndex = 0;
var leftPercentage;


//establish all variables for buttons
var buttonBritney = document.getElementById("imgButtonBritney");
var buttonKesha = document.getElementById("imgButtonKesha");
var buttonAmy = document.getElementById("imgButtonAmy");
var buttonYeller = document.getElementById("imgButtonYeller");
var buttonOlivia = document.getElementById("imgButtonOlivia");
var buttonReclined = document.getElementById("imgButtonReclined");


//animate slides in accordance with buttons pressed in navigation
buttonBritney.addEventListener("click", function() {
callSlideIndex = 0;
var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
TweenLite.to(slideContainer, 2, {left:"\"" + leftPercentage + "%" + "\""});
currentSlideIndex = 0;
}, false);


buttonKesha.addEventListener("click", function() {
callSlideIndex = 1;
var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
TweenLite.to(slideContainer, 2, {left:"\"" + leftPercentage + "%" + "\""});
currentSlideIndex = 1;
}, false);


buttonAmy.addEventListener("click", function() {
callSlideIndex = 2;
var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
TweenLite.to(slideContainer, 2, {left:"\"" + leftPercentage + "%" + "\""});
currentSlideIndex = 2;
}, false);


buttonYeller.addEventListener("click", function() {
callSlideIndex = 3;
var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
TweenLite.to(slideContainer, 2, {left:"\"" + leftPercentage + "%" + "\""});
currentSlideIndex = 3;
}, false);


buttonOlivia.addEventListener("click", function() {
callSlideIndex = 4;
var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
TweenLite.to(slideContainer, 2, {left:"\"" + leftPercentage + "%" + "\""});
currentSlideIndex = 4;
}, false);


buttonReclined.addEventListener("click", function() {
callSlideIndex = 5;
var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
TweenLite.to(slideContainer, 2, {left:"\"" + leftPercentage + "%" + "\""});
currentSlideIndex = 5;
}, false);


//closing brace for init
}
Thanks!
Link to post
Share on other sites

when concatenating you don't need to escape the quotes in the beginning or end of your variable:

buttonBritney.addEventListener("click", function() {
       callSlideIndex = 0;
       var leftPercentage = (callSlideIndex - currentSlideIndex) * 100;
      
       // try this - just the variable and your concatenated string
       TweenLite.to(slideContainer, 2, {left: leftPercentage + "%"});
        
       currentSlideIndex = 0;
}, false);

to test if the number is negative you can check using this:

// check if number is negative
if(number < 0)
    // number is negative
}

is that what you mean ?

 

http://www.quirksmode.org/js/strings.html

  • Like 1
Link to post
Share on other sites

Thanks, Jonathan.

 

Will that produce a value of left:-100% or left:"-100%"? If it's the former, it won't work.

 

I should note that the leftPercentage should probably be multiplied by -100 and not 100. 

 

Also, I've been doing some searching around and found

See the Pen bysgL by bassta (@bassta) on CodePen

that I may be able to apply. I'll update after I try it out.

Link to post
Share on other sites

ok hopefully that alternate solution works!

  • but is their a reason why you cant just get the width of the slide,  and then animate positive left, and/or animate negative left depending on the slide ??
  • is the only direction the slides moving in is on the X axis.. basically moving east and west?
  • is there a way to setup a limited

    See the Pen by pen (@pen) on CodePen

    or jsfiddle so we can see how the slides are animating?

:)

Link to post
Share on other sites

The viewport container for the slides is actually 100% the width of the browser window, so there is no specified pixel width. If it were in pixels, my problem would be solved!

 

Each slide is 1/6 (or about 16.66667%) of the slide container, and that slide container is 600% of its parent container which acts like a viewport with a scrolling overflow and THAT viewport is the one that's 100% of the browser window. So everything has to resize inside a liquid layout. That's what the client has requested.

 

Yes, the slides are moving only on the x-axis.

 

Unfortunately, I've never set up a codepen or jsfiddle page, though the link in my last post is a codepen page. But I'm thinking the solution offered there is a much more elegant solution to making the proper conversion between percentages and pixels than my little disaster :(

 

If it works, I'll post the solution adapted to my situation.

Link to post
Share on other sites

Just to clarify:

leftPercentage = -100;
TweenLite.to(slideContainer, 2, {left: leftPercentage + "%"});
//is identical to
TweenLite.to(slideContainer, 2, {left: "-100%"});

Quotes just identify the inside content as a string. Concatenating 2 strings (or a number and a string) still gives a string. It doesn't need quotes added to it again.
 
Also, in javascript single and double quotes perform identical function, you don't have to stick solely to double quotes (except for defining strings in JSON). If you want to make a string that also has quotes in it (not required here though) you can mix them to avoid escaping:
 

"'" + leftPercentage + "%" + "'" // '-100%'
// or
'"' + leftPercentage + '%' + '"' // "-100%"
  • Like 4
Link to post
Share on other sites

Thanks, Jamie. But unfortunately, your examples don't work as expected.

 

This works, kind of.

TweenLite.to(slideContainer, 2, {left: leftPercentage + "%"});
 
But here's the weird part. It animates the container using percentage as an absolute value, not relative. So that when leftPercentage returns a value greater than 0, like 100% or 200%, the whole container slides to the right and off the screen. That's quite bizarre as I thought TweenLite doesn't accept absolute percentage values for left: or x:
 
Knowing this, I might leverage this quirk to pass an absolute percentage value into the tween as a variable without doing any fancy calculations. Otherwise, the calculations work as expected.
 
I'll be reporting back soon.
Link to post
Share on other sites

Success!

 

//establish current slide index at start
var leftPosition;


//animate slides in accordance with buttons pressed in navigation
buttonBritney.addEventListener("click", function() {
leftPosition = 0;
TweenLite.to(slideContainer, 2, {left:leftPosition + "%"});
}, false);


buttonKesha.addEventListener("click", function() {
leftPosition = -100;
TweenLite.to(slideContainer, 2, {left:leftPosition + "%"});
}, false);


buttonAmy.addEventListener("click", function() {
leftPosition = -200;
TweenLite.to(slideContainer, 2, {left:leftPosition + "%"});
}, false);


buttonYeller.addEventListener("click", function() {
leftPosition = -300;
TweenLite.to(slideContainer, 2, {left:leftPosition + "%"});
}, false);


buttonOlivia.addEventListener("click", function() {
leftPosition = -400;
TweenLite.to(slideContainer, 2, {left:leftPosition + "%"});
}, false);


buttonReclined.addEventListener("click", function() {
leftPosition = -500;
TweenLite.to(slideContainer, 2, {left:leftPosition + "%"});
}, false);

As it turns out, putting the percentage value after the left: attribute creates an error. But passing the value into a variable and adding the "%" string is allowed.

 

Many thanks for all your help. You all contributed to the final answer that dug me out of this hole.

Link to post
Share on other sites

Hmm, it sounds like there might be some confusion as to what absolute and relative positioning is - GSAP isn't choosing relative or absolute positions of left for you. If your CSS says #slidecontainer { position:relative }, then left will be a relative value from #slidecontainer's default position. Perhaps something like this will be of use to you.  

 

Percentages are calculated from the width of the containing block. In your case, #slidecontainer width is 100% of #slideviewport, which is 100% of body. A value of left:100% on #slidecontainer will move it as many pixels as the window is wide.

 

Also, by:

As it turns out, putting the percentage value after the left: attribute creates an error. But passing the value into a variable and adding the "%" string is allowed.

Do you mean that you tried something like { left: -100% } which created an error and { left: -100 + "%" } was allowed? If so thats just the way javascript works - number literals can't be given units like px or % without being in a string. I thought we had been discussing to do it that way in the first place?

 

Anyway, looks like you sorted it all out. Nice work.

  • Like 2
Link to post
Share on other sites

Oh, I do understand the concept of relative positioning. I originally wanted to position the container from the left as a percentage of the parent div since the layout is scaled to the full width of the browser window. But using "-100%" would only slide the container one slide to the left rather than sliding it to the -100% position, which is where the second slide is exposed (0% for the first slide, -200% for the third slide and so on).

 

I would get errors trying to use -100% without the quotes, but I believed that was because it wasn't supported by the GSAP platform based on the articles I read. Someone found a way to convert percentages to pixels to overcome that limitation', even. But as you pointed out, the percentage has to be placed inside a string.

 

I didn't want to use this forum to be a tutorial for JavaScript, though I am still a beginner-intermediate scripter. If quoted and unquoted values have different effects on an animation, how does that all jive with percentages if you can quote it for relative movement but an error gets thrown up unquoted for a fixed location.

 

Anyway, I learned a lot and appreciate the help.

Link to post
Share on other sites

Just to be clear, to specify a relative end value (regardless of px, % or any unit) the value must not only be a String but use the += and -= notation. http://www.greensock.com/jump-start-js/#relative-tweens

 

For example imagine obj has a left:300px prior to each of the following tweens running:

TweenLite.to(obj, 1, {left:"+=25px"});// tweens to 325px

TweenLite.to(obj, 1, {left:"25px"});// tweens to 25px

The same will work for relative percentages as shown here: http://codepen.io/GreenSock/pen/b9cc32defd0eb89757156dee4c8c4591

  • Like 1
Link to post
Share on other sites

Just to be clear, to specify a relative end value (regardless of px, % or any unit) the value must not only be a String but use the += and -= notation. http://www.greensock.com/jump-start-js/#relative-tweens

 

For example imagine obj has a left:300px prior to each of the following tweens running:

TweenLite.to(obj, 1, {left:"+=25px"});// tweens to 325px

TweenLite.to(obj, 1, {left:"25px"});// tweens to 25px

The same will work for relative percentages as shown here: 

See the Pen b9cc32defd0eb89757156dee4c8c4591 by GreenSock (@GreenSock) on CodePen

Thanks, Carl. This is very informative and clearly demonstrated.

Link to post
Share on other sites

Ah, very nice and responsive. Good Job!

  • Like 1
Link to post
Share on other sites

Ah, very nice and responsive. Good Job!

Thanks to all you guys at Greensock for making a rock-solid animation platform and making all our lives that much easier!

  • Like 1
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.

×