2016-09-30 121 views
0

請幫助我理解使用普通JavaScript操作svg元素及其變換的最佳做法。在旋轉後移動SVG元素

我理解座標系傳下來的節點和鏈接等等等等

我試圖做到的,是繼續旋轉後的元素原文翻譯。旋轉後未沿着軸線移動。

是否需要複製第一個轉換轉換並將其添加到轉換列表的末尾?

非常感謝,如果有人能夠以雄辯的方式闡明一些光。

回答

1

最好的方法是創建一個矩陣變換,然後請求各種變換並使用consolidate()方法。下面是一個例子

<!DOCTYPE HTML> 
 
<html> 
 
<head> 
 
    <title>Transform Request</title> 
 
</head> 
 

 
<body onload=showSVGSource()> 
 
<b><center>Transform Request Object + consolidate</b> 
 
<div id=svgDiv style=background:lime;width:400px;height:400px; > 
 
<svg id=mySVG width=400 height=400 > 
 
<circle id=myCircle cx=0 cy=0 r=150 fill=yellow transform="translate(200,200)" /> 
 
</svg> 
 
</div> 
 
<br> 
 
<button onClick=translateCircle()>translate</button> 
 
<button onClick=scaleCircle()>scale</button> 
 
<br> 
 
<textarea id=svgSourceValue style=width:500px;height:100px;></textarea> 
 
<center> 
 
<script> 
 
function translateCircle() 
 
{ 
 
    var objTransformRequestObj = mySVG.createSVGTransform() 
 
    //---attach new transform to element, init its transform list--- 
 
    var myTransListAnim=myCircle.transform 
 
    var objTransList=myTransListAnim.baseVal 
 

 
    objTransformRequestObj.setTranslate(40,0) 
 
    objTransList.appendItem(objTransformRequestObj) 
 
    objTransList.consolidate() 
 
    showSVGSource() 
 

 
} 
 
function scaleCircle() 
 
{ 
 
    var objTransformRequestObj = mySVG.createSVGTransform() 
 
    //---attach new transform to element, init its transform list--- 
 
    var myTransListAnim=myCircle.transform 
 
    var objTransList=myTransListAnim.baseVal 
 

 
    objTransformRequestObj.setScale(.5,.3) 
 
    objTransList.appendItem(objTransformRequestObj) 
 
    objTransList.consolidate() 
 
    showSVGSource() 
 
} 
 
function showSVGSource() 
 
{ 
 
    svgSourceValue.value=svgDiv.innerHTML 
 
} 
 
</script> 
 
</body> 
 

 
</html>

3

你實現這一目標是通過嵌套的變換方式。例如,看看下面的示例SVG。

<svg width="600" height="200"> 
 
    <g> 
 
    <rect x="0" y="50" width="100" height="100" fill="blue"/> 
 
    </g> 
 
</svg>

你可以申請一個轉換到<g>和另一對<rect>。他們將是獨立的,但將整體效果相結合。

因此,例如,如果我想將所有內容都移動到正確的位置,我可以對該組應用翻譯轉換。

<svg width="600" height="200"> 
 
    <g transform="translate(200,0)"> 
 
    <rect x="0" y="50" width="100" height="100" fill="blue"/> 
 
    </g> 
 
</svg>

然後,如果我想旋轉到位矩形,我可以通過應用旋轉變換,就是這樣做的。

<svg width="600" height="200"> 
 
    <g transform="translate(200,0)"> 
 
    <rect x="0" y="50" width="100" height="100" fill="blue" 
 
      transform="rotate(45,50,100)"/> 
 
    </g> 
 
</svg>

然後,如果我願意,我可以移動矩形更進一步權利,更新組的變換。

<svg width="600" height="200"> 
 
    <g transform="translate(400,0)"> 
 
    <rect x="0" y="50" width="100" height="100" fill="blue" 
 
      transform="rotate(45,50,100)"/> 
 
    </g> 
 
</svg>

去想這個問題的方法是,<rect>是在自己的小世界(「座標空間」是爲官一任:)是一無所知什麼是回事它的父元素。

所以如果我們使用我們上面學到的東西,我們可以很容易地創建你之後的那種動畫。以下動畫由三個階段組成。首先我們將矩形向右移動,然後旋轉它,然後再繼續。中間的旋轉不會影響我們再次向右移動的第三階段。

var outer = document.getElementById("outer"); 
 
var inner = document.getElementById("inner"); 
 

 
var tx = 0;  // the animated X position 
 
