Перемещайте объект каждые несколько секунд, используя SVG - PullRequest
1 голос
/ 07 июня 2019

Рисуйте (один раз) и перемещайте объекты каждые пять секунд, как показано на рисунках слева направо. Я искал, но не смог найти способ рисовать внешние линии и перемещать объекты рядом с ним.

<animate xlink:href="#blue-rectangle"
         attributeName="x" 
         from="50"
         to="425" 
         dur="5s"
         begin="circ-anim.repeat(2)"
         fill="freeze" 
         id="rect-anim" />

ref: https://css -tricks.com / guide-svg-animations-smil /

https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Basic_Shapes

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateMotion

enter image description here enter image description hereenter image description here

1 Ответ

2 голосов
/ 07 июня 2019

Использование animateMotion было бы решением для непрерывного движения по траектории. Если вам нужно остановить движение через определенные промежутки времени, я бы использовал javascript. В этой книге: Использование SVG с CSS3 и HTML5: векторная графика для веб-дизайна у вас есть подробное описание того, как использовать JavaScript для эмуляции animateMotion

Чтобы остановить прямоугольник, я использую метку времени для обратного вызова requestAnimationFrame. В следующем примере я останавливаю прямоугольник каждые 2 секунды на 1 секунду.

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

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

let rid;//the request animation frame id
let track = document.getElementById("track"),
  trackLength = track.getTotalLength(),//the total length of the track
  dur = 15000; //duration of one loop of track, in ms
 
let lastTime = 0;//last time when the rect has stopped
let flag = false; 

let interval = 5000;


function update(time) {
  rid = requestAnimationFrame(update);
    // to stop the rect every 5 seconds
    var deltaT = time%interval;
    //during 1 second
    if (deltaT < interval/2){
    flag = false;
  var t = ((deltaT + lastTime) % dur) / dur, // position in repeat cycle
    distance, // distance along the path for this rect
    point, // SVGPoint for that distance
    point2; // SVGPoint for a slightly different distance

  distance = trackLength * (t % 1);
  point = track.getPointAtLength(distance);
  point2 = track.getPointAtLength((distance + 2) % trackLength);
  angle = Math.atan2(point.y - point2.y, point.x - point2.x);

  rect.setAttribute(
    "transform",
    "translate(" +
      [point.x, point.y] +
      ")" +
      "rotate(" +
      angle * 180 / Math.PI +
      ")"
  );

 }else{if(flag==false){lastTime += interval/2; flag = true;}}
  
}
rid = requestAnimationFrame(update);
svg{border:1px solid;}
path{fill:none; stroke:black;}
<svg viewBox = "0 0 150 200" width="200">
  <path id="track" d="M70,30 Q70,20 80,20L120,20 Q130,20 130,30L130,170.000 Q130,180 120,180L30,180 Q20,180 20,170L20,130 Q20,120 30,120L60,120 Q70,120 70,110Z" />
 <polygon id="rect" points="0,0 -10,0 -10,-10 0,-10 0,0" style="fill: #ff0000;"/> 
</svg>

UPDATE

И вот как я бы это сделал, используя animateMotion

setInterval(()=>{ svg.pauseAnimations(); 
                  setTimeout(()=>{svg.unpauseAnimations()},1000)
                },2000);
svg{border:1px solid;}
path{fill:none; stroke:black;}
<svg id="svg" viewBox = "0 0 150 200" width="300">
  <path id="track" d="M70,30 Q70,20 80,20L120,20 Q130,20 130,30L130,170.000 Q130,180 120,180L30,180 Q20,180 20,170L20,130 Q20,120 30,120L60,120 Q70,120 70,110Z" />
  <polygon id="rect" points="0,0 10,0 10,10 0,10 0,0" style="fill: #ff0000;">
  <animateMotion id="test" begin= "0s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze">
    <mpath xlink:href= "#track" />
    </animateMotion></polygon>
</svg>

ОБНОВЛЕНИЕ 2

Вот как вы перемещаете 5 блоков на пути: Единственное отличие - это атрибут begin для animateMotion.

все

setInterval(()=>{ svg.pauseAnimations(); 
                  setTimeout(()=>{svg.unpauseAnimations()},1500)
                },3000);
svg{border:1px solid;}
path{fill:none; stroke:black;}
<svg id="svg" viewBox = "30 0 360 450" width="300">
<defs>
<polygon id="theRect" points="0,0 20,0 20,20 0,20 0,0" style="fill: #ff0000;" />
</defs>

  <path id="track" d="M288.938,33 Q289,12 310,12L350,12 Q371,12 371,33L371,408 Q371,429 350,429L66,429 Q45,429 45,408L45,374 Q45,353 66,353L267,353 Q288,353 288.062,332Z" />
  
  
  <use xlink:href="#theRect">
  <animateMotion id="test" begin= "0s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
    <mpath xlink:href= "#track"  />
    </animateMotion></use>
  
  <use xlink:href="#theRect">
  <animateMotion id="test" begin= "-.5s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
    <mpath xlink:href= "#track"  />
    </animateMotion></use>
  
  <use xlink:href="#theRect">
  <animateMotion id="test" begin= "-1s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
    <mpath xlink:href= "#track" />
    </animateMotion></use>
  
  
   <use xlink:href="#theRect">
  <animateMotion id="test" begin= "-1.5s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
    <mpath xlink:href= "#track"  />
    </animateMotion></use>
  
  <use xlink:href="#theRect">
  <animateMotion id="test" begin= "-2s" dur="15s" repeatCount="infinite" rotate="auto" fill="freeze" >
    <mpath xlink:href= "#track"  />
    </animateMotion></use>
</svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...