Jump to content
Search Community

Problem with animating Foreign Object element nested in SVG

LachlanTS 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

I'm having an issue with animating an HTML element nested inside an SVG with <foreignObject>.

 

When the SVG is set to 100%, there's no problem, but when it's dimensions are scaled the <foreignObject> elements don't honour the resizing of the parent SVG when they're animated and act as if the SVG were set to 100%.

 

Here you can see how it looks at 100%:

2018-01-25_12-34-47.png.ffa59ef659c4a5478922ca139e3278fa.png

And here's the Codepen:

See the Pen 129a5aa1d5144b8a1d875ad4ff23d6a7 by lachlants (@lachlants) on CodePen

 

And here's how it looks when the SVG is set to Width: 50%:

2018-01-25_12-36-20.png.3e766540cec03a8cbbaa75398afef52d.png

 

And the Codepen:

See the Pen 7ded3187df907ed11f2940e87cd383a9 by lachlants (@lachlants) on CodePen

 

Love to hear if there are any solutions to this?

 

I'm aware that using the transform: scale on the SVG will solve this, but hoping to find a way to use SVG built-in resizing to save some work at implementing this.

 

Thanks in advance,

 

Lachlan

 

 

 

See the Pen 7ded3187df907ed11f2940e87cd383a9 by lachlants (@lachlants) on CodePen

Link to comment
Share on other sites

Why do you need to do it inside an svg. The animation you are creating can be created regular html elements, it doesn't need to be inside an svg container. At the very least the text doesn't. 

 

As noted if you must use svg I think svg text would be much better than injecting html text.

 

Regardless, if you are injecting html text in the svg and you know the size of the svg relative to the dom is consistent. Ie 100% wide, 50% wide etc you could apply font size based on vw viewport width units. You'll also likely have to tinker with the html containers including the size of the foreign object itself , I don't believe the svg will trigger them to resize, they will probably have to have percentage or viewport based sizing which will hopefully be honored within the svg rather than arbitrary pixel based sizing.

  • Like 2
Link to comment
Share on other sites

On 26/01/2018 at 12:32 AM, mikel said:

Hi @LachlanTS,

 

Why are you making it so hard for you?

 

SVG text in paths can solve the task.

 

Kind regards

Mikel

 

 

 

Thanks  @mikel. Yes, I appreciate SVG text would be a much easier solution, but the above animation isn't a one-off; it's part of a large set of user-editable animations that are more complicated than the example I sent through. Unfortunately, SVG text is currently quite limited and doesn't offer multi-line text wrapping (easily), which is a feature we require for the animations.

 

I'm aware that we can manually create text wrapping with <tspan> SVG elements, but this adds a level of complexity that we would prefer to avoid if possible.

 

Thanks,

 

Lachlan

Link to comment
Share on other sites

On 26/01/2018 at 1:32 AM, Visual-Q said:

Why do you need to do it inside an svg. The animation you are creating can be created regular html elements, it doesn't need to be inside an svg container. At the very least the text doesn't. 

 

As noted if you must use svg I think svg text would be much better than injecting html text.

 

Regardless, if you are injecting html text in the svg and you know the size of the svg relative to the dom is consistent. Ie 100% wide, 50% wide etc you could apply font size based on vw viewport width units. You'll also likely have to tinker with the html containers including the size of the foreign object itself , I don't believe the svg will trigger them to resize, they will probably have to have percentage or viewport based sizing which will hopefully be honored within the svg rather than arbitrary pixel based sizing.

 

Thanks @Visual-Q.

 

As I replied to Mikel, the animation is only a basic sample of a set of more complicated/detailed animations that respond to user input; which is the reason for not using regular HTML elements.

 

Your text resizing suggestions sound good and like they would work. The issue is that given a user is dynamically resizing the entire animation container, I was hoping to find a solution that would resize both the animation and text at the same time, rather than complicating it with separate calculations for both.

 

Basically, the above animation is a simple prototype for a large set of animations and we're looking for a consistent way to have each animation be scaled by the user, while also being able to use advanced text features such as multi-line wrapping.

 

Does it sound like the CSS transform: scale applied to the SVG is the best solution based on this?

 

Thanks,

 

Lachlan

Link to comment
Share on other sites

