admin管理员组文章数量:1401947
I'm building a Gauge chart in a presentational ponent in React.
I just need to pass it a percentage and let the ponent do the rest. I can't use any animations because I'm taking a screenshot of the ponent 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="">
<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>
I'm building a Gauge chart in a presentational ponent in React.
I just need to pass it a percentage and let the ponent do the rest. I can't use any animations because I'm taking a screenshot of the ponent 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/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>
Share
Improve this question
edited Jun 22, 2021 at 0:47
Ezra Free
asked Jun 18, 2021 at 21:15
Ezra FreeEzra Free
75412 silver badges21 bronze badges
2
- 2 I'm on my phone, so just quick hint. If you put the small circle in <g> node and set the translate right, you can then wrap it in another which sets the rotation correctly. Still, you need some script to alter the rotation depending on the percentage. – Tomáš Zato Commented Jun 18, 2021 at 23:43
- 2 A better way to do this would be to use a path with an arc mand and a marker. Markers auto-orient by default, so if the marker is not a symmetric shape, you don't have to calculate your own rotation transform. – Michael Mullany Commented Jun 19, 2021 at 14:57
2 Answers
Reset to default 4You can do it all in SVG by setting pathLength
and using animationMotion
to position the circle.
Some JavaScript and a W3C standard Web Component (JSWC supported in all modern Browsers) help in putting multiple gauges on screen and making them dynamic.
customElements.define("svg-gauge", class extends HTMLElement {
connectedCallback() {
let speed = 0.5; // set to 0.0001 for instant display!
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"/>
<circle stroke="${col}" cx="0" cy="0" fill="#fff" r="4" stroke-width="3">
<animateMotion dur="${speed}s" path="${arc}" keyPoints="0;0.75" fill="freeze" keyTimes="0;1" calcMode="linear"/>
</circle>
<text x="50%" y="40%" text-anchor="middle">XXX</text>
</svg>`;
this.style.display='inline-block';
this.percent = this.getAttribute("value") || "50";
}
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;
}
})
drag sliders
<svg-gauge value="35" color="red" ></svg-gauge>
<svg-gauge value="50" color="orange"></svg-gauge>
<svg-gauge value="75" color="green" ></svg-gauge>
I went ahead and accepted Danny '365CSI' Engelman's answer above, but just in case anyone wants to do this without the animations here is how I ended up implementing it:
<div style="width:400px">
<svg viewBox="0 -10 100 100" xmlns="http://www.w3/2000/svg">
<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="50 85"></path>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</circle>
</svg>
</div>
本文标签: javascriptHow to position an SVG circle along another circle39s pathStack Overflow
版权声明:本文标题:javascript - How to position an SVG circle along another circle's path - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744312009a2600075.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论