【问题标题】:SVG frame-based animation基于 SVG 帧的动画
【发布时间】:2021-03-27 10:59:02
【问题描述】:

谁能建议在 svg 中基于 JPEG 实现基于帧的动画的最佳方法是什么?

我发现的一个例子是这样的:

<svg version="1.1" baseProfile="tiny" id="svg-root"
  width="100%" height="100%" viewBox="0 0 480 360"
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

   <image width="320" height="240" xlink:href="test1.jpg">
      <animate id='frame_0' attributeName='display' values='inline;none'
               dur='0.5s' fill='freeze' begin="0s" repeatCount="indefinite"/>
   </image>

   <image width="320" height="240" xlink:href="test2.jpg">
      <animate id='frame_1' attributeName='display' values='none;inline'
               dur='0.5s' fill='freeze' begin="0.5s" repeatCount="indefinite" />
   </image>

</svg>

它适用于 2 帧,但不能真正缩放。我想要一个可以处理 100 帧甚至更多帧的东西。

【问题讨论】:

    标签: animation svg


    【解决方案1】:

    这更容易:

    <svg version="1.1" baseProfile="tiny" id="svg-root"
      width="100%" height="100%" viewBox="0 0 480 360"
      xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    
      <image width="320" height="240" xlink:href="test1.jpg">
        <animate attributeName="xlink:href" 
          values="test1.jpg;test2.jpg" 
          begin="0s" repeatCount="indefinite" dur="1s"/>
      </image>
    
    </svg>
    

    【讨论】:

    • 这仅适用于 Firefox。原始代码适用于 FF 和 Chrome :-|
    • 有趣,我在 Linux 上测试了 Firefox、Chromium 和 Opera,它们三个都可以工作!但事实上,出于某种原因,Windows 上的 Chrome 和 Safari 并没有。
    • 这样做的一个可能的缺点是不会预加载帧。
    • 那么,如何将所有图像放入一个长长的 JPG 条带中,该条带像传统电影条带一样有效,并使用关键帧和 calcMode="discrete" 进行 animateTransform 呢?在此周围可能有一个 SVG 元素,它建立了一个视口,条带在该视口内“移动”。希望这是有道理的。
    • 感谢@ThomasW 的回答。 FWIW,您可以通过将各个帧放入 &lt;defs&gt; 块中来进行预加载。几帧图像条是可以的,这通常用于CSS sprites,但它不适合大型动画,因为浏览器可能无法正确加载如此大的图像,正如我最近发现的那样。
    【解决方案2】:

    另一种方法,

    如果您的动画正在运行,但只是制作过多而无法设置文件,您可以使用模板来生成 SVG。

    使用 Grunt.Js 之类的东西来读取目录中的所有图像,然后使用下划线模板构建 SVG 帧,就像您已经从文件路径数组中设置它们一样。

    这些代码 sn-ps 可能无法开箱即用,但非常接近。

    这里 grunt 文件抓取文件夹中的文件,检查它们是否是图像,然后将它们推送到数组中。

    // gruntfile.js //
    
    var fs = require('fs');
    var path = require('path');
    var _ = require("underscore");
    
    grunt.registerTask('Build Animated SVG', function () {
    
        var template = grunt.file.read("/path to SVG underscore template/");    //see SVG section below.
    
            var frames = [];
            var pathtoframes = "mypath";
            var mySVG = "mysvg.svg";
    
            fs.readdirSync(path.resolve(pathtoframes)).forEach(function (file) {
    
                if (filetype == "svg" || filetype == "png" || filetype == "jpg" || filetype == "gif") {
                    var frame = {};
                    frame.src = pathtoframes + "/" + file;
                    frames.push(frame);
                }
            });
    
    var compiledSVG = _.template(template, {frames:frames});
    
    grunt.file.write(path.resolve(pathtoframes) + "/compiled_" + mySVG, compiledSVG);
    
    });
    

    这个模板将被 grunt 文件读入,下划线将遍历每个文件并将其写入一个大字符串。然后 Grunt 将其保存为可以加载的 SVG。

    <!-- SVG underscore template -->
        <svg version="1.1" baseProfile="tiny" id="svg-root"
              width="100%" height="100%" viewBox="0 0 480 360"
              xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    
              <% _.each(frames, function(frame, index){ %>
                 <image width="320" height="240" xlink:href="<%= frame.src %>">
                    <animate 
                             id='frame_<%= index %>' 
                             attributeName='display' 
                             values='none;inline'
                             dur='0.5s' 
                             fill='freeze' 
                             begin="0.5s" 
                             repeatCount="indefinite" 
                             />
                </image>
            <% } %>
        </svg>
    

    【讨论】:

      【解决方案3】:

      https://michaelsboost.github.io/SVGAnimFrames/

      为此,您可以轻松地使用我的库 SVGAnimFrames。只需调用 1 行代码...

      SVGAnimFrames("#bounce svg", "repeat", "40", "0");
      

      请参阅Github repo 了解如何使用它。

      理想情况下,您最好的选择是使用 spritesheet 并逐帧制作动画,从而最大限度地减少不必要的 http 请求。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-17
        • 1970-01-01
        • 2014-09-17
        • 2020-02-29
        • 2015-01-15
        • 2019-03-27
        相关资源
        最近更新 更多