I'm not sure if a global transform scale on the entire svg would work as you want I guess you'll just have to try and see. It would be a magic bullet if it did, I'm doubtful it would be that simple.

 

Here's a post about transforms on svg though it seems to be mainly about applying it to internal objects not global transform on the entire svg which is what I think you're after. May be useful info in it though.

https://css-tricks.com/transforms-on-svg-elements/

 

Another post about placing and sizing, scaling svgs

https://css-tricks.com/scale-svg/

 

I don't see any discussion of foreign objects in these though.

 

 

 

 

Link to comment
Share on other sites

Not sure why you even need svg for this. Everything in your demo can be done with HTML. Messing with foreignObject is trouble. The only reason I would ever use it is to render HTML to a canvas element.

 

If you want to scale text, you can use an aspect ratio to figure out the scale value.

  • Like 3
Link to comment
Share on other sites

19 hours ago, Visual-Q said:

I'm not sure if a global transform scale on the entire svg would work as you want I guess you'll just have to try and see. It would be a magic bullet if it did, I'm doubtful it would be that simple.

 

Here's a post about transforms on svg though it seems to be mainly about applying it to internal objects not global transform on the entire svg which is what I think you're after. May be useful info in it though.

https://css-tricks.com/transforms-on-svg-elements/

 

Another post about placing and sizing, scaling svgs

https://css-tricks.com/scale-svg/

 

I don't see any discussion of foreign objects in these though.

 

 

 

 

Thanks @Visual-Q.

 

Yes, the css-tricks link is what we've been working off for the transform. It appears to work in isolated tests; it's just a matter of implementing it into the web application's current UI setup.

Link to comment
Share on other sites

17 hours ago, OSUblake said:

Not sure why you even need svg for this. Everything in your demo can be done with HTML. Messing with foreignObject is trouble. The only reason I would ever use it is to render HTML to a canvas element.

 

If you want to scale text, you can use an aspect ratio to figure out the scale value.

Thanks @OSUblake.

 

You're right that the above animation could be done easily with just HTML, unfortunately, as I mentioned above, this is a very basic demo of a very large series of far more complicated animations that will require SVG to create the graphics.

 

Scaling the text independently is also a viable option but given the large volume of animations and that fact that the scaling is done dynamically by the user; we were hoping to streamline the process and only require the scaling of one container element, rather than several different scaling calculations occurring at once as the user dynamically scales the animation.

Link to comment
Share on other sites

After further experiments with the foreignObject nested inside a scaled SVG element; it appears that any CSS transform applied to an HTML element nested in a foreignObject resets the positioning/scale of the HTML element to a position/scale as if the SVG wasn't scaled.

 

Given Greensock animations of DOM elements uses CSS transform, this will apply a CSS transform to the nested HTML element and reset it's positioning.

Link to comment
Share on other sites

2 hours ago, LachlanTS said:

After further experiments with the foreignObject nested inside a scaled SVG element; it appears that any CSS transform applied to an HTML element nested in a foreignObject resets the positioning/scale of the HTML element to a position/scale as if the SVG wasn't scaled.

 

Given Greensock animations of DOM elements uses CSS transform, this will apply a CSS transform to the nested HTML element and reset it's positioning.

 

 

It's resetting the current transform matrix. You would have to scale it back down.

 

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

 

foreignObject is just problematic for animations, rendering artifacts are common, and it doesn't work in IE. I would just overlay scaled HTML text.

 

 

Link to comment
Share on other sites

On 01/02/2018 at 4:27 PM, OSUblake said:

foreignObject is just problematic for animations, rendering artifacts are common, and it doesn't work in IE. I would just overlay scaled HTML text.

 

 

Thanks, yes this is our fall back if the foreignObject approach doesn't work.

 

In the set of animations we'll be creating, masking will be pretty essential and could be become quite complicated. One advantage we get with having the text as an HTML foreignObject rather than HTML text layered on top of the SVG; is we get to use SVG masking for both the text and SVG graphics, rather than having to replicate the masks in HTML for the text and sync the timing for both sets of masks.

 

With this in mind, I'd prefer not to have to create the masks in both SVG and HTML. Having said this, if foreignObject just doesn't work for us and we get rendering artifacts, we'll have to settle with layering HTML text on SVG graphics.

 

We've also accepted that IE won't be compatible with the app.

Link to comment
Share on other sites

  • 1 year later...

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