2011-04-12 2 views
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 좌표 번역 변형?

위의 올바른 분석을 통해 나와있는 경로의 왼쪽 위 또는 첫 번째 핸들의 좌표를 얻을 수 있다고 생각합니다. 그 후에, 경로 상자를 결정하기 위해 경로를 파싱해야하고, 따라서 경로의 중심 (다소 원형 오브젝트와 관련이 있기 때문에)을 결정해야합니까?

자유롭게 만들어진 모양의 애니메이션을 수동으로 시도하지 않는 것이 모두 교훈입니까?

+0

변환을 경로 값에 적용하도록 Inkscape를 설정하면 아마 조금 더 깨끗해 보일 것입니다. 'Inkscape Prefs> 변형> 변형 저장 : 최적화 '를 시도해보십시오. –

답변

6

변형이 가장 안쪽에서 바깥쪽으로 적용될 것이라고 생각하므로 transform="translate(-9.9178912,-891.57237)"이 마지막으로 수행됩니다. 당신이 즉, 경로 자체 내에서, 가장 안쪽 지역에 애니메이션을 넣어하지만 만약 당신이 다른 변환을 무시할 수 있습니다 :

<g transform1> 
    <g transform2> 
     <g transform3> 
     <path d="coordinates"> 
      <animateTransform your transformation here> 
     </path> 
     </g> 
    </g> 
    </g> 

그럼 당신은 그냥 잉크 스케이프에서 쉽게 할 경로의 중심을 찾아야, 그러나 on-the-fly (여기에서 관련된 질문 : programmatically How to get shape width in SVG document using java)를하는 것은 까다로운 일입니다.

저는 개인적으로 svg 내에서 스크립트를 사용하므로 getBBox를 사용하여 모양의 경계 상자를 찾을 수 있습니다. 당신은 또한에 속성으로 "초기화 (EVT)"온로드 =를 추가 할 필요가

<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> 

: 당신이 당신의 SVG에 다음 요소를 추가하는 경우에는 그 중심에 대한 ID = "톱니 바퀴"회전 어떤 요소를 만들 수 있습니다 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() 함수는 주어진 id를 가진 요소를 찾는 addRotateTransform()을 호출합니다. 그런 다음 getBBox()를 사용하여 해당 객체의 중심을 찾고 관련 센터가있는 animateTransform 메소드를 추가합니다. 전체 회전의 속도를 결정하는 dur 속성을 변경할 수 있습니다.

많은 코드처럼 보일 수도 있지만 경로의 중심을 결정하는 가장 쉬운 방법이라고 생각합니다. 또한 init() 함수에 addRotateTransform('whatever-id');을 추가하여 다른 회전 요소를 쉽게 추가 할 수 있음을 의미합니다.

+0

감사합니다. 문제가 해결되는 방식을 좋아합니다.경험이없는 SVG의 요소에 관한 것이지만, 배울 것이기 때문에 완벽합니다. 여가 시간 프로젝트이며 여가 시간은 희소합니다. 그래서 이것을 구현하지 않을 것입니다. 잠시. 이 접근법을 시도한 후에 질문/답변에 추가 할 것을 발견하면 여기로 돌아올 것입니다. –

+1

요소의 중심을 얻는 것이 지나치게 복잡한 방법처럼 보일 수도 있지만, 더 간단한 방법을 알지 못합니다. 약간의 시간이있을 때 EMCAScript를 실험 해 보는 것이 좋습니다. SVG 내에서 임의로 복잡한 애니메이션을 수행 할 수 있습니다. –

+2

일부 터닝 기어의 예를 만들었습니다. http://www.petercollingridge.co.uk/sites/files/peter/4gears.svg –