Jump to content
Search Community

Spinning Wheel SVG

ram0409 test
Moderator Tag

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

Hi, I am trying to create a spinning wheel with 14 elements and it doesn't work. Here is my html code

 

<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>Spinning wheel with svg text</title>
  <link rel="stylesheet" href="css/style.css">
</head>

<body>
      <section class="full-screen">
        <div class="wheel-03">
            <svg preserveAspectRatio="xMinYMin meet" class="wheel-svg" version="1.1"
                 width="800" height="400"
                 viewBox="0 0 800 400">
                <g transform="translate(0,0)">
                    <g transform="translate(0,250)" class="wheel-container">
                        <text x="0" y="-225" class="term term00">SMELL</text>
                    ...
                  
                </g>
            </svg>
        </div>
    </section>
  <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js'></script>

    <script src="js/index.js"></script>

</body>
</html>

 

 

And here is my js code

 

$(window).load(function () {
 
      var term01 = $('.wheel-03 .term01');
    var term02 = $('.wheel-03 .term02');
    var term03 = $('.wheel-03 .term03');
    var term04 = $('.wheel-03 .term04');
...

    var stepFrame = 1

 
      // css classes
    tl01 = new TimelineLite();
    tl01
    ...

    
    
    
    
    tl14 = new TimelineLite();
    

...


    .to(term26, stepFrame, {

            attr: {y: '-=75'},
            ease: Linear.easeNone
        })
    ; */

    var wheelTurn = 0.3;

    wheel03 = new TimelineMax({repeat: 50, timeScale: 3});
    wheel03.add(tl01, 0);
    
 ...
    wheel03.add(tl26, 0);
    wheel03.play();

    TweenMax.to(wheel03, 0.1, {timeScale: 10, ease: Circ.easeOut})
    TweenMax.to(wheel03, 4.9, {timeScale: 5, delay: 5, ease: Circ.easeOut})
});

 

Edited by moderator to remove tons of code and prevent scroll injuries

Link to comment
Share on other sites

Jonathan is exactly right, we can't look through all that code and guess what isn't working or why.

When making the demo for us, please reduce the code to just the amount necessary to replicate the problem.

For instance, my guess is that you could make a demo with 3 nested timelines instead of 26.

  • Like 3
Link to comment
Share on other sites

Thanks for the demo. 

I'll admit it was more of a challenge than I first thought and I spent some time with some approaches that didn't quite work out.

The good news is I got it down to about 2 lines of code:

 

$("text").each(function(index,element){
  master.to(element, duration, {y:-475, ease:Linear.easeNone, repeat:-1, repeatDelay:(wordTimeOffset * numTexts) - duration}, index * wordTimeOffset)
  master.from(element, duration, {opacity:0, ease:"quickPulse", repeat:-1, repeatDelay:(wordTimeOffset * numTexts) - duration}, index * wordTimeOffset)
});

 

See the Pen eRvENg?editors=0010 by GreenSock (@GreenSock) on CodePen

 

The basic idea is that there are 2 repeating animations for each element:

First animation moves the element from below the svg to above the svg

The second animation fades the element in and then out.

 

I use a CustomEase for the fade that looks like this: https://greensock.com/ease-visualizer?CustomEase=M0,0 C0,0 0.231,0.062 0.358,0.3 0.497,0.561 0.472,1 0.472,1 0.472,1 0.536,1 0.536,1 0.536,1 0.542,0.514 0.642,0.302 0.735,0.101 1,0 1,0

 

The tricky part was figuring out how to make it group of animations repeat at the right time (repeatDelay). Basically I needed the first word to repeat as soon as the last word started moving.

 

You can change the speed by messing with the pixelsPerSecond variable.

You should be able to add more words just by copying and pasting in the svg.

Also try changing the ease to ease:"linear" on the opacity tween for a different fade effect.

 

I think I would next use a variable-transparency gradient mask instead of fading each word in and out. Something to perhaps experiment with at a later date.

 

 

 

  • Like 3
Link to comment
Share on other sites

It would take quite a bit of time to explain this properly, but I'll break down some of the steps

 

STEP 1: Animate each word

 

We know that we want multiple words animating from bottom to top.

I know the svg is 400px tall and each word is 75px tall. 

Putting the wheel-container element at a position of 475 places the top of each word directly below the bottom border

