3

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

(-9.9178912,-891.57237,0)それらは平行移動変換後にxyz 座標に適用されますか?

上記の正しい分析により、記述されたパスの左上のポイント、または最初のハンドルの座標が得られると思います。その後、パスを解析して境界ボックスを決定し、それによってパスの中心 (やや円形のオブジェクトに関係するため) を決定する必要がありますか?

自由に作成された形状に対して手動でアニメーションを作成しようとしないことのすべての教訓ですか?

4

1 に答える 1

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 で簡単に実行できますが、オンザフライで実行するのは難しいです (関連する質問はこちら: Java を使用して SVG ドキュメントで形状幅をプログラムで取得する方法)。

個人的には、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 タグに追加する必要もあります。例えば

<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 メソッドを追加します。1 回転の速度を決定する dur 属性を変更できます。

たくさんのコードに見えるかもしれませんが、パスの中心を決定する最も簡単な方法だと思います。addRotateTransform('whatever-id');また、init() 関数に追加することで、他の回転要素を簡単に追加できることも意味します。

于 2011-06-17T12:40:07.213 に答える