如何使用CSS3或VanillaJS在SVG动画中为时钟效果制作圆形动画



我有以下代码:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="city-total-v2" version="1.1" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<g id="Block1board">
	<g>
		<linearGradient id="SVGID_492_" gradientUnits="userSpaceOnUse" x1="206.0166" y1="603.585" x2="165.4035" y2="493.2244">
			<stop offset="0" style="stop-color: rgb(48, 66, 204);" />
			<stop offset="1" style="stop-color: rgb(48, 66, 204); stop-opacity: 0;" />
		</linearGradient>
		<polygon fill-rule="evenodd" clip-rule="evenodd" fill="url(#SVGID_492_)" points="109.77,675.92 109.77,488.97 262.38,422.89 262.38,609.83 109.77,675.92  " />
		<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#3042CC" points="116.19,721.81 116.19,721.42 109.7,716.77 109.7,611.43 262.73,540.88 269.11,545.97 269.21,545.93 269.21,651.25 118.96,720.53 116.63,721.74 116.52,721.66 116.19,721.81  " />
		<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#0A2C60" points="116.19,721.81 116.19,721.42 109.7,716.77 109.7,611.43 201.92,682.28 118.96,720.53 116.63,721.74 116.52,721.66 116.19,721.81  " />
		<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M134.53,655.73c0.08-19.16,10.9-37.98,24.14-42 c13.24-4.03,23.92,8.25,23.83,27.41c-0.08,19.16-10.9,37.97-24.14,42S134.44,674.88,134.53,655.73L134.53,655.73z" style="     display: block; " />
		<linearGradient id="SVGID_493_" gradientUnits="userSpaceOnUse" x1="161.1758" y1="638.1934" x2="161.1758" y2="663.8602">
			<stop offset="0" style="stop-color: rgb(48, 66, 204);" />
			<stop offset="1" style="stop-color: rgb(75, 235, 201);" />
		</linearGradient>
		<path fill-rule="evenodd" clip-rule="evenodd" fill="url(#SVGID_493_)" d="M142.87,672.1L142.87,672.1l17.48-22.04v-32.18 c10.75-2.23,19.2,8.14,19.13,23.96c-0.07,16.5-9.39,32.71-20.8,36.18C152.31,679.96,146.63,677.51,142.87,672.1L142.87,672.1z" style="     transform: rotate3d(0, 16deg); " />
	</g>
</svg>

单击运行代码片段查看演示。

我想用渐变形状填充圆圈(就像时钟一样(

这可能使用CSS3或VanillaJS吗??非常感谢任何建议

为了让它发挥作用,我已经注释掉了你的最后一条路径,现在我正在动态绘制它。随着动画的每一步,路径都会改变其形状。

要开始动画,请单击svg画布。

请阅读我在代码中的评论

let c = {x:159,y:648.13}//the center of the shape
let tilt = 16;//the tilt angle
// the radiuses of the ellipse 
let R = 30.5;
let r = 17.8;
let steps = 360;// number of frames for the animation
let step = 2*Math.PI/steps;
let rid = null;// request animation id
let ry = [];// an array for the points used to draw the ellipse
//rotate the path
test.setAttributeNS(null,"transform",`rotate(${tilt} ${c.x} ${c.y})` )

let a = -Math.PI/2 -(16 * Math.PI/180);// starting angle
function Frame(){
rid= requestAnimationFrame(Frame);
// with every step a new point is pushed in the points array
if(a < 3*Math.PI/2){a+=step
let x = c.x + r*Math.cos(a);
let y = c.y + R*Math.sin(a);
ry.push({x,y})
// build the d attribute for the path
let d = `M${c.x},${c.y}`;
ry.map(e=>{
d+=`L${e.x},${e.y}`
})
d+="Z" 
// reset the d attribute for the path                     
test.setAttributeNS(null,"d",d);
}else{
// when everithing is done, stop the animation
cancelAnimationFrame(rid)
}
}
// restart animation on click
svg.addEventListener("click",()=>{
if(rid){cancelAnimationFrame(rid); rid="null"}
a = -Math.PI/2 -(16 * Math.PI/180);
ry = [];
Frame()
})
svg{border:1px solid}
<svg id="svg" viewBox="100 400 200 350" width="200">
<defs>
<linearGradient id="SVGID_492_" gradientUnits="userSpaceOnUse" x1="206.0166" y1="603.585" x2="165.4035" y2="493.2244">
<stop offset="0" style="stop-color: rgb(48, 66, 204);" />
<stop offset="1" style="stop-color: rgb(48, 66, 204); stop-opacity: 0;" /></linearGradient>
<linearGradient id="SVGID_493_" gradientUnits="userSpaceOnUse" x1="161.1758" y1="638.1934" x2="161.1758" y2="663.8602">
<stop offset="0" style="stop-color: rgb(48, 66, 204);" />
<stop offset="1" style="stop-color: rgb(75, 235, 201);" />
</linearGradient>  
</defs> 

<g id="Block1board">
<polygon fill="url(#SVGID_492_)" points="109.77,675.92 109.77,488.97 262.38,422.89 262.38,609.83 109.77,675.92  " />
<polygon fill="#3042CC" points="116.19,721.81 116.19,721.42 109.7,716.77 109.7,611.43 262.73,540.88 269.11,545.97 269.21,545.93 269.21,651.25 118.96,720.53 116.63,721.74 116.52,721.66 116.19,721.81  " />
<polygon fill="#0A2C60" points="116.19,721.81 116.19,721.42 109.7,716.77 109.7,611.43 201.92,682.28 118.96,720.53 116.63,721.74 116.52,721.66 116.19,721.81" />
<path fill="#FFFFFF" d="M134.53,655.73c0.08-19.16,10.9-37.98,24.14-42 c13.24-4.03,23.92,8.25,23.83,27.41c-0.08,19.16-10.9,37.97-24.14,42S134.44,674.88,134.53,655.73L134.53,655.73z" />

<!--<path fill="url(#SVGID_493_)" d="M142.87,672.1L142.87,672.1l17.48-22.04v-32.18 c10.75-2.23,19.2,8.14,19.13,23.96c-0.07,16.5-9.39,32.71-20.8,36.18C152.31,679.96,146.63,677.51,142.87,672.1L142.87,672.1z" style="transform: rotate3d(0, 16deg); " />-->

<path id="test" d="" fill="url(#SVGID_493_)"  />  
</g>
</svg>

更新

为了在不同的角度停止动画,我添加了let stopAngle = (240*Math.PI/180)-Math.PI/2;在这种情况下,温度为240摄氏度。如果需要使动画变慢,请更改step持续时间。例如,尝试step = 0.008;而不是step = 2*Math.PI/steps

let c = {x:150,y:150}
let R = 120;
let r = 90;
let steps = 360;
let step = 0.005//2*Math.PI/steps;
let rid = null;
let ry = []

let a = -Math.PI/2;// starting angle
let stopAngle = (240*Math.PI/180)-Math.PI/2
function Frame(){
rid= requestAnimationFrame(Frame);
if(a < stopAngle){a+=step
let x = c.x + r*Math.cos(a);
let y = c.y + R*Math.sin(a);
ry.push({x,y})
let d = `M${c.x},${c.y}`;
ry.map(e=>{
d+=`L${e.x},${e.y}`
})
d+="Z" 

test.setAttributeNS(null,"d",d);
}else{
cancelAnimationFrame(rid)
}
}
Frame();

最新更新