簡體   English   中英

使用d3圍繞自己的中心旋轉svg路徑

[英]Rotate an svg path around its own centre using d3

我有一個用Inkscape制作的SVG路徑(開關圖標),我試圖以編程方式圍繞其自身的中心旋轉90度。 在我正確的網頁中,我有許多圖標都由ID引用,因此這是我可以應用的通用解決方案。

看起來這個問題是相同的,但是OP從來沒有跟進,他們從來沒有提供更多的代碼或小提琴。

我在這里有一個小提琴它顯示了我的示例的所有內容。

knob = d3.select("#switch1")
knob.attr('transform', 'rotate(0 0 0)')

是我用於輪換的基本代碼。 我需要知道如何計算x和y值,以便可以像示例中一樣使任何給定的圖標指向打開/關閉文本。 或使用d3獲得相同旋轉效果的另一種方法

如果我執行了knob.attr('transform', 'rotate(90 0 0)')該圖標就會從頁面上消失-我以為0 0會繞其相對中心旋轉?

如果我手動執行knob.attr('transform', 'rotate(90 15 15)') ,則可以將其保留在頁面上,但放置在錯誤的位置。

SVG路徑由以下組成:

       <path
       id="switch1"
       style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.12199998;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       d="m 35.741778,27.194664 -1.082299,0 0,-8.512001 1.082299,-9e-6 z m -5.563199,-4.274211 a 5.00005,5.000032 0 0 0 9.999999,2e-5 5.00005,5.000032 0 1 0 -9.999999,-2e-5 z"
       inkscape:connector-curvature="0" />

完整的SVG標記可以在小提琴上找到。

您可以使用getBBox()獲取<path>的位置:

const centre = knob.node().getBBox();

然后,只需計算其中心即可:

knob.attr("transform", "rotate(" + angle + ", " + 
    (centre.x + centre.width / 2) + ", " + (centre.y + centre.height / 2) + ")");

顯然,這里的angle是您想要的角度。

