juliangarnier / anime

JavaScript animation engine
https://animejs.com
MIT License
50.4k stars 3.68k forks source link

Possible problem with SVG and transform-box #887

Open xdanielc opened 7 months ago

xdanielc commented 7 months ago

I was using mathplotlib and discovered I could export SVGs so I thought about adding animation, but apparently I can't use the stroke-box or any other smaller box that fits the content, which for properties suuch as rotation or scale is important.

I think this could be a duplicate of #823 but would be nice to have some workaround for such an extensively used python library that can output good looking charts.

Here's the code, I tried to keep as little as possible so you could reproduce the bug.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <script src="main.js" defer, type="module"></script>
   <link rel="stylesheet" href="style.css">
   <style>
      *{
         margin: 0;
         padding: 0;
      }
      body{
         display: grid;
      }
      g[id^="xtick_"], g[id^="ytick_"]{
         transform-box: stroke-box;
      }
   </style>
</head>
<body>
<div class="graf">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="460.8pt" height="345.6pt" viewBox="0 0 460.8 345.6"
   xmlns="http://www.w3.org/2000/svg" version="1.1">
   <defs>
      <style type="text/css">*{stroke-linejoin: round; stroke-linecap: butt}</style>
   </defs>
   <g id="figure_1">
      <g id="patch_1"><path d="M 0 345.6 L 460.8 345.6 L 460.8 0 L 0 0 z" style="fill: #ffffff"/></g>
      <g id="axes_1">
         <g id="patch_2"><path d="M 57.6 307.584 L 414.72 307.584 L 414.72 41.472 L 57.6 41.472 z" style="fill: #ffffff"/></g>
         <g id="matplotlib.axis_1">
            <g id="xtick_1">
               <g id="line2d_1">
                  <defs><path id="mc02f30e17d" d="M 0 0 L 0 3.5" style="stroke: #000000; stroke-width: 0.8"/></defs>
                  <g><use xlink:href="#mc02f30e17d" x="57.6" y="307.584" style="stroke: #000000; stroke-width: 0.8"/></g>
               </g>
               <g id="text_1"><text style="font: 14px 'Inter'; text-anchor: middle" x="57.6" y="324.766812" transform="rotate(-0 57.6 324.766812)">0</text></g>
            </g>
            <g id="xtick_2">
               <g id="line2d_2"><g><use xlink:href="#mc02f30e17d" x="171.8784" y="307.584" style="stroke: #000000; stroke-width: 0.8"/></g></g>
               <g id="text_2"><text style="font: 14px 'Inter'; text-anchor: middle" x="171.8784" y="324.766812" transform="rotate(-0 171.8784 324.766812)">2</text></g>
            </g>
            <g id="xtick_3">
               <g id="line2d_3"><g><use xlink:href="#mc02f30e17d" x="286.1568" y="307.584" style="stroke: #000000; stroke-width: 0.8"/></g></g>
               <g id="text_3"><text style="font: 14px 'Inter'; text-anchor: middle" x="286.1568" y="324.766812" transform="rotate(-0 286.1568 324.766812)">4</text></g>
            </g>
            <g id="xtick_4">
               <g id="line2d_4"><g><use xlink:href="#mc02f30e17d" x="400.4352" y="307.584" style="stroke: #000000; stroke-width: 0.8"/></g></g>
               <g id="text_4"><text style="font: 14px 'Inter'; text-anchor: middle" x="400.4352" y="324.766812" transform="rotate(-0 400.4352 324.766812)">6</text></g>
            </g>
            <g id="text_5"><text style="font: 14px 'Inter'; text-anchor: middle" x="236.16" y="342.13025" transform="rotate(-0 236.16 342.13025)">Something</text></g>
         </g>
         <g id="matplotlib.axis_2">
            <g id="ytick_1">
               <g id="line2d_5">
                  <defs><path id="m6af464285a" d="M 0 0 L -3.5 0 " style="stroke: #000000; stroke-width: 0.8"/></defs>
                  <g><use xlink:href="#m6af464285a" x="57.6" y="255.990857" style="stroke: #000000; stroke-width: 0.8"/></g>
               </g>
               <g id="text_6"><text style="font: 14px 'Inter'; text-anchor: end" x="50.6" y="261.082263" transform="rotate(-0 50.6 261.082263)">20</text></g>
            </g>
            <g id="ytick_2">
               <g id="line2d_6"><g><use xlink:href="#m6af464285a" x="57.6" y="206.619429" style="stroke: #000000; stroke-width: 0.8"/></g></g>
               <g id="text_7"><text style="font: 14px 'Inter'; text-anchor: end" x="50.6" y="211.710835" transform="rotate(-0 50.6 211.710835)">40</text></g>
            </g>
            <g id="ytick_3">
               <g id="line2d_7"><g><use xlink:href="#m6af464285a" x="57.6" y="157.248" style="stroke: #000000; stroke-width: 0.8"/></g></g>
               <g id="text_8"><text style="font: 14px 'Inter'; text-anchor: end" x="50.6" y="162.339406" transform="rotate(-0 50.6 162.339406)">60</text></g>
            </g>
            <g id="ytick_4">
               <g id="line2d_8"><g><use xlink:href="#m6af464285a" x="57.6" y="107.876571" style="stroke: #000000; stroke-width: 0.8"/></g></g>
               <g id="text_9"><text style="font: 14px 'Inter'; text-anchor: end" x="50.6" y="112.967978" transform="rotate(-0 50.6 112.967978)">80</text></g>
            </g>
            <g id="ytick_5">
               <g id="line2d_9"><g><use xlink:href="#m6af464285a" x="57.6" y="58.505143" style="stroke: #000000; stroke-width: 0.8"/></g></g>
               <g id="text_10"><text style="font: 14px 'Inter'; text-anchor: end" x="50.6" y="63.596549" transform="rotate(-0 50.6 63.596549)">100</text></g>
            </g>
            <g id="text_11"><text style="font: 14px 'Inter'; text-anchor: middle" x="19.733125" y="174.528" transform="rotate(-90 19.733125 174.528)">Wathever</text></g>
         </g>
         <g id="line2d_10"><path d="M 114.7392 295.488 L 171.8784 196.745143 L 400.4352 102.939429 " clip-path="url(#pbadfb57762)" style="fill: none; stroke: #fe4a49; stroke-width: 2.4; stroke-linecap: square"/></g>
         <g id="line2d_11"><path d="M 114.7392 265.865143 L 171.8784 216.493714 L 400.4352 169.590857 " clip-path="url(#pbadfb57762)" style="fill: none; stroke: #fed766; stroke-width: 2.4; stroke-linecap: square"/></g>
         <g id="line2d_12"><path d="M 114.7392 216.493714 L 171.8784 295.488 L 400.4352 201.682286 " clip-path="url(#pbadfb57762)" style="fill: none; stroke: #009fb7; stroke-width: 2.4; stroke-linecap: square"/></g>
         <g id="line2d_13"><path d="M 114.7392 246.116571 L 171.8784 147.373714 L 400.4352 53.568 " clip-path="url(#pbadfb57762)" style="fill: none; stroke: #492b7c; stroke-width: 2.4; stroke-linecap: square"/></g>
         <g id="patch_3"><path d="M 57.6 307.584 L 400.4352 307.584" style="fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square"/></g>
         <g id="text_12"><text style="font: 700 18px 'Inter'; text-anchor: middle" x="236.16" y="29.472" transform="rotate(-0 236.16 29.472)">A random graph</text></g>
      </g>
   </g>
   <defs>
      <clipPath id="pbadfb57762">
         <rect x="57.6" y="41.472" width="357.12" height="266.112"/>
      </clipPath>
   </defs>
</svg>
</div>
</body>
</html>

JS

import anime from "animejs";

let tl = anime.timeline({autoplay: true, complete: function(){
    tl.reverse()
}})

tl.add({
    targets: 'g[id^="xtick_"], g[id^="ytick_"]',
    translateY: [100, 0],
    opacity: [0, 1],
    scale: [1.5, 1],
    delay: anime.stagger(100),
    easing: 'linear',
    duration: 1200
})
juliangarnier commented 7 months ago

Hey thanks for the reporting this! Could you add more details regarding:

I can't use the stroke-box or any other smaller box that fits the content

I'm not sure to understand exactly what you mean. What is the issue exactly and expected behaviour?

Thanks!

xdanielc commented 7 months ago

Could you add more details

Yeah, in the style tag you can see I'm using that property and value, which if you change the scale will change the point of transformation (I didn't use this property before maybe it's recent-ish?)

g[id^="xtick_"], g[id^="ytick_"]{
   transform-box: stroke-box;
}
juliangarnier commented 7 months ago

Sorry for the late reply I though I already responded.

I tried to keep as little as possible so you could reproduce the bug.

You still haven't described what the bug is, and what is the expected behaviour.

Also can you share a live example ?

Thanks!!