Jump to content
Search Community

reposition and scale an element that has been scaled by a previous animation

fcdobbs test
Moderator Tag

Recommended Posts

Hi,

I'm trying to figure out how to reposition and scale an element that has been scaled by a previous animation.  The previous animation may have been completed and killed at the time the next animation is called.   Overwrite appeared to work only if the animation that positioned and scaled the element previously had not been killed.

In this example, I'd like to first apply new position and size attributes, and then apply a new scale.  I'd like ellipse1 to end up at the position and scale of ellipse2 after the sequence is completed.

Is a sequence like this best accomplished by recording several states in a different order with gsap flip, and animating to those states in the order I'd like them to be played?

Thanks for your help!

See the Pen ZEqXpje by fcdobbs (@fcdobbs) on CodePen

Link to comment
Share on other sites

Hi,

 

I have limited experience in SVG but in this cases I always remember what @OSUblake recommends: "keep everything in the center of the SVG view box at startup and then create a coordinate system based on that". So taking his extremely wise words I forked your codepen and came up with this:

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

 

As I mentioned SVG is not the sharpest tool on my development drawer. I'll invoque @Cassie and @PointC, our SVG wizards so they can either confirm what I'm saying or expose me as a fraud and post a better solution :D

 

Hopefully this helps.

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Thanks, Rodrigo.

 

If it's easy, I'd be curious if you have formulae for the x and y values you've applied to the svg's to keep them centered.  If I can calculate these values from the element's current properties, this could be a good solution.

 

I came up with a solution that keeps the svg centered through scale and attribute transitions by tweening the transformation matrix like this:

transform: (i,e)=>

         "matrix(" + new_scale + "," + gsap.getProperty(e,"skewY") + "," + gsap.getProperty(e,"skewX") + "," + new_scale + "," + (gsap.getProperty(e,"cx") - gsap.getProperty(e,"cx") * new_scale) + "," + (gsap.getProperty(e,"cy") - gsap.getProperty(e,"cy") * new_scale) + ")" }})

See the Pen BaqwgOr?editors=0010 by fcdobbs (@fcdobbs) on CodePen

 

I also put together a version using gsap Flip.  It's more verbose but could prove useful if other properties are involved in the animation.  I didn't find Flip.fromTo in the docs, but I tried it, and it appears to work!

See the Pen MWPOErE?editors=0011 by fcdobbs (@fcdobbs) on CodePen

 

I thought there could be a more compact version that would allow gsap to make the transform matrix calculations by using CSS's transform-box.

 

CSS correctly scales and positions the elements, but I couldn't find a syntax that would allow gsap to animate through these values.

 

This syntax throws an Error: <ellipse> attribute transform: Expected transform function, "null".

t1.to("#ellipse1",{duration: duration, "transform-origin":"50% 50%", "transform-box":"fill-box", "transform":"scale(.5, .5)",})

 

gsap looses track of the center point with both of these syntaxes, but maybe there's a formula that will adjust the transformation matrix based on the data-svg-origin attribute:

t1.to("#ellipse1",{duration: duration, transformOrigin:"50% 50%", transformBox:"fill-box", "transform":"scale(.5, .5)",})

t1.to("#ellipse1",{duration: duration, transformOrigin:"50% 50%", transformBox:"fill-box", scale:.5,})

See the Pen dygZZOo?editors=0011 by fcdobbs (@fcdobbs) on CodePen

 

If you have formulae handy for calculating the x and y offsets based on the current element's properties, I'll give that a try. 

 

It's unclear to me if tweening the transformation matrix values directly might throw gsap off in subsequent animations of these elements.

 

Thanks for your help!

Link to comment
Share on other sites

Hi,

 

I didn't do a single calculation ;) Actually I just used the viewbox value you had in your SVG and took it from there.

 

If you use just this JS in the codepen I created:

gsap.set("#ellipse1", {
  opacity: 1,
});
gsap.set("#ellipse2", {
  opacity: 1,
});

You'll see both ellipses centered in the SVG container:

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

 

Starting at that point both ellipses are at the center of the SVG canvas and their X and Y values are both zero, so given the dimensions of your view box: viewBox="0 0 100 100" you know that the bounds are 100 on each axis. Then with the radius on each axis I set their positions using a couple of set() instances:

gsap.set("#ellipse1", {
  y: -40,
  opacity: 1,
});
gsap.set("#ellipse2", {
  x: 25,
  y: 40,
  opacity: 1,
});

And then all I had to do is move ellipse1 to the same coordinates ellipse2 has:

t2.to("#ellipse1", {
  duration: duration,
  x: 25,
  y: 40,
  attr: {
    rx: new_rx,
    ry: new_ry,
  }
})

And that's it. Sometimes the simplest solution just works :D

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Thanks, Rodrigo.

 

Is there any syntax that utilizes the CSS transform-box property to keep an svg element centered without manually calculating x and y  offsets?

 

This syntax throws an error, but it does match the rendering of the CSS transform-box property until the svg attributes are updated:

t1.to("#ellipse1",{duration: duration, transformOrigin:"50% 50%", transformBox:"fill-box", "transform":"scale(2, 2)",})

 

See the Pen KKGZBQQ?editors=0010 by fcdobbs (@fcdobbs) on CodePen

 

Thanks for your help!

Link to comment
Share on other sites

Hi,

 

SVG is not something I have a lot of experience with, but my guess is that you're looking for SVG Origin:

svgOrigin
[Only for SVG elements] Works exactly like transformOrigin but it uses the SVG’s global coordinate space instead of the element’s local coordinate space. This can be very useful if, for example, you want to make a bunch of SVG elements rotate around a common point. You can either define an svgOrigin or a transformOrigin, not both (for obvious reasons). So you can do gsap.to(svgElement, {duration: 1, rotation: 270, svgOrigin: "250 100"}) if you’d like to rotate svgElement as though its origin is at x: 250, y: 100 in the SVG canvas’s global coordinates. Units are not required. It also records the value in a data-svg-origin attribute so that it can be parsed back in. svgOrigin doesn’t accommodate percentage-based values.

 

 

You can read more about it in the CSS Plugin docs (scroll about the middle of the page)

https://greensock.com/docs/v3/GSAP/CorePlugins/CSSPlugin

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

On 5/3/2023 at 2:22 PM, fcdobbs said:

I came up with a solution that keeps the svg centered through scale and attribute transitions by tweening the transformation matrix like this:

 

transform: (i,e)=>

 

         "matrix(" + new_scale + "," + gsap.getProperty(e,"skewY") + "," + gsap.getProperty(e,"skewX") + "," + new_scale + "," + (gsap.getProperty(e,"cx") - gsap.getProperty(e,"cx") * new_scale) + "," + (gsap.getProperty(e,"cy") - gsap.getProperty(e,"cy") * new_scale) + ")" }})

That formula is not correct, sorry. The skew values are definitely wrong - that's not how matrices work. 

 

I have very limited time right now. Is there any way you could simplify your question? A lot of the stuff in your CodePen looked odd to me. I want to keep the advice focused on what you need. 

 

For example, maybe just provide a CodePen and say "how can I get the green oval to animate to the position where its center is aligned with the center of the purple oval?" Again, the simpler the better. No need to include a bunch of extra code in there that isn't working. 

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...