Я бы подумал, что это сработало бы (см .: https://www.w3.org/TR/2001/REC-smil-animation-20010904/#Accumulate):
<path transform="translate(100, 100)" fill="none" stroke-linejoin="bevel" id="motionpath" stroke="black" d="m 0, 0 c 40,0 45,35 180,35"></path>
<circle id="circle" r="25" stroke="black" stroke-width="3" fill="red" cx="100" cy="100">
<animateMotion begin="click" dur="1s" fill="freeze" addative="replace" accumulate="sum">
<mpath xlink:href="#motionpath"></mpath>
</animateMotion>
</circle>
Но это явно не так.
Я попробовал куча способов, в том числе поиск такой идеи:
<circle id="circle" r="25" stroke="black" stroke-width="3" fill="red" cx="100" cy="100">
<animate attributeName="cx" from="100" by="+180" begin="circle.click" dur="1s" fill="freeze" additive="replace" accumulate="sum"></animate>
<animate attributeName="cy" from="100" by="+35" begin="circle.click" dur="1s" fill="freeze" additive="replace" accumulate="sum"></animate>
</circle>
(фокусировался на поведении [перед рассмотрением пути], так как я думал, что это добавит 180 к cx и добавит 35 к cy каждый клик но это не так).
Ни одна из моих попыток не сработала.
Единственный способ, который я нашел, был с JS (используя накопление из первого примера), однако, я думаю, что мой JS способ более надежный и многократно используемый, чем в вопросе, так что, может быть, это немного поможет?
(Вы можете установить repeatCount в теге <animateMotion>
, и это будет рассмотрено в JS и на каждой итерации он не прыгает, как в демонстрационной версии вопроса et c.)
Демонстрация на CodePen (или ниже): https://codepen.io/Alexander9111/pen/VwLmKVd
![enter image description here](https://i.stack.imgur.com/MUSnZ.gif)
const svg = document.querySelector('svg');
const circle = document.querySelector('#circle');
const motionP = document.querySelector('#motionpath');
let animateM = document.querySelector('#circle > animateMotion');
let currentRepeatCount = 0;
const RepeatCount = animateM.getAttribute('repeatCount');
animateM.setAttribute('repeatCount', 'indefinite');
animateM.addEventListener('repeatEvent', (e) => {
currentRepeatCount +=1;
console.log(currentRepeatCount);
svg.pauseAnimations();
});
circle.addEventListener('click', () => {
animateM = document.querySelector('#circle > animateMotion');
if (currentRepeatCount == 0){
animateM.beginElement();
} else if (currentRepeatCount == RepeatCount){
return void(0);
} else {
svg.unpauseAnimations();
}
})
<svg preserveAspectRatio="xMidYMid meet" width="auto" height="auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 400" style="background-color: #0010ff3b;">
<path transform="translate(100, 100)" fill="none" stroke-linejoin="bevel" id="motionpath" stroke="black" d="m 0, 0 c 40,0 45,35 180,35"></path>
<circle id="circle" r="25" stroke="black" stroke-width="3" fill="red" cx="100" cy="100">
<animateMotion begin="indefinite" dur="1s" fill="freeze" addative="replace" accumulate="sum" repeatCount="4">
<mpath xlink:href="#motionpath"></mpath>
</animateMotion>
</circle>
</svg>
Если вы хотите переместить путь вместе с нами, мы можем отредактировать событие повтора:
animateM.addEventListener('repeatEvent', (e) => {
currentRepeatCount +=1;
console.log(currentRepeatCount);
svg.pauseAnimations();
if (currentRepeatCount < RepeatCount){
const box = circle.getBoundingClientRect();
var pt = svg.createSVGPoint();
pt.x = (box.left + box.right) / 2;
pt.y = (box.top + box.bottom) / 2;
var svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
console.log(svgP.x,svgP.y)
motionP.setAttribute('transform', `translate(${svgP.x}, ${svgP.y})`)
}
});
И мы получаем это хорошее поведение :
![enter image description here](https://i.stack.imgur.com/nqmwA.gif)