Анимация движения Image

117
10 августа 2021, 18:20

Я создал путь SVG и хочу анимировать изображение вдоль этого пути.
Я могу анимировать объект, используя тег <animateMotion>. Но я не могу понять, как это сделать с изображением.

Вот мой путь SVG:

<svg id="svg" height="1746px" width="100%">
    <path d="M 100 50 Q 100 150 200 220 L 650 630 C 700 670 700 700 650 730 C 390 850 390 1000 580 1000
     Q 800 1000 900 1450 Q 900 1550 800 1550 L 300 1585 Q 160 1620 160 1740"stroke="black" stroke-width="30" fill="none"
    id="animatePath"/>
    <img src="car.png" id="car">
    <animateMotion xlink:href="#car" dur="10s" repeatCount="indefinite" begin="0s">
        <mpath xlink:href="#animatePath"/>
    </animateMotion>
</svg>
Answer 1

Я сделал анимацию path с помощью JavaScript (также работает на IE). Вы также можете анимировать свое изображение таким образом.

 //Задаем количество автомобилей 
          var carCount = 8; 
          var i;  
		   // Задаем цвета для автомобилей 
          var colors = [ "Dodgerblue", "Blue", "Purple", "CornFlowerBlue","Red", "LimeGreen", "Gold", "Sienna"]; 
            // // Создаем холст SVG           
		 var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); 
          var _create = function (type){return document.createElementNS("http://www.w3.org/2000/svg", type);} 
          var _set = function (el,par){for (key in par) {el.setAttribute(key.replace('X','-'),par[key]);}svg.appendChild(el);} 
          // Задаем атрибуты SVG          
		 with(svg){  
            setAttribute('width', '450'); 
            setAttribute('height', '450'); 
            setAttribute("viewBox", "0 0 250 250");  
            setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); 
          }  
          svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); 
          svgG.appendChild(svg); 
          var adenaubullet = _create("circle"); 
          _set(adenaubullet,{r:7,fill:'#f00',stroke:'#f00',cx:110,cy:8,strokeXwidth:1}); 
           // Создаем трассу NORDSCHLEIFE 
		  var pfad = _create("path"); 
          pfad.setAttribute("d","M23.748,97.732c-4.235-2.956-3.875-3.774,0.149-6.424c4.415-2.912,9.246-4.657,13.445-7.991c3.775-2.997,6.616-6.559,8.157-11.154c0.658-1.969,0.469-3.708,0.928-5.656c0.49-2.073,2.818-3.084,2.289-5.231c-1.943-7.859,12.718-12.905,15.122-20.157c3.09-9.145-16.734-9.687-5.879-15.675c3.809-2.103,3.375-6.84,6.656-9.057c4.651-3.144,8.367,1.576,11.515,4.158c3.215,2.642,3.816-0.669,7.024-1.456c3.189-0.786,10.073,3.112,11.988-0.465c1.826-3.412,1.65-7.33,6.191-8.478c4.341-1.098,8.877-0.364,12.739-3.081c1.894-1.331,6.225-6.532,8.439-2.986c2.437,3.904-0.348,10.177,0.854,14.706c2.772,10.454,17.172,9.7,25.21,10.781c9.04,1.215,17.95,12.277,26.751,6.006c3.794-2.695,4.927-5.525,10.095-6.125c1.264-0.15,7.907-1.917,7.61,0.729c-0.316,2.853-6.305,5.333-8.338,6.711c-4.479,3.022-0.753,6.298,1.884,2.81c3.211-4.251,8.561-3.146,12.597-5.729c3.836-2.448,4.706-5.857,5.413-9.774c1.985-10.859,17.365-0.166,21.786,3.753c4.462,3.959,0.835,6.313,1.039,10.839c0.191,3.879,3.526,1.893,5.27,4.377c1.404,1.99,0.811,7.445-1.462,8.753c-3.792,2.168-6.586-2.64-9.273,2.805c-1.183,2.4-3.285,4.19-3.92,6.858c-0.735,3.091,1.969,7.785-0.122,10.477c-1.086,0.723-2.258,1.257-3.517,1.6c-1.907,1.228-3.592,3.089-5.258,4.608c-2.656,2.422-4.04,5.798-6.476,8.439c-3.986,4.336-10.271,6.805-16.063,7.526c-1.563,0.396-3.123,0.396-4.681,0c-2.271-0.944-1.521-3.241-4.827-2.771c-2.364,0.319-6.657,3.103-4.31,5.873c3.164,3.744,14.496,4.718,10.232,11.852c-4.087,6.844-13.375,9.795-19.857,13.7c-7.564,4.557-15.104,9.15-22.606,13.8c-7.321,4.53-16.081,8.639-22.572,14.298c-4.59,4.036-7.287,12.104-12.4,15.145c-2.264,1.35-1.265,4.361-4.132,5.722c-2.816,1.335-5.621-0.041-7.605-2.184c-0.949-1.027-2.493-4.413-4.188-2.536c-2.399,2.652-5.102,5.234-8.833,5.743c-3.432,0.466-6.206-1.944-9.507-1.572c-3.674,0.413-5.729-0.104-7.561-3.373c-1.255-2.242-3.559-3.075-5.613-4.396c-3.346-2.152-5.549-4.272-8.34-7.002c-5.066-4.96-13.847-9.133-14.34-17.222c-0.215-3.656,2.038-7.426,2.341-11.079c0.397-4.697-0.287-9.311-1.945-13.715c-1.431-3.801-3.489-7.284-4.994-11.039C29.209,99.368,26.926,99.928,23.748,97.732");  
          _set(pfad,{fill:'none',stroke:'#666',strokeXwidth:6}); 
          var bordstein=pfad.cloneNode(true); 
          _set(bordstein,{stroke:'#ddd',strokeXwidth:4}); 
          //Вариант трассы GRAND-PRIXSTRECKE (красный цвет трассы) 
		  var grandprix = _create("path"); 
          grandprix.setAttribute("d","M32.246,245.125c-2.99-2.644,4.779-6.693,6.57-8.077c3.212-2.479,6.842-4.163,5.87-8.961c-0.891-4.404,1.944-8.48,3.929-12.302c1.225-2.359,2.457-4.719,3.468-7.177c1.085-2.64,0.846-3.498-1.781-4.92c-2.916-1.579-8.019-3.264-4.406-7.271c3.643-4.035,7.452-7.957,11.752-11.297c3.277-2.547,7.475-2.651,11.457-3.249c1.722-0.26,13.399-0.733,13.39-2.918c-0.015-3.294,6.497-2.777,8.654-3.153c1.517-0.266,5.267-1.056,5.688,1.308c0.445,2.497-1.268,3.257-2.928,4.664c-7.362,6.223-15.047,12.292-22.803,18.019c-0.534,0.395-8.754,5.805-8.457,3.525c0.423-3.213,5.225-8.695,1.275-11.084c-2.188-1.332-4.133-0.486-6.367,0.376c-1.574,0.607-5.299,1.734-6.084,3.411c-0.74,1.58,0.625,3.774,2.29,3.882c1.022,0.069,3.515-1.991,3.427,0.323c-0.094,2.511,0.521,5.18-0.138,7.646c-0.792,2.955-2.661,5.646-4.08,8.322c-0.9,1.696-3.023,4.913-2.296,7.02c0.89,2.563,4.673,2.549,5.777,4.88c1.078,2.279-4.431,3.46-5.976,4.184c-2.971,1.387-5.743,2.851-8.27,4.98c-1.822,1.534-3.684,3.438-5.079,5.381C35.841,244.419,34.963,247.523,32.246,245.125"); 
          _set(grandprix,{fill:'none', stroke:'#000', strokeXwidth:4}); 
          var grandprixbordstein=grandprix.cloneNode(true); 
          _set(grandprixbordstein,{stroke:'#f00',strokeXwidth:3}); 
          var myText=_create("text"); 
          with (myText){ 
            setAttribute("font-family", "Arial, sans-serif"); 
            setAttribute("font-weight", "bold"); 
            setAttribute("font-style", "italic"); 
            setAttribute("text-anchor", "middle"); 
          } 
          var myTextNode = document.createTextNode(""); 
          myText.appendChild(myTextNode); 
          var nordschleife=myText.cloneNode(true); 
          _set(nordschleife,{x:120,y:77,fontXsize:16}); 
          nordschleife.textContent="NORDSCHLEIFE"; 
          var grandprixtext=nordschleife.cloneNode(true); 
          _set(grandprixtext,{x:110,y:220,fontXsize:16}); 
          grandprixtext.textContent="GRAND-PRIX"; 
          var grandprixtext1=nordschleife.cloneNode(true); 
          _set(grandprixtext1,{x:110,y:240,fontXsize:16}); 
           grandprixtext1.textContent="STRECKE"; 
          var adenautext=nordschleife.cloneNode(true); 
          _set(adenautext,{x:165,y:14,fontXsize:16}); 
          adenautext.textContent="ADENAU"; 
          var roundSquare=[]; 
          var mySquare=_create("rect"); 
          var roundBullet=[]; 
          var roundBulletText=[]; 
          for (i=1;i <= carCount;i++){ 
             
            roundBullet[i]=adenaubullet.cloneNode(true); 
            _set(roundBullet[i],{r:5,strokeXwidth:0,fill:colors[i],stroke:colors[i],cx:180,cy:120+i*5*3}); 
             
            roundSquare[i]=mySquare.cloneNode(true); 
            _set(roundSquare[i],{x:203,y:113+i*5*3,fill:'#ddd',stroke:'none',height:13,width:30}); 
             
            roundBulletText[i]=adenautext.cloneNode(true); 
            _set(roundBulletText[i],{x:210,y:125+i*5*3,fontXsize:14,fontXstyle:'normal'}); 
            roundBulletText[i].textContent="0"; 
          } 
          var lapsText=nordschleife.cloneNode(true); 
          _set(lapsText,{x:217,y:122,fontXsize:14,fontXstyle:'normal'}); 
          lapsText.textContent="LAPS"; 
          var cars = []; 
          var step=[]; 
          var laps=[]; 
          var len = pfad.getTotalLength(); 
          var speed = 1.5; 
          var pos = []; 
          var pt; 
          var repeater; 
          var lapPos = []; 
           // Создаем автомобиль 
		  var carProto = _create("circle"); 
          with (carProto){ 
            setAttribute("r", 3); 
            setAttribute("stroke-width", "1"); 
          } 
          for(i = 1; i <= carCount; i++){ 
            cars[i]=carProto.cloneNode(true); 
            pos[i]=i*5+750; 
            laps[i]=0; 
            lapPos[i]=750; 
            pt=pfad.getPointAtLength(len/1000*pos[i]) 
            _set(cars[i],{cx:pt.x,cy:pt.y,stroke:colors[i],fill:colors[i]}); 
            step[i]=speed+Math.random()/1; 
          } 
          var animate=function(){ 
            for(i = 1; i <= carCount; i++){ 
              pos[i]+=step[i]; 
              lapPos[i]+=step[i]; 
              if(pos[i]>1000){ 
                pos[i]=1; 
                step[i]=speed+Math.random()/2;   
              } 
              if (lapPos[i]>1750){ 
                lapPos[i]=750; 
                laps[i]++; 
                roundBulletText[i].textContent=laps[i]; 
              } 
              pt=pfad.getPointAtLength(len/1000*pos[i]) 
              cars[i].setAttribute("cx", pt.x); 
              cars[i].setAttribute("cy", pt.y); 
            } 
            //Повторение = requestAnimationFrame(animate); 
            repeater = setTimeout(animate,1000/60); 
          } 
          animate(); 
 
      </script>
 body  
		  { 
		  font-family:"Calibri", "Helvetica", sans-serif; 
		  } 
          .content { 
		  width:300px; 
		  margin-left:auto; 
		  margin-right:auto; 
		  } 
          #svgG { 
		  width:200px; 
		  margin-left:auto; 
		  margin-right:auto;} 
           
		  svg { 
		  width:450px; 
		  height:450px; 
		  overflow:hidden; 
		  } 
          h1,p{text-align:center;} 
          p{font-size:8px;} 
          .p10{font-size:14px;font-weight:bold;}
  <div class="content"> 
        <div id="svgG"></div> 
        
         
        </div>