TweenLite.set(".wheel-container", {y:475});

 

The container is moved down and each word still has its own y value of 0 (i removed your y attributes in the html).

To make each word go up to the top of the stage I have to move -475 px.

I use a jQuery each() loop to add a tween for each word into a timeline

 

$("text").each(function(index,element){
  master.to(element, duration, {y:-475, ease:Linear.easeNone})
});

 

I use the following variables to figure out the duration of each tween based on the distance each word needs to travel and the speed

 

var pixelsPerSecond = 300;
var distance = 475;
var duration = distance / pixelsPerSecond;

 

Having a linear, constant rate of motion is very important for step 2.

For now step 1 does this:

 

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

 

  • Like 4
Link to comment
Share on other sites

Step 2: Make each word animate directly after the previous word (so it appears they are all animating as a group).

 

In step1 there is a big time gap between the first word animating and the second word animating.

I want each word to follow its predecessor at exactly the right time.

I want word1 to start animating as soon as word0 gets into the yellow border of the svg.

I know that each word is 75px tall so I just need to know how long it will take word0 to travel 75px up.

 

I know my pixelsPerSecond speed and how tall each word is so I can calculate myWordTimeOffset as follows: 

 

var pixelsPerSecond = 300
var wordHeight = 75;
var wordTimeOffset = wordHeight / pixelsPerSecond;

 

That calculation tells me that the second word needs to start 0.75 seconds after the first word.

Likewise the third word needs to have the same offset after the second word.

We can use the index of the loop and wordTimeOffset to dynamically set the absolute position of each animation in the timeline like so:

 

$("text").each(function(index,element){
  master.to(element, duration, {y:-475, ease:Linear.easeNone}, index * wordTimeOffset)
});

 

Yielding the following result which makes it look like a single list is animating at once:

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

 

  • Like 4
Link to comment
Share on other sites

Step 3: Make it loop

 

The issue with step 2 is that it only plays through once.

We need the first word to comeback up from the bottom 0.75 after the last word starts animating.

So we need to find the proper repeatDelay. This was a bit tricky and I came up with this:

 

repeatDelay:(wordTimeOffset * numTexts) - duration

 

I really can't explain that without walking you through a visual timeline like that found in Animate CC, so you'll just have to trust that it works when used like this:

 

$("text").each(function(index,element){
  master.to(element, duration, {y:-475, ease:Linear.easeNone, repeat:-1, repeatDelay:(wordTimeOffset * numTexts) - duration}, index * wordTimeOffset);
});

 

you can see the infinite repeat with the proper repeatDelay here:

 

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

 

Now that we have all words animation at the same rate with the right repeat, the next step is just to create another tween that fades the words in and out as they move. 

  • Like 3
Link to comment
Share on other sites

Step 4 Create a fadeInOut animation with the same timing as the movement tween.

 

Since I need a single tween that starts at opacity:0 goes to opacity:1 and then back to opacity:0 I decided to create a customEase.

In order to understand this step, you must first completely understand how an ease works

 

I decided to use an ease that looks like this:

 hZYBVehmRo_hQfL21m5bIg.png

 

you'll notice it stays stuck at max value for a little bit (flat part up top). 

 

I also tried a more linear ease like:

QtmWh8hIQ_K_f8rrn22RkA.png

 

 

They are both in my final CodePen as:

 

CustomEase.create("quickPulse", "M0,0 C0,0 0.231,0.062 0.358,0.3 0.497,0.561 0.472,1 0.472,1 0.472,1 0.536,1 0.536,1 0.536,1 0.542,0.514 0.642,0.302 0.735,0.101 1,0 1,0");
CustomEase.create("linear", "M0,0 C0,0 0.073,0.162 0.2,0.4 0.339,0.661 0.5,1 0.5,1 0.5,1 0.663,0.666 0.796,0.382 0.889,0.181 1,0 1,0");

 

You can definitely get some wild effects by just playing with the ease. i would probably round off the top of my quickPulse (ease 1) just to smooth it out a little.

 

I added the opacity tween at the same time like so:

 

$("text").each(function(index,element){
  master.to(element, duration, {y:-475, ease:Linear.easeNone, repeat:-1, repeatDelay:(wordTimeOffset * numTexts) - duration}, index * wordTimeOffset);
  master.from(element, duration, {opacity:0, ease:"quickPulse", repeat:-1, repeatDelay:(wordTimeOffset * numTexts) - duration}, index * wordTimeOffset)
});

 

