SVG半弧顺时针动画超180度(半个圆)纯CSS/JS
SVG semi-arc clockwise animation over 180 degrees (half of a circle) with pure CSS/JS
我的代码需要一些帮助。我的目标是制作一个 180 度渐进式动画,该动画在圆的上半部分顺时针旋转。我的最终目标是同时播放两个动画:上半部分顺时针,下半部分逆时针,两者的方式完全相同。
到目前为止我有这个:
// Circle functions
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
const angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
function describeArc(x, y, radius, startAngle, endAngle){
const start = polarToCartesian(x, y, radius, endAngle);
const end = polarToCartesian(x, y, radius, startAngle);
const arcSweep = endAngle - startAngle <= 180 ? "0" : "1";
const d = [
"M", start.x, start.y,
"A", radius, radius, 0, arcSweep, 0, end.x, end.y,
"L", x,y,
"L", start.x, start.y
].join(" ");
return d;
}
.arc {
animation: moveForward 5s linear forwards;
}
@keyframes moveForward {
to {
d: path("M 450 150 A 300 300 0 0 0 450 150 L 150 150 L 450 150");
}
}
<svg viewBox="0 0 300 300" height="250" width="250" style="background-color: black;">
<path fill="white" stroke-width="0" d="M 450 150 A 300 300 0 0 0 -150 149.99999999999997 L 150 150 L 450 150" />
<path class="arc" fill="black" stroke-width="0" d="M 450 150 A 300 300 0 0 0 -145.44232590366238 97.90554669992092 L 150 150 L 450 150" />
</svg>
不介意外推半径,我想为这个动画吐出SVG区域内的动画。如您所见,它沿着路径前进但缺少某些东西,因为它在动画过程中开始缩小。我不是专家,但形状插值可能缺少某些东西。
我正在使用公式根据另一个有点相关的问题 this answer 生成终点。它基本上将我的弧角转换为笛卡尔坐标。
感谢任何意见,非常感谢。
一个可能的解决方案是为非常粗的笔画(圆半径的两倍)设置动画。
在这种情况下,圆的半径是 20,所以 stroke-width="40"
在下一个示例中,我正在为路径的 stroke-dasharray 设置动画:62.84,0(行程长度 = 62.84,间隙 = 0)到 0、62.4(行程长度 = 0,间隙 = 62.84 ) 其中 62.84 是路径的长度。
请阅读如何 How SVG Line Animation Works
path {
stroke-dasharray: 62.84,0;
animation: anim 5s linear infinite;
}
@keyframes anim {
to {
stroke-dasharray: 0, 62.84;
}
}
<svg viewBox="-50 -50 100 100" width="90vh">
<path stroke-width="40" fill="none" stroke="black" d="M20,0A20,20 0 0 0 -20,0"/>
</svg>
如您所见,我只使用了 css。您可能需要使用 JS 来计算路径的长度。您可以使用 getTotalLength() 方法来完成。
更新
OP 正在评论:
if I were to expand the radius so it covers the SVG area (the square container) entirely, without any padding, what's the factor between this enlarged radius and your solution? What should I take into account?
在这种情况下,可见圆(半径 + stroke-width/2)应至少为 70.71,但也可以大于此值。 70.71 表示中心和 svg 元素的一个角之间的距离。这是双边 = 50 的 right-angled 三角形的斜边。由于 viewBox="-50 -50 100 100" 边 = 100/2。
这意味着 stroke-width="70.71" 并且您需要像这样重写 d 属性:
d="M35.355,0A35.355,35.355 0 0 0 -35.355,0"
其中 35.355 = 70.71/2
还需要重新计算路径的长度(我使用的是 p.getTotalLength()
方法),在本例中为 111.09。我将此值用于 CSS 中的 stroke-dasharray。
console.log(p.getTotalLength())
svg{border:solid}
path {
stroke-dasharray: 111.09,0;
animation: anim 5s linear infinite;
}
@keyframes anim {
to {
stroke-dasharray: 0, 111.09;
}
}
<svg viewBox="-50 -50 100 100" width="90vh">
<path id="p" stroke-width="70.71" fill="none" stroke="black"
d="M35.355,0A35.355,35.355 0 0 0 -35.355,0"/>
</svg>
根据评论; Enxaneta 她的回答,没有计算 pathLength,而是设置 pathLength="1"
svg {
border: solid
}
path {
stroke-dasharray: 1, 0;
animation: anim 5s linear infinite;
}
@keyframes anim {
to {
stroke-dasharray: 0, 1.1;
}
}
<svg viewBox="-50 -50 100 100" height="180px">
<path pathLength="1"
stroke-width="70.71" fill="none" stroke="black"
d="M35.355,0A35.355,35.355 0 0 0 -35.355,0"/>
</svg>
我的代码需要一些帮助。我的目标是制作一个 180 度渐进式动画,该动画在圆的上半部分顺时针旋转。我的最终目标是同时播放两个动画:上半部分顺时针,下半部分逆时针,两者的方式完全相同。
到目前为止我有这个:
// Circle functions
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
const angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
function describeArc(x, y, radius, startAngle, endAngle){
const start = polarToCartesian(x, y, radius, endAngle);
const end = polarToCartesian(x, y, radius, startAngle);
const arcSweep = endAngle - startAngle <= 180 ? "0" : "1";
const d = [
"M", start.x, start.y,
"A", radius, radius, 0, arcSweep, 0, end.x, end.y,
"L", x,y,
"L", start.x, start.y
].join(" ");
return d;
}
.arc {
animation: moveForward 5s linear forwards;
}
@keyframes moveForward {
to {
d: path("M 450 150 A 300 300 0 0 0 450 150 L 150 150 L 450 150");
}
}
<svg viewBox="0 0 300 300" height="250" width="250" style="background-color: black;">
<path fill="white" stroke-width="0" d="M 450 150 A 300 300 0 0 0 -150 149.99999999999997 L 150 150 L 450 150" />
<path class="arc" fill="black" stroke-width="0" d="M 450 150 A 300 300 0 0 0 -145.44232590366238 97.90554669992092 L 150 150 L 450 150" />
</svg>
不介意外推半径,我想为这个动画吐出SVG区域内的动画。如您所见,它沿着路径前进但缺少某些东西,因为它在动画过程中开始缩小。我不是专家,但形状插值可能缺少某些东西。
我正在使用公式根据另一个有点相关的问题 this answer 生成终点。它基本上将我的弧角转换为笛卡尔坐标。
感谢任何意见,非常感谢。
一个可能的解决方案是为非常粗的笔画(圆半径的两倍)设置动画。
在这种情况下,圆的半径是 20,所以 stroke-width="40"
在下一个示例中,我正在为路径的 stroke-dasharray 设置动画:62.84,0(行程长度 = 62.84,间隙 = 0)到 0、62.4(行程长度 = 0,间隙 = 62.84 ) 其中 62.84 是路径的长度。
请阅读如何 How SVG Line Animation Works
path {
stroke-dasharray: 62.84,0;
animation: anim 5s linear infinite;
}
@keyframes anim {
to {
stroke-dasharray: 0, 62.84;
}
}
<svg viewBox="-50 -50 100 100" width="90vh">
<path stroke-width="40" fill="none" stroke="black" d="M20,0A20,20 0 0 0 -20,0"/>
</svg>
如您所见,我只使用了 css。您可能需要使用 JS 来计算路径的长度。您可以使用 getTotalLength() 方法来完成。
更新
OP 正在评论:
if I were to expand the radius so it covers the SVG area (the square container) entirely, without any padding, what's the factor between this enlarged radius and your solution? What should I take into account?
在这种情况下,可见圆(半径 + stroke-width/2)应至少为 70.71,但也可以大于此值。 70.71 表示中心和 svg 元素的一个角之间的距离。这是双边 = 50 的 right-angled 三角形的斜边。由于 viewBox="-50 -50 100 100" 边 = 100/2。
这意味着 stroke-width="70.71" 并且您需要像这样重写 d 属性:
d="M35.355,0A35.355,35.355 0 0 0 -35.355,0"
其中 35.355 = 70.71/2
还需要重新计算路径的长度(我使用的是 p.getTotalLength()
方法),在本例中为 111.09。我将此值用于 CSS 中的 stroke-dasharray。
console.log(p.getTotalLength())
svg{border:solid}
path {
stroke-dasharray: 111.09,0;
animation: anim 5s linear infinite;
}
@keyframes anim {
to {
stroke-dasharray: 0, 111.09;
}
}
<svg viewBox="-50 -50 100 100" width="90vh">
<path id="p" stroke-width="70.71" fill="none" stroke="black"
d="M35.355,0A35.355,35.355 0 0 0 -35.355,0"/>
</svg>
根据评论; Enxaneta 她的回答,没有计算 pathLength,而是设置 pathLength="1"
svg {
border: solid
}
path {
stroke-dasharray: 1, 0;
animation: anim 5s linear infinite;
}
@keyframes anim {
to {
stroke-dasharray: 0, 1.1;
}
}
<svg viewBox="-50 -50 100 100" height="180px">
<path pathLength="1"
stroke-width="70.71" fill="none" stroke="black"
d="M35.355,0A35.355,35.355 0 0 0 -35.355,0"/>
</svg>