Источник ответа: @Frank Wisniewski

Примечание переводчика:

Убрал лишнюю информацию о сайте разработчика скрипта.
Добавил комментарии в скрипт.

Answer 2

Для привязки растрового изображения к пути с помощью команды анимации animateMotion
вместо тега <img> лучше использовать тег SVG <image>

 <image xlink:href="https://i.stack.imgur.com/gLbds.png" y="-15" x="-15"  id="car" width="25px" height="25px">

атрибуты <image>: y="-15" x="-15" позиционируют иконку относительно пути

<svg id="svg" height="1746px" width="100%"> 
     <!-- Траектория движения --> 
	<path d="M 100 50 Q 100 150 200 220 L 650 630 C 700 670 700 700 650 730 C 390 850 390 1000 580 1000 
     Q 800 1000 900 1450 Q 900 1550 800 1550 L 300 1585 Q 160 1620 160 1740"stroke="black" stroke-width="30" fill="none" 
    id="animatePath"/> 
   <!-- Добавление растрового изображения -->    
   <image id="car" xlink:href="https://i.stack.imgur.com/gLbds.png" y="-15" x="-15"   width="25px" height="25px"> 
    <animateMotion 
	  xlink:href="#car" 
	  dur="20s" 
	  repeatCount="1" 
	  begin="start.click" 
	  restart="whenNotActive" > 
       
	  <mpath xlink:href="#animatePath"/> 
    </animateMotion>  
	</image> 
	 <!-- Кнопка запуска анимации --> 
	<g id="start"> 
	 <rect x="120" y="10" width="80" height="30" rx="5" fill="transparent" stroke="#B59964" /> 
	  <text x="138" y="33" font-size="24" fill="#C75C5C" >Start </text> 
	</g> 
</svg>

Источник ответа: @Alexandr_TT

READ ALSO
Как правильно обработать и обновить документы в MongoDB на NODE JS?

Как правильно обработать и обновить документы в MongoDB на NODE JS?

Как мне проверить новые полученные данные с ранее полученными данными в коллекции и сравнить если такая запись уже существует тогда к count этой...

246
Сохранение положения выбранного option в разных select

Сохранение положения выбранного option в разных select

Как сохранить выбранное положение option в select с нужным классомВ js и jQ не силён

343
scrollHeight и clientHeight равны 0 JS

scrollHeight и clientHeight равны 0 JS

Такой странный баг у меня

182
Кэширование внешних API в Angular PWA и окружение

Кэширование внешних API в Angular PWA и окружение

Можно ли при использовании @angular/pwa кэшировать внешние API (домен приложения и API не совпадает)Если да то каким образом должна выглядеть коyфигурация...

205