sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
79.31k stars 4.18k forks source link

SVGs with animateTransform lag for an extremely long time when embedded #11681

Closed justingolden21 closed 5 months ago

justingolden21 commented 5 months ago

Describe the bug

SVG elements inline inside svelte files with will lag a lot before starting. Reproduced locally in dev, with build and in production website, on win10 and linux

Reproduction

https://svelte.dev/repl/a58a0871b908479fb265ea7e10b17f84?version=4.2.17

<script>
    let name = 'world';
</script>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
    <path d="m8 16v-16" fill="none" stroke="#EAB308">
        <animateTransform
            attributeName="transform"
            type="rotate"
            from="0 8 8"
            to="360 8 8"
            dur="12s"
            repeatCount="indefinite" />
    </path>
</svg>

<h1>Hello {name}!</h1>

Logs

N/A

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (16) x64 11th Gen Intel(R) Core(TM) i7-11700K @ 3.60GHz
    Memory: 18.53 GB / 31.87 GB
  Binaries:
    Node: 20.11.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 10.2.4 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.14.1 - ~\AppData\Roaming\npm\pnpm.CMD
  Browsers:
    Edge: Chromium (123.0.2420.97)
    Internet Explorer: 11.0.19041.4355

Severity

annoyance

justingolden21 commented 5 months ago

If I link to a static SVG file, then it works fine:

<img src="line.svg" alt="">

But when it's inline, then it doesn't work.

I marked this as "annoyance" instead of anything higher because it's not applicable to that many, but for me this is huge since it blocks me from releasing an update where I would have a dynamic animated SVG background. I can't have dynamic data in a static SVG, so I need it embedded in HTML / inside Svelte.

I also noticed this happens in chromium browsers (chrome, edge, and brave) but not in firefox, and noticed this both in windows 10 and in linux

justingolden21 commented 5 months ago

I should note I'm using svelte 4 and so is the repl.

Prinzhorn commented 5 months ago

This is very unlikely a Svelte issue, how could it? The markup is there, you can see it in dev tools. This screams Chromium bug (the "lag" appears to be one "duration" cycle that just isn't animated). I'm sure you'll find something in the Chromium issue tracker. First result I found was https://issues.chromium.org/issues/40699044

justingolden21 commented 5 months ago

Thanks for the reply!

I would generally agree, but when I take a vanilla HTML file with a SVG embedded, then it works fine in chromium:

<!DOCTYPE html>
<html>
<head>
    <title>Hello World</title>
</head>
<body>
    Hello World
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
        <path d="m8 16v-16" fill="none" stroke="#EAB308">
            <animateTransform
                attributeName="transform"
                type="rotate"
                from="0 8 8"
                to="360 8 8"
                dur="12s"
                repeatCount="indefinite" />
        </path>
    </svg>
</body>
</html>

There is zero lag at all in the animation no matter how many times I refresh.

Do you think it's a chromium+HMR thing?

Also, what did you search to find that issue in the Chromium issue tracker?

Thanks again for the reply.

Prinzhorn commented 5 months ago

but when I take a vanilla HTML file with a SVG embedded, then it works fine in chromium

This is something entirely different. Svelte uses DOM methods to create a structure that matches what you've described with an HTML-like Syntax in a *.svelte file.

Check out the two Fiddles linked in the Chromium tracker. The first one is broken to this day. It does this:

var svgnode = document.createElementNS('http://www.w3.org/2000/svg','svg');
var circle = document.createElementNS('http://www.w3.org/2000/svg','circle');
circle.setAttribute("cx", "10");
circle.setAttribute("cy", "10");
circle.setAttribute("r", "10");
circle.setAttribute("fill", "blue");
var ani = document.createElementNS("http://www.w3.org/2000/svg","animateTransform");
ani.setAttribute("attributeName", "transform");
ani.setAttribute("attributeType", "xml");
ani.setAttribute("type", "translate" );
ani.setAttribute("from", "10");
ani.setAttribute("to", "100");
ani.setAttribute("begin", "0s");
ani.setAttribute("dur", "2s");
ani.setAttribute("fill", "freeze");
circle.appendChild(ani);
svgnode.appendChild(circle);
document.getElementById('mydiv').appendChild(svgnode);

which more closely resembles what Svelte does.

But as the Chromium issue shows, this is only a problem when it happens after the page has loaded. Which might be unavoidable with Svelte, because the rendering might happen a tick later. But I'm not sure about that, are you initializing your Svelte app synchronously right in a <script> or only on dom-ready?

Also, what did you search to find that issue in the Chromium issue tracker?

animateTransform dynamic

Prinzhorn commented 5 months ago

Save this as vanilla HTML and see the same lag:

<!DOCTYPE html>
<html>
<head>
    <title>Hello World</title>
</head>
<body>
  <script>
    setTimeout(() => {
      document.body.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
        <path d="m8 16v-16" fill="none" stroke="#EAB308">
            <animateTransform
                attributeName="transform"
                type="rotate"
                from="0 8 8"
                to="360 8 8"
                dur="12s"
                repeatCount="indefinite" />
        </path>
    </svg>`
    }, 100);
  </script>
</body>
</html>
justingolden21 commented 5 months ago

Ah I see, you're right.

Thanks for the replies and for the example. I'll mark this ticket as closed.

Hopefully chromium figures it out. Makes the update I wanted to publish unusable.