Two.js: Cascading styles in SVG interpreter

Created on 29 Jan 2021  Â·  5Comments  Â·  Source: jonobr1/two.js

Hi!

I was wondering if there was a particular reason why the SVG interpreter doesn't consider cascading styles deeply. Maybe it's a performance issue?

For example, when my root element has stroke-width="2", width the following element:

<g class="pointer pointer-start" transform="translate(17.730055, 149.558318)" fill-rule="nonzero" stroke="#3333CC">
  <path d="M22.1199453,0.00168221378 C16.1547851,-0.073760829 10.4390569,2.39141966 6.39994526,6.78168221 C0.688521077,12.9688265 -1.3845919,21.6857549 0.92994526,29.7816822 C1.89923563,32.6933719 3.04810589,35.5421694 4.36994526,38.3116822 C6.93994526,44.0516822 22.1199453,64.0116822 22.1199453,64.0116822 L22.1799453,64.0116822 C22.1799453,64.0116822 37.3699453,44.0116822 39.9399453,38.3116822 C41.2617846,35.5421694 42.4106549,32.6933719 43.3799453,29.7816822 C45.6904339,21.6856644 43.6177952,12.97073 37.9099453,6.78168221 C33.8640075,2.39514037 28.1470522,-0.0690018407 22.1799453,0.00168221378" class="ShapePath stroke-blue" fill="#3333CC"></path>
  <circle class="ShapePath stroke-blue" fill="#FFFFFF" cx="22.1499453" cy="22.0516822" r="13.9"></circle>
</g>

Renders this:

<g id="two-1157" transform="matrix(1 0 0 1 17.730054 149.558319)" opacity="1">
  <path transform="matrix(1 0 0 1 22.153785 32.00584)" d="M -0.033842 -32.004159 C -5.999002 -32.079602 -11.71473 -29.614422 -15.753842 -25.224159 C -21.465266 -19.037015 -23.538379 -10.320087 -21.223842 -2.224159 C -20.254551 0.68753 -19.105681 3.536328 -17.783842 6.305841 C -15.213842 12.045841 -0.033842 32.005841 -0.033842 32.005841 L 0.026158 32.005841 C 0.026158 32.005841 15.216158 12.005841 17.786158 6.305841 C 19.107998 3.536328 20.256868 0.68753 21.226158 -2.224159 C 23.536647 -10.320177 21.464008 -19.035112 15.756158 -25.224159 C 11.710221 -29.610701 5.993265 -32.074843 0.026158 -32.004159 " fill="#3333CC" stroke="#3333CC" stroke-width="1" stroke-opacity="1" fill-opacity="1" visibility="visible" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" id="two-1158"></path>
  <path transform="matrix(1 0 0 1 22.149946 22.051681)" d="M 13.9 0 C 13.9 7.676758 7.676758 13.9 0 13.9 C -7.676759 13.9 -13.9 7.676758 -13.9 0 C -13.900001 -7.676759 -7.676759 -13.9 -0.000001 -13.9 C 7.676758 -13.900001 13.9 -7.676759 13.9 0 Z " fill="#FFFFFF" stroke="#3333CC" stroke-width="1" stroke-opacity="1" fill-opacity="1" visibility="visible" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" id="two-1159"></path>
</g>

So since the stroke-width property is hard initialized on each element, they're overriding the cascade. Some other properties seem to be working on their direct child. I think deep cascade is in the SVG spec? I may be mistaken here, but even then... loading an external file or svg from an element shows initially with the wrong visual. 🤔

question

All 5 comments

Hey, thanks for sharing this! I tried reconstructing your issue on this jsfiddle. I actually am able to control the styles via stylesheets like so:

Screen Shot 2021-01-30 at 11 10 29 AM

But, maybe I'm setting up the problem different from how you're using it?

One hunch I have is that.., if you're using two.load to load the SVG file the way that Two.js turns the string into a DOM element is to set the inner HTML of a <div /> that isn't placed on the page. _Since it's not actually appended to the DOM styles are never inherited_, and as such Two.js doesn't apply said styles to the object.

You are correct in this: when Two.js interprets an SVG (which is the method name — two.interpret(svgElem) that two.load(url) uses as well) it gleans all styles, both from its attributes _and_ from the method elem.getComputedStyle(), and applies them to the attributes. This could conflict with CSS styles defined elsewhere, though in the fiddle I posted above it doesn't seem to be an issue on Chrome MacOS.

Oh. Interesting!

I'm working on a project animating a "scroll story" where an SVG rendered on canvas / webgl in the background shows progress along diffrent panels. My issue was with groups, if I remember right. Stroke width on parent groups didn't always transfer to its children and that was a problem since my illustration is made with paths and lines only and with Sketch and Sketch's exporter seems to be a big fan of simplifying xml output by grouping attributes on parent groups when it can.

Well, I'll try to reproduce my use case later this week-end when I'm done with the project (on a big rush here 🤪 ). Don't close the issue and I'll update it with more details later.

Thanks for the update. Those are valid concerns that I think we can address. If you have sample SVGs that do reproduce the problem I'd be happy to look into it and resolve the issue. Two.js's SVG interpretation has only gotten good because people post when they have issues 😄

Best of luck with your project! Please share it with us when you've completed it.

Closing out based on resolution of #505. Thanks for reporting!

No, thanks to you for fixing it!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anderspitman picture anderspitman  Â·  4Comments

Neglexis picture Neglexis  Â·  7Comments

sami8github picture sami8github  Â·  3Comments

Sudhanshu4122 picture Sudhanshu4122  Â·  6Comments

caracal7 picture caracal7  Â·  8Comments