【问题标题】:How to position an SVG circle along another circle's path如何沿另一个圆的路径定位 SVG 圆
【发布时间】:2021-06-18 21:15:02
【问题描述】:

我正在 React 的演示组件中构建仪表图。

我只需要传递一个百分比,然后让组件完成剩下的工作。我无法使用任何动画,因为我正在截取组件的屏幕截图以将图像放置在 Powerpoint 演示文稿中。

这是我正在尝试做的截图:

正如您在我的代码 sn-p 中看到的,圆圈 <marker> 位于灰色 <path> 的末端,而不是绿色 <path> 的末端。如上图所示,如何定位圆圈使其位于绿色 <path>stroke-linecap

这是我目前的 HTML 代码:

<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>

【问题讨论】:

  • 我正在使用手机,所以请快速提示。如果将小圆圈放在 节点中并设置正确的平移,则可以将其包裹在另一个正确设置旋转的圆圈中。不过,您需要一些脚本来根据百分比改变旋转。
  • 更好的方法是使用带有弧形命令和标记的路径。标记默认自动定向,因此如果标记不是对称形状,您不必计算自己的旋转变换。

标签: javascript html svg


【解决方案1】:

您可以在 SVG 中通过设置 pathLength 并使用 animationMotion 定位圆来完成所有操作。

一些 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>
<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>

【讨论】:

    【解决方案2】:

    我继续接受了 Danny '365CSI' Engelman 的上述回答,但以防万一有人想在没有动画的情况下执行此操作,这就是我最终实现它的方式:

    <div style="width:400px">
      <svg viewBox="0 -10 100 100" xmlns="http://www.w3.org/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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 2012-12-24
      • 2021-12-27
      • 2013-11-23
      • 2020-09-16
      • 2017-12-13
      • 2016-07-18
      相关资源
      最近更新 更多