這是一個使用SVG(但更小)的演示,單擊SVG中的任意位置以旋轉路徑:

 let toggle = 0; let svg = d3.select("svg") const knob = d3.select("#switch1") const centre = knob.node().getBBox(); svg.on("click", function() { const angle = (toggle = 1 - toggle) ? 90 : 0; knob.attr("transform", "rotate(" + angle + ", " + (centre.x + centre.width / 2) + ", " + (centre.y + centre.height / 2) + ")"); }) 
 svg { border: 1px solid gray; background-color: lavender; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="200" height="100" viewBox="0 0 50 50" id="svg2" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="bar.svg"> <defs id="defs4" /> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="11.2" inkscape:cx="34.921875" inkscape:cy="1047.7595" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:window-width="1920" inkscape:window-height="1033" inkscape:window-x="-4" inkscape:window-y="-4" inkscape:window-maximized="1"> <inkscape:grid type="xygrid" id="grid4157" /> </sodipodi:namedview> <metadata id="metadata7"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title /> </cc:Work> </rdf:RDF> </metadata> <g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> <path id="switch1" style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.12199998;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="m 35.741778,27.194664 -1.082299,0 0,-8.512001 1.082299,-9e-6 zm -5.563199,-4.274211 a 5.00005,5.000032 0 0 0 9.999999,2e-5 5.00005,5.000032 0 1 0 -9.999999,-2e-5 z" inkscape:connector-curvature="0" /> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="25.714285" y="13.612206" id="text4135" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4137" x="25.714285" y="13.612206" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:start;writing-mode:lr-tb;text-anchor:start">OFF</tspan></text> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="44.566826" y="26.086744" id="text4135-2" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4137-2" x="44.566826" y="26.086744" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:start;writing-mode:lr-tb;text-anchor:start">ON</tspan></text> </g> </svg> 

您還可以添加過渡:

 let toggle = 0; let svg = d3.select("svg") const knob = d3.select("#switch1") const centre = knob.node().getBBox(); const centreX = centre.x + centre.width / 2; const centreY = centre.y + centre.height / 2; svg.on("click", function() { const angle = (toggle = 1 - toggle) ? 90 : 0; knob.transition() .ease(d3.easeLinear) .attrTween("transform", function() { return d3.interpolateString("rotate(" + (90 - angle) + ", " + centreX + ", " + centreY + ")", "rotate(" + angle + ", " + centreX + ", " + centreY + ")") }) }) 
 svg { border: 1px solid gray; background-color: lavender; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="200" height="100" viewBox="0 0 50 50" id="svg2" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="bar.svg"> <defs id="defs4" /> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="11.2" inkscape:cx="34.921875" inkscape:cy="1047.7595" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:window-width="1920" inkscape:window-height="1033" inkscape:window-x="-4" inkscape:window-y="-4" inkscape:window-maximized="1"> <inkscape:grid type="xygrid" id="grid4157" /> </sodipodi:namedview> <metadata id="metadata7"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> <dc:title /> </cc:Work> </rdf:RDF> </metadata> <g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> <path id="switch1" style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.12199998;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" d="m 35.741778,27.194664 -1.082299,0 0,-8.512001 1.082299,-9e-6 zm -5.563199,-4.274211 a 5.00005,5.000032 0 0 0 9.999999,2e-5 5.00005,5.000032 0 1 0 -9.999999,-2e-5 z" inkscape:connector-curvature="0" /> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="25.714285" y="13.612206" id="text4135" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4137" x="25.714285" y="13.612206" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:start;writing-mode:lr-tb;text-anchor:start">OFF</tspan></text> <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="44.566826" y="26.086744" id="text4135-2" sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4137-2" x="44.566826" y="26.086744" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:start;writing-mode:lr-tb;text-anchor:start">ON</tspan></text> </g> </svg> 

盡管Gerardo的答案顯示了顯而易見的且應用最廣泛的解決方案,但還有其他方法可以做到這一點。 這個答案有一些實驗性的嘗試(Gerardo報告說它在Safari上被破壞了),因為它提出了兩種並非現成的方法。 認為它是在探索可能性並增加知識庫,而不是呈現慣用方式。


您可以使用transform-origin CSS屬性來控制元素轉換的原點,而不必獲取邊界框並做一些公認的簡單數學。 因為Firefox似乎對此處理方式不同,所以您還應該設置transform-box:fill-box 然后,將旋轉原點設置為50% 50%按最初預期的那樣繞其中心旋轉元素。 旁注:圍繞中心旋轉是HTML的默認行為,而SVG默認情況下圍繞坐標原點旋轉。

這是Gerardo演示的簡化版本:

 let toggle = 0; const svg = d3.select("svg") const knob = d3.select("#switch1") svg.on("click", function() { const angle = (toggle = 1 - toggle) ? 90 : 0; knob.attr("transform", "rotate(" + angle + ")"); }) 
 path { fill: none; stroke: #000000; stroke-width: 1.12199998; transform-box: fill-box; transform-origin: 50% 50% } text { font-size: 10px; font-family: Sans; fill: #000000; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg width="200" height="100" viewBox="0 0 50 50"> <g> <path id="switch1" d="m 35,27 -1,0 0,-9 1,0 zm -5.7,-4 a 5,5 0 0 0 10,0 5,5 0 1 0 -10,0 z" /> <text x="26" y="14">OFF</text> <text x="45" y="26">ON</text> </g> </svg> 

您甚至可以使用hidden-checkbox-label技巧來推送信封,而根本不需要JavaScript!

 path { fill: none; stroke: #000000; stroke-width: 1.12199998; transform-box: fill-box; transform-origin: 50% 50% } text { font-size: 10px; font-family: Sans; fill: #000000; } #dummy { display: none; } #dummy:checked+label path { transform: rotate(90deg); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <input type="checkbox" id="dummy"> <label for="dummy"> <svg width="200" height="100" viewBox="0 0 50 50"> <g> <path id="switch1" d="m 35,27 -1,0 0,-9 1,0 zm -5.7,-4 a 5,5 0 0 0 10,0 5,5 0 1 0 -10,0 z" /> <text x="26" y="14">OFF</text> <text x="45" y="26">ON</text> </g> </svg> </label> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM