我在Inkscape中制作了一个徽标。为了学习,我想通过SVG中的动画支持在徽标旋转中制作轮子形状。
实现旋转很容易,但我很难指定正确的旋转轴。形状是一个齿轮,我希望它围绕它的中心旋转。试验和错误给出了xy坐标(47.1275,1004.17)(其组件奇怪地不对称,但我猜这与Inkscape应用的转换矩阵有关)是一个很好的近似(参见下面的animateTransform标签),但我怎么会从第一原则得到这个?
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 321.281 150.799" xmlns:dc="http://purl.org/dc/elements/1.1/">
<g transform="translate(-9.9178912,-891.57237)">
<g transform="matrix(1.9522781,0,0,1.9522781,4.6434311,-1008.1558)">
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 47.1275 1004.17" to="45 47.1275 1004.17" dur="2s" fill="freeze" additive="sum" repeatCount="indefinite" />
<g transform="matrix(0.65043772,0,0,0.65043772,-143.67477,980.4256)" stroke="#666" stroke-miterlimit="4" stroke-dasharray="none" stroke-width="7.68713093" fill="none">
<path stroke-linejoin="miter" d="m293.404-3.51576c-2.73916,0-5.41514,0.287192-8,0.8125v6.1875c-3.47484,0.838872-6.7198,2.18462-9.6875,4l-4.375-4.375c-2.24264,1.48612-4.29226,3.22977-6.1875,5.125s-3.63888,3.94486-5.125,6.1875l4.375,4.375c-1.81538,2.9677-3.16112,6.21265-4,9.6875h-6.1875c-0.5253,2.58486-0.8125,5.26083-0.8125,8s0.2872,5.41515,0.8125,8h6.1875c0.83888,3.47485,2.18462,6.7198,4,9.6875l-4.375,4.375c1.48612,2.24264,3.22976,4.29227,5.125,6.1875s3.94486,3.63888,6.1875,5.125l4.375-4.375c2.9677,1.81538,6.21266,3.16113,9.6875,4v6.1875c2.58486,0.525308,5.26082,0.8125,8,0.8125,2.73916,0,5.41514-0.287192,8-0.8125v-6.1875c3.47484-0.838872,6.7198-2.18462,9.6875-4l4.375,4.375c2.24264-1.48612,4.29226-3.22977,6.1875-5.125s3.63888-3.94486,5.125-6.1875l-4.375-4.375c1.81538-2.9677,3.16112-6.21266,4-9.6875h6.1875c0.5253-2.58485,0.8125-5.26083,0.8125-8s-0.2872-5.41515-0.8125-8h-6.1875c-0.83888-3.47485-2.18462-6.7198-4-9.6875l4.375-4.375c-1.48612-2.24264-3.22976-4.29227-5.125-6.1875s-3.94486-3.63888-6.1875-5.125l-4.375,4.375c-2.9677-1.81538-6.21266-3.16113-9.6875-4v-6.1875c-2.58486-0.525308-5.26084-0.8125-8-0.8125z" stroke-dashoffset="162" stroke="#666" stroke-linecap="butt" stroke-miterlimit="4" stroke-dasharray="none" stroke-width="7.68713093" fill="none"/>
</g>
</g>
</g>
</svg>
从我在规范中读到的内容,我会说应用的转换矩阵是
1.9522781 0 4.6434311
0 1.9522781 -1008.1558
0 0 1
和
0.65043772 0 -143.67477
0 0.65043772 980.4256
0 0 1
它们是否在翻译转换后应用于xyz坐标(-9.9178912,-891.57237,0)
?
我想上面的正确分析会让我得到所描述路径的左上角,或者可能是第一个手柄的坐标。在那之后,是否必须解析路径来决定边界框,从而决定路径的中心(因为它涉及一个有点圆形的对象)?
是不是尝试在自由创建的形状上手动制作动画,这是一个教训吗?
答案 0 :(得分:6)
我认为转换将从最里面向外应用,因此transform="translate(-9.9178912,-891.57237)"
将在最后完成。但是如果将动画放在最里面的区域,即在路径本身内,则可以忽略其他转换:
<g transform1>
<g transform2>
<g transform3>
<path d="coordinates">
<animateTransform your transformation here>
</path>
</g>
</g>
</g>
然后你只需要找到路径的中心,这在Inkscape中很容易做到,但在飞行中很棘手(相关问题在这里:programmatically How to get shape width in SVG document using java)。
就个人而言,我会在svg中使用一个脚本,这样你就可以使用getBBox来找到你的形状的边界框。如果您将以下元素添加到SVG中,您可以将id =“cog”的任何元素转向其中心:
<script type="text/ecmascript"><![CDATA[
var svgNS = "http://www.w3.org/2000/svg";
function init(evt)
{
if ( window.svgDocument == null )
{
svgDocument = evt.target.ownerDocument;
}
addRotateTransform('cog');
}
function addRotateTransform(target_id)
{
var element_to_rotate = svgDocument.getElementById(target_id);
var my_transform = svgDocument.createElementNS(svgNS, "animateTransform");
var bb = element_to_rotate.getBBox();
var cx = bb.x + bb.width/2;
var cy = bb.y + bb.height/2;
my_transform.setAttributeNS(null, "attributeName", "transform");
my_transform.setAttributeNS(null, "attributeType", "XML");
my_transform.setAttributeNS(null, "type", "rotate");
my_transform.setAttributeNS(null, "dur", "4s");
my_transform.setAttributeNS(null, "repeatCount", "indefinite");
my_transform.setAttributeNS(null, "from", "0 "+cx+" "+cy);
my_transform.setAttributeNS(null, "to", "360 "+cx+" "+cy);
element_to_rotate.appendChild(my_transform);
my_transform.beginElement();
}
]]></script>
您还需要将onload =“init(evt)”添加为SVG标记的属性。 e.g。
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 321.281 150.799"
xmlns:dc="http://purl.org/dc/elements/1.1/"
onload="init(evt)">
首次加载SVG时,这将调用init()函数。 init()函数调用addRotateTransform(),它找到具有给定id的元素。然后,它使用getBBox()找到该对象的中心,并在相关中心添加animateTransform方法。您可以更改dur属性,该属性决定完整旋转的速度。
它可能看起来像很多代码,但我认为这是确定路径中心的最简单方法。它还意味着可以通过将addRotateTransform('whatever-id');
添加到init()函数来轻松添加其他旋转元素。