HTML5如何将一个SVG变形或动画到另一个SVG?

19

我进行了一些搜索,但是我必须承认,我对SVG没有任何经验。我看到了许多现代库,例如Raphael、PaperJS、KineticJS、EaselJS,但我不知道什么适合这里的目标,也许甚至CSS关键帧也能做到。

非常感谢指出这个问题的方向。

目标
在浏览器上,我想使用过渡类型ease-out将svg1动画变形为svg2。

限制条件

  • 任何JavaScript库(如果需要)
  • 应该能够将每个元素转换为相同ID的其他元素
  • 变形形状、路径、填充*、描边*、cx、cy、rc、ry
  • 应该可以在当前Firefox和Chrome上运行,最好能在IE 10上运行
  • 应该能够在新的移动设备上使用,如iPhone 5、nexus 4和7
  • 良好的性能,即使在移动设备上也是如此
  • 不介意呈现为<svg><canvas>

svg1:

<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
 <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
 <defs>
  <linearGradient id="svg_6">
   <stop stop-color="#828236" offset="0"/>
   <stop stop-color="#7d7dc9" offset="0.99219"/>
  </linearGradient>
  <linearGradient id="svg_7" x1="0" y1="0" x2="1" y2="1">
   <stop stop-color="#828236" offset="0"/>
   <stop stop-color="#7d7dc9" offset="0.99219"/>
  </linearGradient>
  <linearGradient y2="1" x2="1" y1="0" x1="0" id="svg_1">
   <stop offset="0" stop-color="#828236"/>
   <stop offset="0.99219" stop-color="#7d7dc9"/>
  </linearGradient>
 </defs>
 <g>
  <title>Layer 1</title>
  <ellipse ry="145" rx="116" id="svg_2" cy="201" cx="317" fill-opacity="0.36" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="5" stroke="#000000" fill="url(#svg_7)"/>
  <ellipse ry="21" rx="10" id="svg_5" cy="137" cx="274" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="5" stroke="#000000" fill="#0cd60c"/>
  <ellipse ry="31" rx="17" id="svg_9" cy="114" cx="346" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="5" stroke="#000000" fill="#0cd60c"/>
  <path id="svg_14" d="m235,239c55.66666,-1.33333 133.33334,-71.66667 167,-4l-167,4z" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="5" stroke="#000000" fill="none"/>
 </g>
</svg>

svg2:

<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
 <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
 <defs>
  <linearGradient id="svg_6">
   <stop offset="0" stop-color="#828236"/>
   <stop offset="0.99219" stop-color="#7d7dc9"/>
  </linearGradient>
  <linearGradient y2="1" x2="1" y1="0" x1="0" id="svg_7">
   <stop offset="0" stop-color="#828236"/>
   <stop offset="0.99219" stop-color="#7d7dc9"/>
  </linearGradient>
  <linearGradient id="svg_1" x1="0" y1="0" x2="1" y2="1">
   <stop stop-color="#828236" offset="0"/>
   <stop stop-color="#7d7dc9" offset="0.99219"/>
  </linearGradient>
 </defs>
 <g>
  <title>Layer 1</title>
  <ellipse id="svg_2" fill="url(#svg_7)" stroke="#000000" stroke-width="5" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" fill-opacity="0.36" cx="317" cy="201" rx="116" ry="145"/>
  <ellipse id="svg_5" stroke="#000000" fill="#0cd60c" stroke-width="5" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" cx="277.5" cy="132.5" rx="13.5" ry="25.5"/>
  <ellipse id="svg_9" stroke="#000000" fill="#0cd60c" stroke-width="5" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" cx="349.5" cy="110" rx="20.5" ry="35"/>
  <path id="svg_14" fill="none" stroke="#000000" stroke-width="5" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" d="m235,240c21.66666,81.66669 114.33334,96.33331 167,-4l-167,4z" />
 </g>
</svg>

提示:你可以在这里可视化,只需将代码粘贴到区域中即可。

我没有要展示的代码,我不想开始就走错。我的直觉告诉我,最佳解决方案有50%的可能性不涉及逐个遍历这些节点并进行差异比较!

6个回答

7

+1 我非常感谢你的回答,但是我还在寻找更广泛的变形,已经更新了问题。 - Fabiano Soriani
“更广泛的形态”是什么意思?我猜Raphaël适合你。 - Mike
1
这意味着,给定一个SVG,我想将其转换为任何其他SVG,SVG1中存在的所有ID也应该在SVG2中,因此它只是根据某些缓动函数对各种数学值进行插值。 - Fabiano Soriani

6

5

paraphrasing:

目前你必须在两个路径元素中使用相同数量的顶点,它们必须是相同类型并以相同顺序出现在另一个路径描述中。您还应该将两个多边形朝向相同的方向(左右和右左会产生不需要的结果)。

因此您可以这样做(请参见下面的链接示例),但您需要计划好,使形状A的路径和形状B的路径以完全相同的方式创建,具有相同的曲线类型、点等。

  1. 我在Illustrator中创建了一个形状
  2. 我复制了那个形状。
  3. 我修改了副本,小心不要添加顶点或从贝塞尔曲线类型更改为线性等
  4. 提示:要确认点数,您可以选择路径,然后转到路径>简化,它会显示该路径上的当前点...
  5. 我保存了SVG文件,然后将这些路径复制/粘贴到另一个带有动画信息的SVG中。
  6. 注意:路径放置在SVG文件中对应于Illustrator中所在图层名称的元素中。如果您保持两个形状在Illustrator中的不同图层中并清晰地命名它们,这将有助于保持SVG文件的组织。
  7. 注意#2:如果您创建的形状非常简单,例如仅包含直线,则可能会将其保存为_polygon而不是_path,我个人发现这很难进行动画处理,因此建议至少向单个点添加贝塞尔曲线控制柄(以及第二个形状中相应的相同点)。

