2014-03-06 43 views
1

我有一堆使用相同的svg路徑的對象,它基本上是一個箭頭。我想將對象放置在另一個圓圈的svg路徑上,這樣箭頭看起來就像在「向外輻射」。在svg路徑上定位<object>

我讀到說使用<object>對SVG爲您提供了更多的控制了幾篇文章,但我不能找到如何<object>的定位到另一個SVG <object>路(圈子)。

而不是僅僅手動旋轉每個<object>我想將它們定位在一條路徑上,以便在未來對它們進行動畫會更容易。我希望他們在翻滾時從中心位置移出一點,我想用這個路徑的動畫會更容易,而不是手動設置每個箭頭的動畫。

我可沿路徑動畫喜歡這裏 http://demo.hongkiat.com/scalable-vector-graphics-animation/ 並通過改變「以下路徑」的路徑,一個圓,但我不想動畫,公正的立場....

UPDATE:我唯一似乎能夠在網上找到一個元素到一個路徑上是animationTransform或沿路徑動畫的東西,但我只想定位元素沿着另一個元素(路徑),如下所示: svg circle 額外的箭頭伸出來是我計劃在未來的滾動動畫......但現在我只是很好奇如何定位箭頭。我也沒有太多,但它的一個開始,我終於工作。任何幫助感謝!

http://jsfiddle.net/74JRf/1/

我只是在想,會是更好的箭頭旋轉到與CSS3,SVG或一個圈?

+1

用''表示你的意思是''標籤嗎?或者,您是否將多個不同的HTML''標籤中的獨立SVG文件嵌入?將SVG文件分開放置在一個頁面上比在同一個SVG中放置多個圖形要複雜得多...一些示例代碼會很有用。 – AmeliaBR

+1

http://jsfiddle.net/74JRf/1/我更新了描述,並得到現在工作在小提琴,但我不能找到任何資源在網上定位沿路徑,只有動畫。 – mike

+1

