【问题标题】:Fill Percentage area in a custom Oval SVG image自定义椭圆形 SVG 图像中的填充百分比区域
【发布时间】:2021-01-21 09:08:29
【问题描述】:

我想将自定义 SVG 填充到特定百分比。

这是我最初的 SVG

<svg width="202" height="195" viewBox="0 0 202 195" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.1" d="M96.8166 4.06964C16.0794 8.40606 -20.4645 94.8546 20.2957 157.019C54.6867 204.16 143.361 202.123 184.273 150.807C226.464 97.5789 163.505 0.38025 96.8166 4.06964Z" stroke="#313848" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

假设有x% 的进度,所以我想像这样填充这个SVG

<svg width="207" height="203" viewBox="0 0 207 203" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.1" d="M99.8166 12.0696C19.0794 16.4061 -17.4645 102.855 23.2957 165.019C57.6867 212.16 146.361 210.123 187.273 158.807C229.464 105.579 166.505 8.38025 99.8166 12.0696Z" stroke="#313848" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M99.8142 12.0736C166.502 8.38527 229.463 105.585 187.273 158.812" stroke="#EA7052" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M96.1683 2.4287C88.1789 2.85671 84.5529 11.2658 88.579 17.3074C91.9765 21.8887 100.751 21.6836 104.805 16.6905C108.986 11.5113 102.768 2.06471 96.1683 2.4287Z" fill="#EDEDEE" stroke="#EA7052" stroke-width="4.76054" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M171.545 162.236C169.583 169.548 177.007 175.33 184.329 173.522C189.985 171.84 192.408 163.889 188.57 158.747C184.582 153.434 173.156 156.193 171.545 162.236Z" fill="#EDEDEE" stroke="#EA7052" stroke-width="4.76054" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

我无法弄清楚如何实现这一点。 我希望它是动态的,这样我就可以达到任何百分比。

另外,我需要以圆周运动从起点到终点对其进行动画处理。

任何帮助都会非常感激。

【问题讨论】:

  • 到目前为止你做了什么尝试?
  • 我对 SVG 和动画完全陌生。我尝试使用path 标签的d 属性,但找不到任何解决方案
  • 您可以使用 getTotalLength() 方法计算路径的长度。这代表 100%。接下来,您可以获得代表 x% 的长度。现在您可以使用 stroke-dasharray 来表示部分路径。您可以使用 getPointAtLength() 方法计算最后一个点的位置

标签: javascript html css svg css-animations


【解决方案1】:

正如我所评论的:

您可以使用getTotalLength() 方法计算路径的长度。这代表 100%。

接下来可以得到代表x%的长度(代码中的xperc)。

现在您可以使用stroke-dasharray 来表示部分路径。

您可以使用getPointAtLength()方法计算最后一个点的位置。

请阅读我代码中的 cmets。

//the desired percentege
let xperc = .35;
//the total length of the path
let tl = base.getTotalLength();
//the partial length at the given percentage xperc
let partial = tl * xperc;

//set the stroke-dasharray of the second use element
perc.setAttribute("stroke-dasharray", `${partial} ${tl -partial}`)

//calculate the position of the point marking the end position
let theEnd = base.getPointAtLength(partial);
// set the cx and the cy attributes for the end point
end.setAttribute("cx", theEnd.x);
end.setAttribute("cy", theEnd.y);
circle {
  stroke: red;
  fill:white;
  stroke-width: 6.87634;
}
<svg width="207" height="203" viewBox="0 0 207 203" fill="none" xmlns="http://www.w3.org/2000/svg">
  <defs>
<path id="base" d="M99.8166,12.0696L99.8166,12.0696C166.505,8.38025 229.464,105.579 187.273,158.807C146.361,210.123 57.6867,212.16 23.2957,165.019C-17.4645,102.855 19.0794,16.4061 99.8166,12.0696Z" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
  </defs>
<use xlink:href="#base" stroke="silver" />
<use xlink:href="#base" stroke="red" id="perc" />
  
<circle cx="99.8166" cy="12.0696" r="10" />
<circle id="end" r="10" />
</svg>

观察:由于你的路径是逆时针方向的,我不得不反转路径以获得所需的结果

这是我使用输入类型范围来更改百分比值的示例:

let xperc = itr.value;
onInput();


itr.addEventListener("input", onInput)

function onInput() {
  xperc = itr.value;
  
  let tl = base.getTotalLength();
  let partial = tl * xperc;

  perc.setAttribute("stroke-dasharray", `${partial} ${tl - partial}`);

  let theEnd = base.getPointAtLength(partial);

  end.setAttribute("cx", theEnd.x);
  end.setAttribute("cy", theEnd.y);
}
circle {
  stroke: red;
  fill:white;
  stroke-width: 6.87634;
}
<input id="itr" type="range" min="0" max="1" step=".001" value=".35" /><br>

<svg width="207" viewBox="-5 -5 220 220" fill="none" xmlns="http://www.w3.org/2000/svg">
  <defs>
<path id="base" d="M99.8166,12.0696L99.8166,12.0696C166.505,8.38025 229.464,105.579 187.273,158.807C146.361,210.123 57.6867,212.16 23.2957,165.019C-17.4645,102.855 19.0794,16.4061 99.8166,12.0696Z" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
  </defs>
<use xlink:href="#base" stroke="silver" />
<use xlink:href="#base" stroke="red" id="perc" />
  
<circle cx="99.8166" cy="12.0696" r="10" />
<circle id="end" r="10" />
</svg>

还有另一个演示,我使用 javascript 将其从 0 设置为 1:

//the animation begins at 0
let xperc = 0;
//get the total length of the path
let tl = base.getTotalLength();
//the request animation id
let rid = null;



function Animation() {
  rid = window.requestAnimationFrame(Animation);
  // while xperc < 1 increase it's value by 0.001. Else stop the animation
  if (xperc < 1) {
    xperc += 0.001;
  }else{window.cancelAnimationFrame(rid)}

  //the same as in the first example
  let partial = tl * xperc;
  perc.setAttribute("stroke-dasharray", `${partial} ${tl - partial}`);

  let theEnd = base.getPointAtLength(partial);

  end.setAttribute("cx", theEnd.x);
  end.setAttribute("cy", theEnd.y);
}

Animation();
circle {
  stroke: red;
  fill:white;
  stroke-width: 6.87634;
}
<svg width="207" viewBox="-5 -5 220 220" fill="none" xmlns="http://www.w3.org/2000/svg">
  <defs>
<path id="base" d="M99.8166,12.0696L99.8166,12.0696C166.505,8.38025 229.464,105.579 187.273,158.807C146.361,210.123 57.6867,212.16 23.2957,165.019C-17.4645,102.855 19.0794,16.4061 99.8166,12.0696Z" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
  </defs>
<use xlink:href="#base" stroke="silver" />
<use xlink:href="#base" stroke="red" id="perc" />
  
<circle cx="99.8166" cy="12.0696" r="10" />
<circle id="end" r="10" />
</svg>

【讨论】:

  • 不同方法的好答案!也许再增加一个百分比输出?
  • @Alexandr_TT - 随意回答问题。
猜你喜欢
  • 1970-01-01
  • 2019-01-14
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多