SVG绘制路径并用椭圆弧填充
SVG Draw Path and Fill with Elliptical Arc
我正在尝试在旋转半径后面逐渐填充一个椭圆,实际上是一个类似时钟的计时器,在扫动的手后面填充。我快要弄对了,但是填充区域的弧度会随着每次重新计算而移动。
CodePen 版本是 here 但总而言之,我使用以下 HTML 开始:
<svg version="1.1" baseProfile="full" width="50%" height="50%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3 3.2">
<path id="pie" stroke="none" stroke-width=".01" fill="rgb(204, 50, 50)"
d="M 1.5 1.7 V 1.5 .3
A 1.5 1.3 0 0 1 1.5 .2
z"/>
<line id="hand" stroke="black" stroke-width=".02"
x1="1.5" y1="1.7" x2="1.5" y2=".2"/>
</svg>
和下面的JavaScript旋转手和draw/fill在它后面:
var sweep = document.getElementById("hand"),
fill = document.getElementById("pie"),
degrees = 0;
const Torads = Math.PI/180;
function rotateHand() {
degrees += 45;
sweep.setAttribute("transform", "rotate(" + degrees + " 1.5 1.7)");
if (degrees <= 180) {
fill.setAttribute("d", "M 1.5 1.7 V .4 A 1.4 1.3 0 0 1 " + ellipticalXcoords(Math.cos((degrees-90) * Torads)) + " " + ellipticalYcoords(Math.sin((degrees-90) * Torads)) + " z");
} else {
fill.setAttribute("d", "M 1.5 1.7 V .4 A 1.4 1.3 0 1 1 " + ellipticalXcoords(Math.cos((degrees - 90) * Torads)) + " " + ellipticalYcoords(Math.sin((degrees - 90) * Torads)) + " z");
}
你在这里让自己过得很艰难。您可以使用与应用于常规圆的剪辑蒙版相同的形状,而不是尝试计算填充区域形状的增量变化,使用 stroke-dasharray
trick.[=14= 可以更轻松地制作动画。 ]
以下是我的做法。请注意,圆形填充旋转了 -90°,以便动画从圆的顶部而不是侧面开始。将相应的 +90° 旋转应用到剪辑蒙版以解决此问题。
var sweep = document.getElementById("hand"),
fill = document.getElementById("apple-fill"),
degrees = 0;
const Torads = Math.PI / 180;
var animating = false;
function rotateHand() {
degrees += 4;
if (degrees >= 360) {
clearInterval(animating);
animating = false;
degrees = 360;
}
sweep.setAttribute("transform", "rotate(" + degrees + " 1.5 1.7)");
fill.setAttribute("stroke-dasharray", degrees * 0.01309 + ", 20");
}
function startAnimation() {
if (!animating) {
degrees = 0;
animating = setInterval(rotateHand, 30);
}
}
<button onclick="startAnimation(); return 0">Animate</button>
<svg width="200" height="200" viewBox="0 0 3 3.2">
<defs>
<clipPath id="apple">
<path d="M1.5.5A.2.2 0 0 1 1.7.315A1.4 1.3 0 1 1 1.3.315A.2.2 0 0 1 1.5.5z" transform="rotate(90,1.5,1.7)" />
</clipPath>
</defs>
<circle cx="1.5" cy="1.7" r=".75" id="apple-fill" fill="none" stroke="rgb(204, 50, 50)" stroke-width="1.5" stroke-dasharray="0,20" transform="rotate(-90,1.5,1.7)" clip-path="url(#apple)" />
<path id="pomodoro" stroke-width=".01" fill="none" stroke="#000" d="M1.5.5A.2.2 0 0 1 1.7.315A1.4 1.3 0 1 1 1.3.315A.2.2 0 0 1 1.5.5" />
<path id="leaf" stroke-width=".01" stroke-linejoin="arc" fill="green" d="M1.5.6A.4.4 0 0 1 2 .1A.5.5 0 0 1 1.5.6" />
<line id="hand" stroke="black" stroke-width=".02" x1="1.5" y1="1.7" x2="1.5" y2=".2" />
</svg>
我正在尝试在旋转半径后面逐渐填充一个椭圆,实际上是一个类似时钟的计时器,在扫动的手后面填充。我快要弄对了,但是填充区域的弧度会随着每次重新计算而移动。
CodePen 版本是 here 但总而言之,我使用以下 HTML 开始:
<svg version="1.1" baseProfile="full" width="50%" height="50%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3 3.2">
<path id="pie" stroke="none" stroke-width=".01" fill="rgb(204, 50, 50)"
d="M 1.5 1.7 V 1.5 .3
A 1.5 1.3 0 0 1 1.5 .2
z"/>
<line id="hand" stroke="black" stroke-width=".02"
x1="1.5" y1="1.7" x2="1.5" y2=".2"/>
</svg>
和下面的JavaScript旋转手和draw/fill在它后面:
var sweep = document.getElementById("hand"),
fill = document.getElementById("pie"),
degrees = 0;
const Torads = Math.PI/180;
function rotateHand() {
degrees += 45;
sweep.setAttribute("transform", "rotate(" + degrees + " 1.5 1.7)");
if (degrees <= 180) {
fill.setAttribute("d", "M 1.5 1.7 V .4 A 1.4 1.3 0 0 1 " + ellipticalXcoords(Math.cos((degrees-90) * Torads)) + " " + ellipticalYcoords(Math.sin((degrees-90) * Torads)) + " z");
} else {
fill.setAttribute("d", "M 1.5 1.7 V .4 A 1.4 1.3 0 1 1 " + ellipticalXcoords(Math.cos((degrees - 90) * Torads)) + " " + ellipticalYcoords(Math.sin((degrees - 90) * Torads)) + " z");
}
你在这里让自己过得很艰难。您可以使用与应用于常规圆的剪辑蒙版相同的形状,而不是尝试计算填充区域形状的增量变化,使用 stroke-dasharray
trick.[=14= 可以更轻松地制作动画。 ]
以下是我的做法。请注意,圆形填充旋转了 -90°,以便动画从圆的顶部而不是侧面开始。将相应的 +90° 旋转应用到剪辑蒙版以解决此问题。
var sweep = document.getElementById("hand"),
fill = document.getElementById("apple-fill"),
degrees = 0;
const Torads = Math.PI / 180;
var animating = false;
function rotateHand() {
degrees += 4;
if (degrees >= 360) {
clearInterval(animating);
animating = false;
degrees = 360;
}
sweep.setAttribute("transform", "rotate(" + degrees + " 1.5 1.7)");
fill.setAttribute("stroke-dasharray", degrees * 0.01309 + ", 20");
}
function startAnimation() {
if (!animating) {
degrees = 0;
animating = setInterval(rotateHand, 30);
}
}
<button onclick="startAnimation(); return 0">Animate</button>
<svg width="200" height="200" viewBox="0 0 3 3.2">
<defs>
<clipPath id="apple">
<path d="M1.5.5A.2.2 0 0 1 1.7.315A1.4 1.3 0 1 1 1.3.315A.2.2 0 0 1 1.5.5z" transform="rotate(90,1.5,1.7)" />
</clipPath>
</defs>
<circle cx="1.5" cy="1.7" r=".75" id="apple-fill" fill="none" stroke="rgb(204, 50, 50)" stroke-width="1.5" stroke-dasharray="0,20" transform="rotate(-90,1.5,1.7)" clip-path="url(#apple)" />
<path id="pomodoro" stroke-width=".01" fill="none" stroke="#000" d="M1.5.5A.2.2 0 0 1 1.7.315A1.4 1.3 0 1 1 1.3.315A.2.2 0 0 1 1.5.5" />
<path id="leaf" stroke-width=".01" stroke-linejoin="arc" fill="green" d="M1.5.6A.4.4 0 0 1 2 .1A.5.5 0 0 1 1.5.6" />
<line id="hand" stroke="black" stroke-width=".02" x1="1.5" y1="1.7" x2="1.5" y2=".2" />
</svg>