使用Javascript可以很容易地在路徑上的一個點定位元素 - 您可以使用路徑的getPointAtLength方法,可能結合getTotalLength方法([請參閱此動畫問題中的示例](http:// stackoverflow.com/a/21228701/3128209))。但是,它不會自動旋轉元素以匹配像SVG動畫那樣的路徑的切線角度。並且沒有任何簡單的方法可以找出角度 - 您需要查詢多個點並使用三角函數計算切線。就你的例子而言,直接定位箭頭可能是最容易的。 – AmeliaBR

回答

1

這與以前的答案類似,除了它使用導入的路徑作爲箭頭,而不是多邊形。

首先,您導入的路徑是humongus因此它們對於我的400x400 svg來說太大了。因此,我不得不將它們縮小到我的svg的合理尺寸。我選擇80px作爲箭頭的高度。要做到這一點,我必須得到導入路徑的實際大小,我已經放入一個元素中。我使用getBBox()來做到這一點如下。

//--get actual size--- 
var bb=importedPaths.getBBox() 
var bbx=bb.x 
var bby=bb.y 
var bbw=bb.width 
var bbh=bb.height 
//---find the center point of this <g>--- 
var cx=bbx+.5*bbw 
var cy=bby+.5*bbh 

//---set desired size, i.e. scale the import-- 
var heightSize=80 
var scale=heightSize/bbh 
//---translate so it's bottom is centered is at (0,0) 
var transX=(-cx)*scale 
var transY=(-cy-.5*bbh)*scale 
importedPaths.setAttribute("transform","translate("+transX+" "+transY+")scale("+scale+" "+scale+")") 

現在我有了這個大小和位於以(0,0)爲中心的箭頭底部,所以我可以使用它來爲符號製作元素。

我將重新調整大小的導入副本製作爲黑色箭頭和灰色箭頭,並將它們放置在<defs>元素中。 <defs>用於存儲/隱藏用於符號的元素。

//---create your symbol objects from transformed import, by placing <g> in defs-- 
var blackArrow=importedPaths.cloneNode(true) 
blackArrow.id="myBlackArrow" 
myDefs.appendChild(blackArrow) 
var grayArrow=importedPaths.cloneNode(true) 
grayArrow.id="myGrayArrow" 
grayArrow.setAttribute("fill","silver") 
myDefs.appendChild(grayArrow) 

以下是一個html文件,您可以在其中看到此操作。我已經包含了一個textarea,顯示svg是如何創建的。 (我離開了左上角的原始箭頭)。注意:在IE和Chrome中運行正常,FF沒有完全呈現箭頭組。

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<body> 
<div style='padding:5px;background-color:gainsboro;'>OK in:IE11/CH32, but FF23 does not fully render arrow in in circle<br /></div> 
<br /> 
<br /> 
<br /> 
<center> 
<div id=svgDiv style='width:400px;height:400px;background-color:lightgreen'> 
<svg id="mySVG" width="400" y="400" overflow="visible" > 
<defs id="myDefs"> 
</defs> 
<g id="importedPaths" fill="black"><path d="M2553.826,1137.28l-2.772-1.719l29.799,1445.434l195.02,1.004l9.765-1448.729 c0,0-63.94,42.007-113.36,42.007S2553.826,1137.28,2553.826,1137.28z" /><path d="M2451.84,1058.265c0,0,171.983,75.005,216.505,75.005s188.535-75.005,188.535-75.005l-190.691-366.037 L2451.84,1058.265z" /></g> 
</svg> 
</div> 
<button onClick=placeArrowsAroundCircle()>Place Arrows Around Circle</button><br /> 
    <br />SVG Source:<br /> 
<textarea id=svgSourceValue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea> 
</center> 

<script id=myScript> 
var NS="http://www.w3.org/2000/svg" 
var xref="http://www.w3.org/1999/xlink" 
//--place this at the center of this svg--- 
var centerX=200 
var centerY=200 
//---every 30 degrees around a center point-- 
//---button--- 
function placeArrowsAroundCircle() 
{ 
    for(var k=0;k<12;k++) 
    { 
     var rotateAngle=k*30 
     var grayArrow=document.createElementNS(NS,"use") 
     grayArrow.setAttributeNS(xref,"href", "#myGrayArrow") 
     grayArrow.setAttribute("onmouseover", "hilite(evt)") 
     grayArrow.setAttribute("onmouseout", "unhilite(evt)") 
     grayArrow.setAttribute("rotateAngle", rotateAngle) 
     grayArrow.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
     mySVG.appendChild(grayArrow) 
    } 
    for(var k=0;k<12;k++) 
    { 
     var rotateAngle=k*30+15 //--offset 15 degrees--- 
     var blackArrow=document.createElementNS(NS,"use") 
     blackArrow.setAttributeNS(xref,"href", "#myBlackArrow") 
     blackArrow.setAttribute("onmouseover", "hilite(evt)") 
     blackArrow.setAttribute("onmouseout", "unhilite(evt)") 
     blackArrow.setAttribute("rotateAngle", rotateAngle) 
     blackArrow.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
     mySVG.appendChild(blackArrow) 
    } 
    svgSourceValue.value=svgDiv.innerHTML 
} 
//--onmouseover--- 
function hilite(evt) 
{ 
    //---IE and Chrome--- 
    if(evt.target.correspondingUseElement) 
     var target=evt.target.correspondingUseElement 
    else //---FF--- 
     var target=evt.target 

    var rotateAngle=target.getAttribute("rotateAngle") 
    target.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")scale(1,1.3)") 
} 
//---onmouseout-- 
function unhilite(evt) 
{ 
    //---IE and Chrome--- 
    if(evt.target.correspondingUseElement) 
     var target=evt.target.correspondingUseElement 
    else //---FF--- 
     var target=evt.target 

    var rotateAngle=target.getAttribute("rotateAngle") 
    target.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
} 

document.addEventListener("onload",init(),false) 
//---adjust(transform) the imported paths so they fit this svg viewPort--- 
function init() 
{ 
    //--get actual size--- 
    var bb=importedPaths.getBBox() 
    var bbx=bb.x 
    var bby=bb.y 
    var bbw=bb.width 
    var bbh=bb.height 
    //---find the center point of this <g>--- 
    var cx=bbx+.5*bbw 
    var cy=bby+.5*bbh 

    //---set desired size, i.e. scale the import-- 
    var heightSize=80 
    var scale=heightSize/bbh 
    //---translate so it's bottom is centered is at (0,0) 
    var transX=(-cx)*scale 
    var transY=(-cy-.5*bbh)*scale 
    importedPaths.setAttribute("transform","translate("+transX+" "+transY+")scale("+scale+" "+scale+")") 

    //---create your symbol objects from transformed import, by placing <g> in defs-- 
    var blackArrow=importedPaths.cloneNode(true) 
    blackArrow.id="myBlackArrow" 
    myDefs.appendChild(blackArrow) 
    var grayArrow=importedPaths.cloneNode(true) 
    grayArrow.id="myGrayArrow" 
    grayArrow.setAttribute("fill","silver") 
    myDefs.appendChild(grayArrow) 
    //---see textarea--- 
    svgSourceValue.value=svgDiv.innerHTML 
} 
</script> 
</body> 
</html> 
+0

這個作品真棒!我有幾個問題... 我可以找到資源來設置樣式svg,但沒有資源可以在CSS中使用{}。我可以在css中設置的風格,還是需要更多的JS?此外,我想動畫的過渡,也許與jQuery或css3 ...我可以申請一個css3過渡:所有的以某種方式在css3或將不起作用,因爲旋轉/大小的變化是內聯?另外我該如何刪除左上角的參考對象/組?再次感謝! – mike

+0

我認爲與svg最嚴肅的動態互動需要Javascript。刪除元素使用:mySVG.removeChild(importedPaths) –

+0

我明白了。謝謝弗朗西斯......我嘗試了幾種不同的方式來擺脫引用對象,但它總是刪除所有的箭頭,而不僅僅是參考路徑......上面給出的代碼做了同樣的事情,它刪除了所有的箭頭。 。不只是左上角的引用對象 – mike

1

您的應用程序演示了SVG的整潔動態方面。我希望我的回答不是太冗長:)

