[英]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.