IMG 标签中的动画 SVG 精灵在水平方向振动 注意

问题描述

查看 24 个精灵帧中弹跳圆的代码片段。

<text y='12'>n:0</text> 显示精灵帧

我怎样才能摆脱水平抖动的移动,是SVG还是CSS?

精灵帧越少偏移越小,每个精灵帧越多偏移越差

在 Chromium 中不太明显,在 FireFox 中更明显

我试过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>

注意

我可以使用库,我正在生成(和更改)精灵表客户端

这个圈子的模板是一个模板文字

<template id="bounce">
  <ellipse cx='50' 
           cy='${72-1*ease(40)}' 
           rx='${minmax(30,40-ease(20))}' 
           ry='30' fill='none' stroke='black' stroke-width='5'>
  </ellipse>
  <text y='12'>n:${framenr}</text>
</template>

一个 Web 组件然后(重新)创建精灵和 IMG,以及显示精灵的一切

<svg-spriter do="bounce" steps="24" duration="1s" animation="infinite"></svg-spriter>

解决方法

我对 fiddle 进行了一些更改,它似乎有效。有一点似乎是变换中的最后一个 left 坐标应该是 svg 的总长度减去窗口的长度。在小提琴中,您可以更改

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

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

在您的代码段中,transform: translate(-100%); 百分比应为 (2300/2400)*100

更重要的是,我已将 width='2400' 属性添加到 svg。为 svg 设置缺失的长度属性的问题非常复杂,我认为每个浏览器的行为方式都不相同。

在小提琴中,我已将 --w 属性更改为 100,即每个 svg 框架的高度和宽度。如果要将其设置为 200,则需要按比例更改 svg 的大小和每帧的坐标。

,

是的,这似乎与您的框架对齐有关。如果我在没有翻译的情况下绘制所有省略号且不透明度为 0.05,则会给出以下图像:

Elipses drawn all at once

乍一看,虽然粗体绿色的厚度在左侧少了一个像素,但还是可以的。因此,在其“空气”位置尝试使用奇数宽度的椭圆可能是值得的。

顺便说一句,SVG(规范)也有您可能会使用的 shape-rendering 参数,但在您的情况下,这应该很少成为问题:

SVG shape-rendering