創建你的'箭頭',使它們的中心/底點在(0,0) - 當它們放置在一個圓周時,以及'hilite/extend 'onmouseover的功能。

我會建議使用多邊形而不是每個黑色和灰色箭頭的路徑。 然後將其放入<defs>以創建所需的使用元素。 例如

<defs> 
<polygon id="myBlackArrow" points="10,0 -10,0 -10,-80 -15,-80 0,-100 15,-80 10,-80" fill="black" /> 
<polygon id="myGrayArrow" points="10,0 -10,0 -10,-80 -15,-80 0,-100 15,-80 10,-80" fill="silver" /> 
</defs> 

然後,與位的Javascript可以構建箭頭圍繞中心點:

var NS="http://www.w3.org/2000/svg" 
var xref="http://www.w3.org/1999/xlink" 
var centerX=200 
var centerY=200 
//---every 40 degrees around a center point-- 
function placeArrowsAroundCircle() 
{ 
    for(var k=0;k<9;k++) 
    { 
     var rotateAngle=k*40 
     var grayArrow=document.createElementNS(NS,"use") 
     grayArrow.setAttributeNS(xref,"href", "#myGrayArrow") 
     grayArrow.setAttribute("onmouseover", "hilite(evt)") 
     grayArrow.setAttribute("onmouseout", "unhilite(evt)") 
     grayArrow.setAttribute("rotateAngle", rotateAngle) 
     grayArrow.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
     mySVG.appendChild(grayArrow) 
    } 

    for(var k=0;k<9;k++) 
    { 
     var rotateAngle=k*40+20 
     var blackArrow=document.createElementNS(NS,"use") 
     blackArrow.setAttributeNS(xref,"href", "#myBlackArrow") 
     blackArrow.setAttribute("onmouseover", "hilite(evt)") 
     blackArrow.setAttribute("onmouseout", "unhilite(evt)") 
     blackArrow.setAttribute("rotateAngle", rotateAngle) 

     blackArrow.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
     mySVG.appendChild(blackArrow) 
    } 
} 

附連到每個箭頭的兩個函數爲鼠標懸停/出將延伸/收縮所述目標箭頭(箭頭在y方向縮放到1.3)。

//--onmouseover--- 
function hilite(evt) 
{ 
    //---IE and Chrome--- 
    if(evt.target.correspondingUseElement) 
     var target=evt.target.correspondingUseElement 
    else //---FF--- 
     var target=evt.target 

    var rotateAngle=target.getAttribute("rotateAngle") 
    target.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")scale(1,1.3)") 
} 
//---onmouseout-- 
function unhilite(evt) 
{ 
    //---IE and Chrome--- 
    if(evt.target.correspondingUseElement) 
     var target=evt.target.correspondingUseElement 
    else //---FF--- 
     var target=evt.target 

    var rotateAngle=target.getAttribute("rotateAngle") 
    target.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
} 