1
谢谢,这似乎是进一步调查的好方法。我会更仔细地检查这是如何完成的,http://jaredstanley.com/html5/svg_mask/iku.svg看起来很酷=) - Fabiano Soriani
1
这是一个很好的总结。我使用了两条路径的方法(第二个隐藏),然后解析路径字符串以获取需要在它们之间进行缓动的顶点(在缓动中每帧更新路径字符串)。你可以在 http://runny.ink 上看到我用 JavaScript 缓动两条贝塞尔路径。 - Ezra Morse

3

事实上,正如Darwin所提到的,有很多库可以实现SVG形状变换。

我还发现了一些额外的库,如snap.svg、KUTE.js、GSAP。Svg.js有一个SVG变形插件,而我不认为velocity.js已经支持这个功能。


0

如果你可以将变形定义为一系列更改而不是第二个SVG,则可以使用d3 http://d3js.org/框架

它具有较陡峭的学习曲线,但它赋予你很大能力。如果你想要更容易的东西,我建议Raphael http://raphaeljs.com/ - 它的功能类似,但更容易入手。


-1

考虑使用纯SVG选项(即无JavaScript),并在之前的答案基础上构建,这里提供一个可行的示例,可能会减少其他人的困扰。


<svg height="120px" width="120px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
    <path>
        <animate 
            dur="10s" 
            repeatCount="indefinite" 
            attributeName="d" 
            calcMode="spline" 
            keySplines="0.4 0 0.2 1; 0.4 0 0.2 1" 
            fill="freeze" 
            values="
                M 336,0 
                c -97.2,0 -176,78.8 -176,176 
                c 0,18.7 2.9,36.8 8.3,53.7 
                c 0,0 0,0 -161.3,161.3
                c -4.5,4.5 -7,10.6 -7,17 
                c 0,0 0,0 0,80
                c 0,13.3 10.7,24 24,24 
                c 0,0 0,0 80,0 
                c 13.3,0 24,-10.7 24,-24 
                c 0,0 0,0 0,-40
                c 0,0 0,0 40,0
                c 13.3,0 24,-10.7 24,-24 
                c 0,0 0,0 0,-40
                c 0,0 0,0 40,0
                c 6.4,0 12.5,-2.5 17,-7 
                c 0,0 0,0 33.3,-33.3
                c 16.9,5.4 35,8.3 53.7,8.3 
                c 97.2,0 176,-78.8 176,-176 
                C 512,78.8 433.2,0 336,0 
                Z
                M 376,176.5 
                c -22.4,0 -40.5,-18.1 -40.5,-40.5 
                c 0,-10.5 4,-20 10.5,-27.2 
                c 7.4,-8.2 18.1,-13.3 30,-13.3 
                c 22.4,0 40.5,18.1 40.5,40.5 
                c 0,22.4 -18.1,40.5 -40.5,40.5 
                Z;
                M 256,0 
                c -45,0 -85.8,15.8 -115.6,41.5 
                c -30.2,26.1 -49,62.4 -49,102.5
                c 0,0 0,0 0,48
                c 0,0 0,0 -18.3,0
                c -35.3,0 -73.1,35.3 -73.1,64
                c 0,0 0,0 0,192
                c 0,35.3 32.8,64 73.1,64 
                c 0,0 0,0 78.9,0
                c 0,0 0,0 104,0
                c 0,0 0,0 107,0
                c 0,0 0,0 75.9,0
                c 40.3,0 73.1,-28.7 73.1,-64 
                c 0,0 0,0 0,-192
                c 0,-35.3 -32.8,-64 -73.1,-64 
                c 0,0 0,0 -18.3,0
                c 0,0 0,0 0,-48
                c 0,-39.2 -17.9,-74.7 -47,-100.7 
                C 343.7,16.6 302.1,0 256,0 
                Z 
                M 164.6,192 
                c 0,0 0,0 0,-48
                c 0,-44.2 40.9,-80 91.4,-80 
                c 50.5,0 91.4,35.8 91.4,80 
                c 0,0 0,0 0,48
                c 0,0 0,0 24,0
                Z;
                M 336,0 
                c -97.2,0 -176,78.8 -176,176 
                c 0,18.7 2.9,36.8 8.3,53.7 
                c 0,0 0,0 -161.3,161.3
                c -4.5,4.5 -7,10.6 -7,17 
                c 0,0 0,0 0,80
                c 0,13.3 10.7,24 24,24 
                c 0,0 0,0 80,0 
                c 13.3,0 24,-10.7 24,-24 
                c 0,0 0,0 0,-40
                c 0,0 0,0 40,0
                c 13.3,0 24,-10.7 24,-24 
                c 0,0 0,0 0,-40
                c 0,0 0,0 40,0
                c 6.4,0 12.5,-2.5 17,-7 
                c 0,0 0,0 33.3,-33.3
                c 16.9,5.4 35,8.3 53.7,8.3 
                c 97.2,0 176,-78.8 176,-176 
                C 512,78.8 433.2,0 336,0 
                Z
                M 376,176.5 
                c -22.4,0 -40.5,-18.1 -40.5,-40.5 
                c 0,-10.5 4,-20 10.5,-27.2 
                c 7.4,-8.2 18.1,-13.3 30,-13.3 
                c 22.4,0 40.5,18.1 40.5,40.5 
                c 0,22.4 -18.1,40.5 -40.5,40.5 
                Z;
                "/>
    </path>
</svg>


这是另一件事情,它将所有动画放在一个SVG文件中,问题是如何将一个SVG文件转换为另一个。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接