Как анимировать круг для эффекта часов в SVG-анимации с использованием CSS3 или VanillaJS? - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть следующий код:

<?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 ??Любой совет очень ценится

1 Ответ

0 голосов
/ 13 декабря 2018

Чтобы заставить это работать, я закомментировал ваш последний путь, и теперь я рисую его динамически.С каждым шагом анимации путь меняет свою форму.

Чтобы запустить анимацию, нажмите svg canvas.

Пожалуйста, прочитайте мои комментарии в коде

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...