下面是一個示例,您可以將它放在.htm文檔中以查看它的工作。這測試確定爲IE/CH/FF

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<body> 
<center> 
<div id="svgDiv" style='background-color:lightblue;width:400px;height:400px;'> 
<svg id="mySVG" width="400" height="400"> 
<defs> 
<polygon id="myBlackArrow" points="10,0 -10,0 -10,-80 -15,-80 0,-100 15,-80 10,-80" fill="black" /> 
<polygon id="myGrayArrow" points="10,0 -10,0 -10,-80 -15,-80 0,-100 15,-80 10,-80" fill="silver" /> 
</defs> 
</svg> 
</div> 
<button onClick=placeArrowsAroundCircle()>Place Arrows Around Circle</button> 
</center> 
<script id=myScript> 
var NS="http://www.w3.org/2000/svg" 
var xref="http://www.w3.org/1999/xlink" 
var centerX=200 
var centerY=200 
//---every 40 degrees around a center point-- 
//---button--- 
function placeArrowsAroundCircle() 
{ 
    for(var k=0;k<9;k++) 
    { 
     var rotateAngle=k*40 
     var grayArrow=document.createElementNS(NS,"use") 
     grayArrow.setAttributeNS(xref,"href", "#myGrayArrow") 
     grayArrow.setAttribute("onmouseover", "hilite(evt)") 
     grayArrow.setAttribute("onmouseout", "unhilite(evt)") 
     grayArrow.setAttribute("rotateAngle", rotateAngle) 
     grayArrow.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
     mySVG.appendChild(grayArrow) 
    } 

    for(var k=0;k<9;k++) 
    { 
     var rotateAngle=k*40+20 
     var blackArrow=document.createElementNS(NS,"use") 
     blackArrow.setAttributeNS(xref,"href", "#myBlackArrow") 
     blackArrow.setAttribute("onmouseover", "hilite(evt)") 
     blackArrow.setAttribute("onmouseout", "unhilite(evt)") 
     blackArrow.setAttribute("rotateAngle", rotateAngle) 

     blackArrow.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
     mySVG.appendChild(blackArrow) 
    } 
} 
//--onmouseover--- 
function hilite(evt) 
{ 
    //---IE and Chrome--- 
    if(evt.target.correspondingUseElement) 
     var target=evt.target.correspondingUseElement 
    else //---FF--- 
     var target=evt.target 

    var rotateAngle=target.getAttribute("rotateAngle") 
    target.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")scale(1,1.3)") 
} 
//---onmouseout-- 
function unhilite(evt) 
{ 
    //---IE and Chrome--- 
    if(evt.target.correspondingUseElement) 
     var target=evt.target.correspondingUseElement 
    else //---FF--- 
     var target=evt.target 

    var rotateAngle=target.getAttribute("rotateAngle") 
    target.setAttribute("transform","translate("+centerX+" "+centerY+")rotate("+rotateAngle+")") 
} 
</script> 
</body> 
</html> 
+0

我真的很感激你的時間這樣做,它很好!我的主要問題是你可以用路徑或路徑組來做這件事嗎?我實際上需要使用的主要svg圖像不是箭頭,而是類似於具有貝塞爾曲線和許多點的非常詳細的頂部的東西,不確定這是否可以用多邊形或路徑完成。另外,頂部與主體分離,因此當我在Illustrator中導出到svg時,組中實際上有兩條路徑。有沒有什麼辦法可以通過組來做到這一點?因此,在放置黑色和灰色多邊形的位置可能會出現黑灰色組,每組有兩條路徑 – mike

+0

,或者可能將此JS應用於要加載整個.svg文件的標記?不知道這會更容易,甚至可能 – mike

+1

是的,你可以使用一個元素爲您元素,你在你的提琴顯示。但是,它必須進行轉換,以便「適合」您計劃使用它的svg viewPort。讓我看看我能做些什麼來爲我的示例使用導入的路徑。我會發表另一個答案。 –