如何在IOS中对SVG路径进行动画处理?

9

我有一个像这样的SVG路径:

<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" version="1.1"  baseProfile="full"> 
    <path d="M47.16,66.38c0.62,1.65-0.03,2.93-0.92,4.28c-5.17,7.8-8.02,11.38-14.99,18.84c-2.11,2.25-1.5,4.18,2,3.75c7.35-0.91,28.19-5.83,40.16-7.95" style="fill:none;stroke:black;stroke-width:2" />
</svg>

我可以渲染路径,但似乎找不到一种方法使路径动画化,以便看起来像是用铅笔“绘制”。animate节点适用于单个坐标,但不适用于路径。

最终,我将在iPhone应用程序中使用此动画,无论是使用解析器还是UIWebView。


请参见https://dev59.com/FmYq5IYBdhLWcg3wtCoo#14282391。 - Phrogz
嗨,你在iOS中如何使用这个? - Misha
3个回答

8
尝试对'stroke-dashoffset'进行动画处理(请注意,您需要使用匹配的'stroke-dasharray'),请参见this example。成功使用此功能需要计算路径的长度,可以通过脚本获取:
var pathlength = yourPathElm.getTotalLength()

示例上查看源代码,以了解如何完成。


非常好的例子,谢谢!我一直在研究您的示例,只隔离适用于单个笔画的元素。我已经接近成功了,除了有几个问题我无法解决:1) 如果我从您的<g>节点中删除translate,为什么我看不到任何东西? 2) 为什么您在stroke-dasharray的样式声明中重复了54两次? - Julian
  1. 因为路径是使用该偏移量定义的(快速inkscape hack)。您可以将变换应用于路径“d”属性并从“g”元素中删除它。
  2. 只是因为我认为这更清晰,它在短划线长度和间隙长度之间交替,但如果它们相同,则确实可以只指定一个数字(浏览器将扩展它们成为偶数个短划线/间隙)请参见http://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty
- Erik Dahlström
我在想,我的路径中是否有移动会重置破折号的描边。有没有办法规避这个问题?(http://www.stretchsketch.com/animate.svg) - dr jerry
begin属性表示动画开始的偏移量。请解释一下什么是rect.click。具有id rect的矩形没有与之关联的点击处理程序。 - Rajkamal Subramanian
@drjerry:嗯,我建议在有moveto时拆分路径,以使其更简单。 - Erik Dahlström
1
@rajkamal: begin="rect.click" 的意思是每当具有id为“rect”的元素被点击时触发动画,请参见http://www.w3.org/TR/SVG11/animate.html#SyncbaseValueSyntax。 - Erik Dahlström

2

我曾经尝试很长时间在不添加额外脚本到头部的情况下完成这个任务(由于我对JavaScript没有任何了解,所以帮助不大),因此这里提供一种解决方案:

<path d="..." stroke-dasharray="">
  <animate attributeName="stroke-dashoffset" from="" to="0" dur="1s" begin="0s"
           onload="var length = parentNode.getTotalLength();
                   parentNode.setAttribute('stroke-dasharray',length+','+length);
                   this.setAttribute('from',length)" />
</path>

我在这里添加了额外的换行以便阅读。

这在SVG中是合法的(虽然在HTML中不合法),因为svg:animate元素允许onload,这是大多数HTML元素所不允许的。


0

一旦你已经渲染了你的SVG路径,想让它看起来像被铅笔绘制,你可以简单地用一个不透明的层覆盖它,然后动画移动这个层沿着路径。

要找到你将移动该层的CGPath,你可以使用这个库: https://github.com/arielelkin/PocketSVG

这将把SVG数据解析成UIBezierPath。然后:

SvgToBezier *myBezier = [[SvgToBezier alloc] initFromSVGPathNodeDAttr:@"M176.17,369.617c0,0,335.106-189.361,214.894,38.298s129.787,282.978,178.723,42.553C618.724,210.042,834.681,87.702,790,307.915" rect:CGRectMake(0,0,1024,768)];

UIBezierPath *myPath = myBezier.bezier;

CAKeyframeAnimation *mySVGPathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
bounceAnimLeft.duration = 3;
bounceAnimLeft.path = myPath.CGPath;

[myObjectToMove.layer addAnimation:mySVGPathAnimation forKey:@"pathAnimation"];

你能对如何使用你的代码片段给出更多解释吗? - DevonDahon
如果你的路径在SVG格式中,并且想要制作出看上去像是正在被绘制的动画,那么首先你需要使用我上面发布的代码将SVG转换成CGPath。一旦你有了CGPath,可以参考这个链接:http://oleb.net/blog/2010/12/animating-drawing-of-cgpath-with-cashapelayer/ - Eric

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