var angle = 0; // the animated angle 
 

 
/* 
 
* The first phase of the animation. 
 
* Function to step to the right until we hit tx=200. 
 
*/ 
 
var stepRightTo200 = function() { 
 
    setTimeout(function() { 
 
    tx += 4; 
 
    outer.setAttribute('transform', 'translate('+tx+',0)'); 
 
    if (tx < 200) // schedule another step in this phase 
 
     stepRightTo200(); 
 
    else   // start next phase of animation 
 
     rotateTo45(); 
 
    }, 32); 
 
}; 
 

 
/* 
 
* The second phase of the animation. 
 
* Step the angle around until we hit 45 degrees. 
 
*/ 
 
var rotateTo45 = function() { 
 
    setTimeout(function() { 
 
    angle += 1; 
 
    inner.setAttribute('transform', 'rotate('+angle+',50,100)'); 
 
    if (angle < 45) 
 
     rotateTo45() 
 
    else 
 
     stepRightTo400(); // start third phase of animation 
 
    }, 32); 
 
}; 
 

 
/* 
 
* The third phase of the animation. 
 
* Step to the right until we hit tx=400. 
 
*/ 
 
var stepRightTo400 = function() { 
 
    setTimeout(function() { 
 
    tx += 4; 
 
    outer.setAttribute('transform', 'translate('+tx+',0)'); 
 
    if (tx < 400) 
 
     stepRightTo400(); 
 
    }, 32); 
 
}; 
 

 
// Kick off first phase of animation 
 
stepRightTo200();
<svg width="600" height="200"> 
 
    <g id="outer"> 
 
    <rect id="inner" x="0" y="50" width="100" height="100" fill="blue"/> 
 
    </g> 
 
</svg>

在上面的例子中,我已經分居了「外」轉變出到父組,但我們真的沒有這樣做。我們可以將變換操作嵌套到單個變換中。

因此,我們可以簡化上述第三SVG例如:

<svg width="600" height="200"> 
 
    <rect x="0" y="50" width="100" height="100" fill="blue" 
 
     transform="translate(400,0) rotate(45,50,100)"/> 
 
</svg>

「外」變換成爲在變換列表中的第一個。如果您需要創建一個多部分轉換,這是一個很好的方法。首先創建(或想象)一個嵌套的組結構,並將變換應用於從「外部」(左)到「內部」(右)的變換。

因此,最後,我們可以使用這個非嵌套窗體重寫我們的動畫腳本。

var inner = document.getElementById("inner"); 
 

 
var tx = 0;  // the animated X position 
 
var angle = 0; // the animated angle 
 

 
/* 
 
* The first phase of the animation. 
 
* Function to step to the right until we hit tx=200. 
 
*/ 
 
var stepRightTo200 = function() { 
 
    setTimeout(function() { 
 
    tx += 4; 
 
    inner.setAttribute('transform', 
 
         'translate('+tx+',0) rotate('+angle+',50,100)'); 
 
    if (tx < 200) // schedule another step in this phase 
 
     stepRightTo200(); 
 
    else   // start next phase of animation 
 
     rotateTo45(); 
 
    }, 32); 
 
}; 
 

 
/* 
 
* The second phase of the animation. 
 
* Step the angle around until we hit 45 degrees. 
 
*/ 
 
var rotateTo45 = function() { 
 
    setTimeout(function() { 
 
    angle += 1; 
 
    inner.setAttribute('transform', 
 
         'translate('+tx+',0) rotate('+angle+',50,100)'); 
 
    if (angle < 45) 
 
     rotateTo45() 
 
    else 
 
     stepRightTo400(); // start third phase of animation 
 
    }, 32); 
 
}; 
 

 
/* 
 
* The third phase of the animation. 
 
* Step to the right until we hit tx=400. 
 
*/ 
 
var stepRightTo400 = function() { 
 
    setTimeout(function() { 
 
    tx += 4; 
 
    inner.setAttribute('transform', 
 
         'translate('+tx+',0) rotate('+angle+',50,100)'); 
 
    if (tx < 400) 
 
     stepRightTo400(); 
 
    }, 32); 
 
}; 
 

 
// Kick off first phase of animation 
 
stepRightTo200();
<svg width="600" height="200"> 
 
    <rect id="inner" x="0" y="50" width="100" height="100" fill="blue"/> 
 
</svg>

希望這有助於你瞭解如何轉換工作。

+0

神奇而且非常翔實。感謝幫助,它確實有幫助。 – daniel