1

I'm trying to emulate a 3d rotation among the y-axis for some paths I have in an SVG. I've found the library SVG3D https://code.google.com/p/svg3d/ and I've given it a try.

The problem is that you can only control the ticking interval duration and the increment (in radians) of each "tick" (there's a setInterval timing function that calls the transform() function which executes the rotation).

There's a toggleRotation function, that works like a play-pause command, but it doesn't give you any control of the timing and rotation of the path.

I have the following example code for my path:

<g id="anim_container" 
    z:xOrigin="0"
    z:yOrigin="0"
    z:zRatio="1000"
    z:sortAlgo="none" 
    z:rotationTime="60"
    onload="init(this);">
    <path
    d="M 460.2203,600.93365 248.25964,263.59573 C 248.63437,272.77915 249.10289,281.86852 249.66521,290.86388 250.03994,298.54799 250.32105,306.70032 250.50856,315.32088 250.88328,323.75461 251.07069,331.251 251.07079,337.81007 L 251.07079,600.93365 203.28125,600.93365 203.28125,204.84271 265.68876,204.84271 479.89835,544.42955 C 479.33579,535.24653 478.77356,526.06345 478.21166,516.88029 477.83651,509.00916 477.4617,500.48202 477.0872,491.29883 476.71206,481.92845 476.52465,473.02649 476.52497,464.59291 L 476.52497,204.84271 524.87674,204.84271 524.87674,600.93365 460.2203,600.93365"
    id="path_n">
        <z:translation x="364.0790100097656" y="402.88818359375"/>
        <z:rotation incRotY="0.5"/>
        <z:translation x="-364.0790100097656" y="-402.88818359375"/>
    </path>
</g>

So, how could you control the spinning and speed of the objects? Is it possible to include an easing function to control the speed of each rotation?

4

1 回答 1

0

好吧,我找到了解决此问题的方法。它需要三个步骤

  1. 首先,它需要您更改 Svg3d 库代码。

    打开文件“svg3d_parsing.js”并在“init”函数中注释以下行

    function init(g) {
        .......
        //clockRotation = window.setInterval("transform()", rotationTime);
        .......
    }
    

    我在这里所做的是避免使用库中包含的“滴答”函数,因此我们将能够使用我们自己的调用 transform()(执行旋转的函数,可作为全局函数使用)滴答功能(并且仅在我们需要时)。然后,在同一文件中找到“getAttrValue”函数并注释此处显示的行:

    function getAttrValue(......
    .....
    if (incAttValue) {
       var incValue = parseFloat(incAttValue);
       //node.setAttribute(tag, returnedValue + incValue);
    }
    return returnedValue;
    

    这是控制旋转的核心。当您执行 init(this) 并在每次调用 transform() 时,属性 rotX 和/或 rotY(取决于您是否设置了 incRotX、incRotY 或两者)被包含到<z:rotation incRotY="0.5"/>标签中,从而导致 <z:rotation incRotY="0.5" rotY="0.5"/>(对于本示例)。然后函数 transform() 读取这些值,并使用它们作为每个轴的旋转角度(以弧度为单位)计算变换矩阵。

    同样,在每次调用 transform() 时,rotX 和/或 rotY 都会分别增加 incRotX 和/或 incRotY。因此,通过注释这一行(并遵循后续步骤),我们将能够根据需要控制旋转角度。

  2. 其次,<z:rotation>通过包含一个 ID 来编辑标签(我使用 svg3d 库文件“dom_utils.js”中的一个函数,但出于此解决方案的目的,我们将设置一个 ID 以便于访问)---(您甚至可以删除 incRotY 属性)所以,我们得到

    <z:rotation id="rot" incRotY="0.5"/>
    
  3. 最后,获得一个补间和滴答功能,将 rotY(和/或 rotX,具体取决于您的情况)设置为 z:rotation 标签。这将是函数变换将应用于路径的旋转角度。

    对于这个例子,我使用 createjs 套件中的 easeljs(用于滴答声)和 tweenjs(用于补间):http ://www.createjs.com/

    将以下代码附加到 svg 结束标记之前的文件中。

    <!--Attaching easeljs and tweenjs libraries-->
    <script
    xlink:href="http://code.createjs.com/easeljs-0.7.0.min.js"
    id="easeljs" />
    <script
    xlink:href="http://code.createjs.com/tweenjs-0.5.0.min.js"
    id="tweenjs" />
    <script id="rotate">
       var v = document.getElementById("rot");         //Get z:rotation tag element
       var numberSpins = 3.5;                          //Set number of spins
       //Setting object with variables to tween.
       //deg will be the current angle value, finalDeg the final value (both in degrees)
       degrees = {deg: 0, finalDeg: numberSpins*360};  
       createjs.Tween.get( degrees, { loop: false } )  //apply tweening of degrees object
       .wait(1800)
       .to( { deg: degrees.finalDeg }, 3000, createjs.Ease.quadInOut )  //Here we set the variable to tween within the object (deg), the final value (finalDeg), the duration and the easing function
       .call(function(){createjs.Ticker.removeEventListener('tick',update)}); //Once we finish spinning, remove listener
       //Then set the update function to be called for each tick
       var update = function(){
          var rad = degrees.deg*Math.PI/180;            //Transform the current angle to radians
          v.setAttribute("rotY",rad);                   //Setting the rotation attribute to be read by transform()
          transform();                                  //Apply rotation with the values we've set in z:rotation tag element
       }
       createjs.Ticker.setFPS( 60 );                   //Just create a ticker. See TweenJs Documentation
       createjs.Ticker.addEventListener( 'tick', update ); //For each tick execute the update function
    </script>
    

    现在我们可以控制旋转次数、动画持续时间并加入缓动功能。

可能必须有一个更整洁的解决方案。

我已经在http://pastebin.com/fjPV4Gb4中发布了整个解决方案

请记住:不要使用 toggleTransform 函数!

注释:您可以取消注释“init”函数(“svg3d_parsing.js”)中调用“transform()”函数的clockRotation计时函数,并删除“update”函数中对transform()的调用,结果相同功能。但是,对 transform() 的调用将导致无限。

于 2013-11-30T11:46:14.240 回答