JAcato Posted August 4, 2020 Posted August 4, 2020 We haven't set up a codepen yet, but included is the visual design created for a web-based game to develop. We found a few examples of GSAP getting actually somewhat close to how it should work, but we find it hard to find a push in the right direction when it comes to intersections in the path below. The marker (avatar on A) should be able to move to points B and C when the player clicks one of those points. From point B, the player should be able to move to C or E From point C, the player should be able to move to B or D or E. Etcetera. Is this actually possible using GSAP with the MorphSVGPlugin and BezierPath?
ZachSaucier Posted August 4, 2020 Posted August 4, 2020 Hey JAcato and welcome to the GreenSock forums. This is quite possible (and fairly easy) using the MotionPathPlugin. You'd have to setup some basic logic to allow certain paths once the user is at a given location but that's pretty trivial The animations themselves are quite straightforward with MotionPathPlugin.
JAcato Posted August 4, 2020 Author Posted August 4, 2020 Hi ZachSaucier, First of all thanks for the welcome and quick reply! Really appreciated! The MotionPathPlugin should be the way to go then. Thanks! I will try to setup a Codepen to have some progress to look at, and see how far I will get. Do you know of an example using a path with multiple directions like mentioned in the OP? Until now, I've been wrestling with the examples shown in
ZachSaucier Posted August 4, 2020 Posted August 4, 2020 41 minutes ago, JAcato said: Do you know of an example using a path with multiple directions like mentioned in the OP? Not besides that thread, no. Here's some pseudo-code: <!-- The stuff you click on goes inside --> <div data-loc='a'></div> <div data-loc='b'></div> <!-- ... --> // Setup the data const possiblePaths = { a: { b: {anim: animAB, dir: 1}, c: {anim: animAC, dir: 1} }, b: { a: {anim: animAB, dir: -1}, c: {anim: animBC, dir: 1}, e: {anim: animBE, dir: 1} }, // ... } // Get the DOM elements for the click const locations = document.querySelectorAll('[data-loc]'); // Keep track of the current location and animation let currLoc = 'a'; let currAnim = gsap.to({}, {}); // Add a click listener to check if it's valid from the given configuration locations.forEach(loc => { loc.addEventListener('click', e => { if(!currAnim.isActive() // Don't allow choices while animation happening && possiblePaths[currLoc].hasOwnProperty(loc.dataset.loc) ) { // Make sure it can be navigated to const dataObj = possiblePaths[currLoc][loc.dataset.loc]; // Play the animation based on the direction and update the state currAnim = dataObj.dir === 1 ? dataObj.anim.play() : dataObj.anim.reverse(); currLoc = loc.dataset.loc; } }); }); 1
JAcato Posted August 4, 2020 Author Posted August 4, 2020 Hi Zach, Great thanks! I've been looking into https://codepen.io/GreenSock/pen/mdyxvGX as well to find a suitable approach. Back to prototyping!
ZachSaucier Posted August 4, 2020 Posted August 4, 2020 1 minute ago, JAcato said: I've looking into https://codepen.io/GreenSock/pen/mdyxvGX as well to find a suitable approach. While you can learn from that pen, I don't think it's really relevant to the effect you're creating. I highly recommend creating individual paths connecting each location, not trying to animate part of a larger path.
JAcato Posted August 6, 2020 Author Posted August 6, 2020 Hi Zach, I managed to get it all working, except.. reverse() is not working somehow. Do you have an idea why? // for each path we generate a tween // d is the "d" attribute, // id is the "id" attribute, eg. "path-a-b": path from a to b // we check if "a: {b: {...}}" exists // and we check if "b: {a: {...}}" exists // then we add the tween to both properties const anim = gsap.to('#avatar', { motionPath: { path: d, align: id, alignOrigin: [0.5, 0.5], }, transformOrigin: '50% 50%', duration: 1, ease: 'power1.inOut', paused: true, onComplete: () => { console.group('Tween complete'); console.log('Instance: ', instance); console.groupEnd(); }, }); // on click on a marker // we grab the id, eg. "em-b", so we know where we have to go (point b) // then we take the current location, eg. "a", find the corresponding animation (a to b) // and according to the set "dir", we determine to either play or reverse the animation // eg. currentLocation is "a", marker is "em-b", so we look for "a: {b:{...}}" // dir === 1, so play() it is. this works :) // eg. currentLocation is "b", marker is "em-a", so we look for "b: {a:{...}}" // dir === -1, so reverse() it is. this doesn't work :) obj.dir === 1 ? obj.anim.play() : obj.anim.reverse();
ZachSaucier Posted August 6, 2020 Posted August 6, 2020 3 hours ago, JAcato said: I managed to get it all working, except.. reverse() is not working somehow. Do you have an idea why? Good work! I'm guessing it's because the animation hasn't been played so it's trying to .reverse() from the start (going nowhere). Sorry I didn't think that through in my pseudo-code. Try this: obj.dir === 1 ? obj.anim.play() : obj.anim.progress(1).reverse(); Without a demo it's hard to say for sure though. 1
JAcato Posted August 7, 2020 Author Posted August 7, 2020 @ZachSaucier Great! That works indeed. Once the player has walked a path, the reverse is working as intended! One note: when the player hasn't walked a certain path yet, and it's called using .progress(1).reverse(), it's playing backwards, but the start and end position are wrong. Let me try and set up a codepen demo illustrating this
JAcato Posted August 10, 2020 Author Posted August 10, 2020 @ZachSaucier Hi Zach! Managed to move a step forward. I've also setup a demo in Codepen, which illustrates the progress thus far. As you can see, moving from point A (where the avatar starts) to C works perfectly. Going from C to B works as well. At that point, going back to A, doesn't work as intended, it uses point B as finish, where as that should be the starting point. I believe this is, because the original path from A to B hasn't been walked yet. So it doesn't know where to start. See the Pen NWNqOyQ by nogzoiets-the-looper (@nogzoiets-the-looper) on CodePen.
ZachSaucier Posted August 10, 2020 Posted August 10, 2020 Hey JAcato. I'm not sure why you're getting the path data and passing that into your motionPath... Why not let MotionPathPlugin do that for you? I think it also fixes your logic issue. Additionally, once you fix the issue, then your demo has trouble replaying the same path. (say going from A->C->B->A, going back to C has issues). You can fix that by adding .progress(0) before the .play(): See the Pen dyMowgN?editors=0010 by GreenSock (@GreenSock) on CodePen.
JAcato Posted August 10, 2020 Author Posted August 10, 2020 Hi @ZachSaucier Thanks a lot! That fixes all It works perfectly. Many thanks for your help and support!
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now