Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
bdrtsky

Morph cycle between array of paths?

Recommended Posts

Hello, guys!

 

Let's say I have an array of paths. Is there a clean native way to loop between them? First shape, second etc...I mean, I probably could setTimeout and then loop manually, but is this the right way?

Link to comment
Share on other sites

One way of many possibilities — 

 

See the Pen LNLpgB by PointC (@PointC) on CodePen

 

Happy tweening.

:)

 

  • Like 1
Link to comment
Share on other sites

But you don't loop between array of shapes here. You just switching 2 shapes. I need more then 2.

Link to comment
Share on other sites

Here you just creating 5 separate shapes with the loop. This is not what I am asking.

Link to comment
Share on other sites

Sorry, I misunderstood. What exactly do you need it to do? Do you have a demo?

  • Like 1
Link to comment
Share on other sites

Yes, I made one - 

See the Pen qwjEKP by bdrtsky (@bdrtsky) on CodePen

 

 

What I need is to loop between shapes in array. First, second, third. Without manually writing timeline. 

Link to comment
Share on other sites

The result what I need is here, but I can't write timeline manually (whant to just pass the array of data) - 

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

 

 

Probably some "timeline builder" function, not sure how to do that better...

Link to comment
Share on other sites

@PointC yes, like this, thanks. Beside one part - how to actually loop it? If I add repeat: -1 it jumps to first shape, not morphing :-( And I want to maintain the order, so yo-yo will not work.

Link to comment
Share on other sites

Yep, @PointC's is the simplest solution. If you need a function, here's something rudimentary:

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

 

If you need to go back to the beginning shape, just tack an extra tween on the end accordingly. Is that what you're looking for? 

  • Like 2
Link to comment
Share on other sites

Jack's is far more elegant, but I'm a simple guy, so here's another option. Tween the morph in a function that keeps getting called each time the tween is finished and just increment a count variable. I also didn't know if the first morph was supposed to start from nothing (which is why I added the starting d attribute data) or if it should be the first target in the shapes array. 

 

See the Pen rbwVOz by PointC (@PointC) on CodePen

 

Happy tweening

  • Like 3
Link to comment
Share on other sites

@GreenSock thanks! In my actual app code I have "ERROR: malformed path" error. What could cause it?

Link to comment
Share on other sites

UPD, got it, I need to `el.setAttribute("d", this.paths[0])`

 

Thanks guys!

  • Like 1
Link to comment
Share on other sites

@PointC actually, I like your solution! Didn't think about that I can loop it this way. This is awesome!

  • Like 2
Link to comment
Share on other sites

2 minutes ago, bdrtsky said:

UPD, got it, I need to `el.setAttribute("d", this.paths[0])`

 

Yeah, that error message just meant that the path data didn't make sense...it sounds like you figured out that it was because the initial path was completely empty. 

 

8 minutes ago, PointC said:

...so here's another option. Tween the morph in a function that keeps getting called each time the tween is finished and just increment a count variable.

 

Indeed! Nice solution as well. I love it when we provide multiple solutions and people see how you can approach things from various angles. ?

  • Like 2
Link to comment
Share on other sites

Oh, one very minor thing - you could make it slightly shorter like this:

 

OLD:

function morphIt() {
  TweenMax.to("path", 1, { morphSVG: shapes[count], onComplete:morphIt });
  count ++;
  count = count > shapes.length - 1 ? 0 : count;
}

 

NEW:

function morphIt() {
  TweenMax.to("path", 1, { morphSVG: shapes[count], onComplete:morphIt });
  count = (count + 1) % shapes.length;
}

 

NEW (Alternate):

function morphIt() {
  TweenMax.to("path", 1, { morphSVG: shapes[count++], onComplete:morphIt });
  count %= shapes.length;
}

 

?

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Don't bring that fancy code around here. I said I was a simple guy. ?

 

Nice work. I'm always learning around here. ?

  • Like 3
Link to comment
Share on other sites

Hi,

 

Morphing - my favorite toy! Plus random sequences ...

 

But why does the animation stop sometimes? Is my computer too weak, demanding my code, or have I built in errors?

 

See the Pen xerJNG by mikeK (@mikeK) on CodePen

 

 

Best regards

Mikel

 

Link to comment
Share on other sites

It stops because your random number function is sometimes choosing the same path data when it gets called. So if your current path is shapes[4] and the random generator returns 4, you'll tween from shapes[4] to shapes[4] which visually wouldn't show anything.

 

You could set a variable for an active shape and if the random function returns the same number, you choose a new one and feed that into the tween.

 

Make sense?

:)

 

  • Like 2
