Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
645 views
in Technique[技术] by (71.8m points)

animation - Animated SVG sprite in IMG tag vibrates in horizontal direction

See code snippet for bouncing circle in 24 sprite frames.

<text y='12'>n:0</text> displays the sprite framenr

How can I get rid of the horizontal jitter movement, is it SVG or CSS?

The offset is less at less frames in sprite, and gets worse and worse at more frames per sprite

It is less obvious in Chromium, and more obvious in FireFox

I tried https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio

<style>
  #bounce {
    --w: 200px;
    width: var(--w);
    height: var(--w);
    overflow: hidden;
    display: inline-flex;
    background: lightgreen;
  }

  img {
    position: relative;
    left: 0;
    animation: moveX 1s steps(23) infinite;
  }

  @keyframes moveX {
    to {
      transform: translate(-100%);
      left: 100%;
    }
  }

</style>
<div id="bounce"><img id=svgimg src="SVG injected here"></div>
<script>
  window.onload = () => svgimg.src = `data:image/svg+xml,` + svg.innerHTML;
</script>
<template id=svg>
  <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2400 100' height='200'>
    <style>
      ellipse {
        fill: none;
        stroke: green;
        stroke-width: 5;
      }

    </style>
    <g transform='translate(0 0)'>
      <ellipse cx='50' cy='32' rx='30' ry='30'></ellipse><text y='12'>n:0</text>
    </g>
    <g transform='translate(100 0)'>
      <ellipse cx='50' cy='32.3' rx='30' ry='30'></ellipse><text y='12'>n:1</text>
    </g>
    <g transform='translate(200 0)'>
      <ellipse cx='50' cy='33.2' rx='30' ry='30'></ellipse><text y='12'>n:2</text>
    </g>
    <g transform='translate(300 0)'>
      <ellipse cx='50' cy='34.5' rx='30' ry='30'></ellipse><text y='12'>n:3</text>
    </g>
    <g transform='translate(400 0)'>
      <ellipse cx='50' cy='36.5' rx='30' ry='30'></ellipse><text y='12'>n:4</text>
    </g>
    <g transform='translate(500 0)'>
      <ellipse cx='50' cy='39' rx='30' ry='30'></ellipse><text y='12'>n:5</text>
    </g>
    <g transform='translate(600 0)'>
      <ellipse cx='50' cy='42' rx='30' ry='30'></ellipse><text y='12'>n:6</text>
    </g>
    <g transform='translate(700 0)'>
      <ellipse cx='50' cy='45.7' rx='30' ry='30'></ellipse><text y='12'>n:7</text>
    </g>
    <g transform='translate(800 0)'>
      <ellipse cx='50' cy='49.8' rx='30' ry='30'></ellipse><text y='12'>n:8</text>
    </g>
    <g transform='translate(900 0)'>
      <ellipse cx='50' cy='54.5' rx='31.3' ry='30'></ellipse><text y='12'>n:9</text>
    </g>
    <g transform='translate(1000 0)'>
      <ellipse cx='50' cy='59.8' rx='33.9' ry='30'></ellipse><text y='12'>n:10</text>
    </g>
    <g transform='translate(1100 0)'>
      <ellipse cx='50' cy='65.7' rx='36.9' ry='30'></ellipse><text y='12'>n:11</text>
    </g>
    <g transform='translate(1200 0)'>
      <ellipse cx='50' cy='72' rx='40' ry='30'></ellipse><text y='12'>n:12</text>
    </g>
    <g transform='translate(1300 0)'>
      <ellipse cx='50' cy='65.7' rx='36.9' ry='30'></ellipse><text y='12'>n:13</text>
    </g>
    <g transform='translate(1400 0)'>
      <ellipse cx='50' cy='59.8' rx='33.9' ry='30'></ellipse><text y='12'>n:14</text>
    </g>
    <g transform='translate(1500 0)'>
      <ellipse cx='50' cy='54.5' rx='31.3' ry='30'></ellipse><text y='12'>n:15</text>
    </g>
    <g transform='translate(1600 0)'>
      <ellipse cx='50' cy='49.8' rx='30' ry='30'></ellipse><text y='12'>n:16</text>
    </g>
    <g transform='translate(1700 0)'>
      <ellipse cx='50' cy='45.7' rx='30' ry='30'></ellipse><text y='12'>n:17</text>
    </g>
    <g transform='translate(1800 0)'>
      <ellipse cx='50' cy='42' rx='30' ry='30'></ellipse><text y='12'>n:18</text>
    </g>
    <g transform='translate(1900 0)'>
      <ellipse cx='50' cy='39' rx='30' ry='30'></ellipse><text y='12'>n:19</text>
    </g>
    <g transform='translate(2000 0)'>
      <ellipse cx='50' cy='36.5' rx='30' ry='30'></ellipse><text y='12'>n:20</text>
    </g>
    <g transform='translate(2100 0)'>
      <ellipse cx='50' cy='34.5' rx='30' ry='30'></ellipse><text y='12'>n:21</text>
    </g>
    <g transform='translate(2200 0)'>
      <ellipse cx='50' cy='33.2' rx='30' ry='30'></ellipse><text y='12'>n:22</text>
    </g>
    <g transform='translate(2300 0)'>
      <ellipse cx='50' cy='32.3' rx='30' ry='30'></ellipse><text y='12'>n:23</text>
    </g>
  </svg></template>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I have made some changes to the fiddle, and it seems to work. One point seems to be that the last left coordinate in the transformation should be the total length of the svg minus the length of the window. In the fiddle, you can change

transform: translate(calc(-1 * var(--steps) * var(--w)));

to

transform: translate(calc(-1 * calc(var(--steps) - 1) * var(--w)));

In your snippet, the transform: translate(-100%); percentage should be (2300/2400)*100.

More importantly, I have added the width='2400' property to the svg. The matter of setting a missing length property for an svg is quite complex, and I do not think that every browser behaves the same way.

In the fiddle, I have changed the --w property to 100, which is the height and width of each svg frame. If you want to set it to 200, you would need to change the size of the svg and the coordinates of each frame proportionally.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...