feel free to change ease:"quickPulse" to ease:"linear" to see the difference.

 

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

 

 

 

 

 

 

  • Like 5
Link to comment
Share on other sites

16 hours ago, Carl said:

Thanks, Craig. I had to do something to up my game once @OSUblake started creating "6-part tutorials as answers:-D

 

@Carl I think I'm going to add more stuff, so you're going to have some catching up to do.

 

I have to ask. After explaining everything, I'm wondering it's hit you yet. You already wrote about how to do this, demo and all.

https://greensock.com/1-19-0/

 

  • Like 2
Link to comment
Share on other sites

16 minutes ago, Dipscom said:

And here we go again. Could someone put a restraining order on @OSUblake to stop upping the game here in the forums? Some of us have to sleep, eat, go to the toilet, wash, et al, from time to time...

 

I wasn't going to add anything, but since you brought it up, here's how I would do it. Imagine the wheel from the its side. It's a regular a polygon, which means you can figure out it's radius.

http://mathopenref.com/polygonradius.html

http://www.mathsisfun.com/geometry/regular-polygons.html

 

Once  you figure out the radius, you can rotate the vertices for each polygon face inside an animation. Each face can  then be mapped back into its 1D front view by comparing the top and bottom y-coordinate. If the bottom value is greater than the top, that means the face is upside down, and is on the backside, so it won't be visible.

 

Well, that's how I would do most of it... but don't wait around for me. It's your turn to do make a demo, which I will need to see by close of business today. 

  • Like 5
Link to comment
Share on other sites

29 minutes ago, OSUblake said:

 

I wasn't going to add anything, but since you brought it up, here's how I would do it. Imagine the wheel from the its side. It's a regular a polygon, which means you can figure out it's radius.

http://mathopenref.com/polygonradius.html

http://www.mathsisfun.com/geometry/regular-polygons.html

 

Once  you figure out the radius, you can rotate the vertices for each polygon face inside an animation. Each face can  then be mapped back into its 1D front view by comparing the top and bottom y-coordinate. If the bottom value is greater than the top, that means the face is upside down, and is on the backside, so it won't be visible.

 

Well, that's how I would do most of it... but don't wait around for me. It's your turn to do make a demo, which I will need to see by close of business today. 

 

:-o

 

Link to comment
Share on other sites

Hey Blake,

 

Thanks for checking my sanity;) lol, forgetting about the modifiersPlugin demo is definitely within the realm of possibility. 

I did start down that path, but in my haste got tripped over how to handle the negative range with modulo stuff (i just re-found your wrap function, which I'm sure would have helped). Additionally, I was hung up on how to handle the opacity change with that solution. 

 

The path I took ended up being the one with least mental resistance at the time. 

If you want to take a stab at a simple or more advanced (3d) approach please share. You can't tease us like this;)

 

C

 

 

  • Like 3
Link to comment
Share on other sites

  • 2 weeks later...
On 6/21/2017 at 9:37 AM, Carl said:

If you want to take a stab at a simple or more advanced (3d) approach please share. You can't tease us like this;)

 

Simple shading isn't as hard as you may think. It's based around a simple vector calculation called the dot product, which multiplies 2 vectors together to return a scalar. You multiply RGB values by that scalar to get the adjusted color.

function dotProduct(v0, v1) {
  return v0.x * v1.x + v0.y * v1.y;
}

 

The vectors you pass in are from the light source and the surface normal. A normal is a line perpendicular to a surface. 

 

gGoMVkK.jpg

 

If the angle between the light source and the normal is 0, then all the light will reflect back. If the angle is 90 degrees or more, then no light will be reflected back. You can play around with that concept in this demo. Drag the light around, and watch as the color changes. Note that I'm not adjusting for any background lighting or distance from the light source.

 

 

That's how I did all the shading in this 3D experiment using SVG.

 

See the Pen eNKYbG by osublake (@osublake) on CodePen

 

If SVG could do a mesh gradient, which at one point in time was planned for SVG 2, I'm pretty sure it would be possible to do gouraud shading. It looks a lot nicer, but I doubt you'd be able to animate an SVG with a reasonable frame rate doing that. 

 

D3D_Shading_Modes.png

 

  • Like 3
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.
×
×
  • Create New...