Link to comment
Share on other sites

Hi @PointC,

 

 

Thank you very much. Very plausible. Will try to construct such a variable.

 

Best regards

Mikel

  • Like 2
Link to comment
Share on other sites

Hi,

 

Well, to code a condition is not exactly my strength. But with my 'simple' version it works ...

 

See the Pen rbwEEE by mikeK (@mikeK) on CodePen

 

Kind regards

Mikel

Link to comment
Share on other sites

This is my attempt at generating a random number that isn't the same as the last one generated. I just compared the new random number to the existing old one and if they match I called the function again. I'm honestly not sure if this is the most concise way to do this, but it works. It was a good little brain exercise. ? I'd be curious to see how @GreenSock would write it.

 

See the Pen mgMdeJ by PointC (@PointC) on CodePen

 

Happy tweening.

:)

 

 

  • Like 2
Link to comment
Share on other sites

Yeah, that's probably exactly what I'd do. I might try to make the function a little more reusable so that I could pass in the length as well as the number to exclude, like: 

var boxes = document.querySelectorAll("div"),
    newNumber, i;

for (i = 0; i < boxes.length; i++) {
  newNumber = getRandomInt(boxes.length, newNumber);
  boxes[i].innerHTML = newNumber;
  console.log(newNumber);
}

function getRandomInt(length, exclude) {
  var random = Math.floor(Math.random() * length);
  return (random === exclude) ? getRandomInt(length, exclude) : random;
}

 

Alternatively, if you just want to grab a random element that's not the previously selected one, you could slap a new property on the actual array (or NodeList) to keep track of things and leverage something like this one function: 

function getRandomFrom(array) {
  var selected = array.selected;
  while (selected === (array.selected = Math.floor(Math.random() * array.length))) {};
  return array[array.selected];
}

 

(this isn't useful for this case, but I thought I'd share in case it's helpful)

 

Lastly, if you want to randomly pull values from an array one-by-one until they've all been pulled (almost as if when you pull one, it's no longer available to be pulled again until ALL of them have been uniquely pulled out), here's a fun function I just whipped together:

 

function pullRandomFrom(array) {
  if (!array.eligible || array.eligible.length === 0) {
    array.eligible = array.slice(0); //make a copy, attach it as "eligible" property
    array.eligible.sort(function() { return 0.5 - Math.random(); }); //shuffle
  }
  return array.eligible.pop();
}

 

All you've gotta do is feed the array in each time and it keeps track of things for you. :)

 

That was a fun exercise. Thanks for the invitation, @PointC

  • Like 2
Link to comment
Share on other sites

Great stuff Jack. I was gonna pass in the array length (I only used a hard coded 5 because that's what @mikel had in his array), but I hadn't thought about passing in the number to exclude. That's a neat and concise way of doing it.

 

This is one of those very handy utility functions that people could use for many projects. The last function in your answer is great too. I've had a couple projects where I needed to empty an array randomly so that's cool. I'm copying all of these and putting them in the useful stuff library. :ph34r:

 

Thanks for the input and lesson at GreenSock JavaScript University. I put a dollar in your tip jar. ;)

  • Haha 1
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.
×