Fork me on GitHub
#reagent
<
2022-03-15
>
Pepijn de Vos13:03:20

Hmmm I wast trying to do a CSS transition on an SVG attribute, but apparently you can't do that because it can only style a select few presentation attributes. So that puts me in JS animation domain it seems. It's quite low priority, but was just wondering if there are nice libraries that work with Reagent to do transitions like this.

p-himik13:03:56

I'd start looking at React libraries for that because React can definitely introduce its own peculiarities in the whole process. And React<->Reagent interop is not that bad.

Pepijn de Vos13:03:58

Yea it tends to be 1. Cljs things 2. React things 3. ... 4. ... 5. JS things in terms of easy integration. Found some examples of people hacking D3.js into componentdidupdate or whatever but that's a big can of worms just to make some transitions feel nicer

p-himik13:03:39

Is your SVG embedded directly or via <object>/`<img>`?

Pepijn de Vos13:03:50

directly embedded

p-himik13:03:58

And is that attribute that you want to transition something that can be set in CSS?

Pepijn de Vos13:03:22

Nope that's the whole problem, I want to transition the x/y position

Pepijn de Vos13:03:43

The first thing I tried is just put a CSS transition on it but that's not supported.

p-himik13:03:00

...can't you set those in CSS via left/top instead of using x/y attributes?

Pepijn de Vos13:03:14

I don't think so

p-himik13:03:25

Strange. https://stackoverflow.com/questions/35201001/how-to-transition-transform-in-svg suggests that it should be possible to use transition. But I haven't tried it myself.

Pepijn de Vos14:03:29

I'll give it a go...

Pepijn de Vos14:03:54

Nope... transition: all 1s; in the CSS, and in the inspector I can see it's applied and the HTML changes

<svg transform="translate(-150, 100)" class="staging">...</svg>
but it's just jumping around. > some typos in your script (no units, `attr()` instead of css()), use this I think that's the key, you have to modify the CSS rather than the HTML attributes. Not sure if you can do that in a neat way in Reagent/React

Pepijn de Vos14:03:53

{:style {:transform (str "translate(" vx "px " vy "px)")}} doesn't do anything at all

Pepijn de Vos14:03:02

oh! , and it's working?!?!

Pepijn de Vos14:03:25

It's sooooo finicky! I tried to wrap another :transform in :style and in that case it shows up as an actual style= attribute in the HTML and doesn't work.

p-himik14:03:35

If you apply some :style and it doesn't make its way into the Inspector, it's 95% chance that you did something wrong.

Pepijn de Vos14:03:18

yea no actually managed to make that work too. Was not applying the transition to the other element yet :face_palm:

Pepijn de Vos14:03:43

So now... am I going to replace all x/y with translate :thinking_face: :face_palm:

Pepijn de Vos14:03:45

hey it actually seems to work. It's silly, but it works.

Pepijn de Vos15:03:22

oh no!! It works in Firefox but not in Chrome

Pepijn de Vos15:03:45

Chrome just doesn't apply the transform on a nested SVG element.

Pepijn de Vos15:03:35

And if you apply the transform to a g inside the SVG then the rotation axis becomes the origin and it completely flips out if you then rotate the element

p-himik15:03:29

> Chrome just doesn't apply the transform on a nested SVG element. So the transform is there in the Chrome's inspector, but it's not applied?

Pepijn de Vos15:03:19

Like, it's an obvious browser bug

p-himik15:03:33

Wait. You have <svg> within <svg>. Is that even legal?

Pepijn de Vos15:03:07

yea it is, but... apparently so unconventional that both Firefox and Chrome have weird issues around them.

p-himik15:03:02

Potentially it may be not about that but rather about the closest parent that has position: relative or something like that. It's 50/50 here - either you did something wrong or there's a genuine bug in some or all of the browsers. I've seen enough of the latter to never brush it off.

Pepijn de Vos15:03:46

Yea svg defines "viewports" which is basically the nearest svg element

Pepijn de Vos15:03:48

But there are buggy edgecases where you apply styles on the svg tag itself.

Pepijn de Vos16:03:37

lmao I got rid of the nested SVGs but now the transition is completely insane https://twitter.com/pepijndevos/status/1503765068881747973

p-himik16:03:37

:D At least it looks funny. If you can create an MRE in pure JS, I'd try asking on SO instead - this seems to be a highly specific thing that also has nothing to do with CLJS or even React, so SO would be a better place.

Pepijn de Vos16:03:26

It interpolates the matrix values, so since the translation is now folded into the transform, it interpolates these quite significant offsets in different matrix indixes

p-himik16:03:43

I see. Tricky.

Pepijn de Vos18:03:00

I think I either have to work with separate rotation/translation/scaling from the start, or decompose the matrix into these operations. It seems like CSS has specific animation behavior for those functions.