如何沿另一个圆的路径定位 SVG 圆 [英] How to position an SVG circle along another circle's path
问题描述
我正在 React 的展示组件中构建仪表图.
我只需要传递一个百分比,然后让组件完成剩下的工作.我无法使用任何动画,因为我正在截取组件的屏幕截图以将图像放入 Powerpoint 演示文稿中.
这是我正在尝试执行的操作的屏幕截图:
正如您在我的代码片段中看到的,圆圈
被定位在灰色
的末尾而不是末尾绿色
.我如何定位圆圈,使其位于绿色
的 stroke-linecap
处,如上图所示?
这是我目前的 HTML 代码:
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><定义><标记id="点"viewBox="0 0 10 10"refX="4"refY="4"标记宽度=4"标记高度=4"><圆CX=4"cy="4"r="2"填充=#FFFFFF"中风="#008000"笔画宽度=2"/></标记></defs><path d="M20,60a35,35 0 1,1 60,0"stroke="#D3D7DB"stroke-width="4" fill="none"stroke-linecap="round"></path><path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="75 35" marker-end="url(#dot)"></path></svg>
您可以通过设置 pathLength
并使用 animationMotion
定位圆来在 SVG 中完成所有操作.
一些 JavaScript 和 W3C 标准 Web 组件(所有现代浏览器都支持)有助于在屏幕上放置多个仪表并使它们动态化.
<svg-gauge value="35" color="red"></svg-gauge><svg-gauge value="50" color="orange"></svg-gauge><svg-gauge value="75" color="green"></svg-gauge><脚本>customElements.define("svg-gauge", class extends HTMLElement {连接回调(){让弧 = "M20,60a35,35 0 1,1 60,0";let col = this.getAttribute("color")||"green";this.innerHTML =`<input type="range" min="0" max="100" step="5" value="0"`+//删除2行` oninput="this.parentNode.percent=this.value"/><br>`+//仅用于演示`<svg viewbox="0 0 100 100"><path d="${arc}" stroke="grey" stroke-width="6" fill="none"stroke-linecap="round"></path><path id="P" d="${arc}" stroke="${col}" stroke-width="8" pathLength="100"fill="none" stroke-linecap="round" stroke-dasharray="75 35"></path><circle cx="0" cy="0" fill="#fff" r="4" stroke="${col}" stroke-width="3"><animateMotion dur="0.5s" keyPoints="0;0.75"fill="freeze" keyTimes="0;1" calcMode="linear" path="${arc}"></animateMotion></circle><text x="50%" y="40%" text-anchor="middle">XXX</text></svg>`;this.style.display='inline-block';this.percent = this.getAttribute("value");}设置百分比(val = 0){this.setAttribute("value", val);让破折号 = val + " " + (105 - val);this.querySelector("#P").setAttribute('stroke-dasharray', dash);this.querySelector("animateMotion").setAttribute('keyPoints', '0;'+val/100);this.querySelector("text").innerHTML =`${val} %`;this.querySelector("animateMotion").beginElement();this.querySelector("input").value = val;}})</script>
I'm building a Gauge chart in a presentational component in React.
I just need to pass it a percentage and let the component do the rest. I can't use any animations because I'm taking a screenshot of the component to place the image in a Powerpoint presentation.
Here's a screenshot of what I'm trying to do:
As you can see in my code snippet, the circle <marker>
is being positioned at the end of the grey <path>
instead of at the end of the green <path>
. How could I position the circle so it sits at the stroke-linecap
of the green <path>
as in the image above?
Here's the HTML code I have so far:
<div style="width:400px">
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker
id="dot"
viewBox="0 0 10 10"
refX="4"
refY="4"
markerWidth="4"
markerHeight="4"
>
<circle
cx="4"
cy="4"
r="2"
fill="#FFFFFF"
stroke="#008000"
stroke-width="2"
/>
</marker>
</defs>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="75 35" marker-end="url(#dot)"></path>
</svg>
</div>
You can do it all in SVG by setting pathLength
and using animationMotion
to position the circle.
Some JavaScript and a W3C standard Web Component (supported in all modern Browsers) help in putting multiple gauges on screen and making them dynamic.
<svg-gauge value="35" color="red"></svg-gauge>
<svg-gauge value="50" color="orange"></svg-gauge>
<svg-gauge value="75" color="green"></svg-gauge>
<script>
customElements.define("svg-gauge", class extends HTMLElement {
connectedCallback() {
let arc = "M20,60a35,35 0 1,1 60,0";
let col = this.getAttribute("color")||"green";
this.innerHTML =
`<input type="range" min="0" max="100" step="5" value="0"`+ // delete 2 lines
` oninput="this.parentNode.percent=this.value" /><br>`+ // just for demo
`<svg viewbox="0 0 100 100">
<path d="${arc}" stroke="grey" stroke-width="6" fill="none"
stroke-linecap="round"></path>
<path id="P" d="${arc}" stroke="${col}" stroke-width="8" pathLength="100"
fill="none" stroke-linecap="round" stroke-dasharray="75 35"></path>
<circle cx="0" cy="0" fill="#fff" r="4" stroke="${col}" stroke-width="3">
<animateMotion dur="0.5s" keyPoints="0;0.75"
fill="freeze" keyTimes="0;1" calcMode="linear" path="${arc}">
</animateMotion></circle>
<text x="50%" y="40%" text-anchor="middle">XXX</text>
</svg>`;
this.style.display='inline-block';
this.percent = this.getAttribute("value");
}
set percent(val = 0) {
this.setAttribute("value", val);
let dash = val + " " + (105 - val);
this.querySelector("#P").setAttribute('stroke-dasharray', dash);
this.querySelector("animateMotion").setAttribute('keyPoints', '0;'+val/100);
this.querySelector("text").innerHTML =`${val} %`;
this.querySelector("animateMotion").beginElement();
this.querySelector("input").value = val;
}
})
</script>
这篇关于如何沿另一个圆的路径定位 SVG 圆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!