Я искал аналогичную вещь и наткнулся на этот ответ. Ответ @Alexandr_TT заставил меня задуматься о более гибком способе сделать это без использования графического редактора (например, Inkscape и т. д.).
Мне пришла в голову следующая идея:
- Используйте
<AnimateMotion/>
для первого цикла.
- Запускайте setInterval каждые X миллисекунд и каждый раз, когда он срабатывает, чтобы захватить центральную точку круга (из
circle.getBoundingClientRect()
и svg.matrixTransform()
)
- Поместите эти значения x и y в два массива, чтобы зафиксировать их.
- Когда AnimateMotion заканчивается, очистите текущий setInterval и поместите первый элемент также в конец каждого из массивов (чтобы закрыть цикл).
- Удалите тег
<AnimateMotion/>
из DOM.
- Поместите эти массивы в атрибут values тегов
<animate id="cx" attributeName="cx" values="" .../>
и <animate id="cy" attributeName="cy" values="" .../>
.
- начинайте оба этих анимированных тега с
cx.beginElement()
и cy.beginElement()
Вы могли бы просто быть довольны этим с точки зрения производительности, или вы могли бы скопировать и вставить элементы DOM с их атрибутами values="..."
и сохранить это как ваш новый мастер-файл, по сути достигнув того, что @Alexandr_TT сделал с графическим редактором. Конечно, этот метод, который я показываю, является гибким, если вы решите изменить свой путь и т. д.
Демонстрация: https://codepen.io/Alexander9111/pen/VwLaNEN
HTML:
<circle id="circle" class="circle" cx="0" cy="00" r="125">
<animateMotion
path="M162.9,150c6.8-0.2,12.1-5.7,12.1-12.5c0-6.9-5.6-12.5-12.5-12.5c-6.8,0-12.3,5.4-12.5,12.2v25.7 c-0.2,6.8-5.7,12.2-12.5,12.2c-6.9,0-12.5-5.6-12.5-12.5c0-6.8,5.4-12.3,12.1-12.5L162.9,150z"
dur="4s" begin="0s"
epeatCount="1" fill="freeze"
calcMode="linear"
fill="freeze">
</animateMotion>
<animate id="cx" attributeName="cx" values="" dur="4s" repeatCount="indefinite" begin="indefinite"/>
<animate id="cy" attributeName="cy" values="" dur="4s" repeatCount="indefinite" begin="indefinite"/>
</circle>
JS:
const svg = document.querySelector('svg');
const animateElem = document.querySelector('animateMotion');
const circle = document.querySelector('#circle');
const cx = document.querySelector('#cx');
const cy = document.querySelector('#cy');
let myInterval;
let valuesX = [];
let valuesY = [];
function startFunction() {
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)
valuesX.push(svgP.x);
valuesY.push(svgP.y);
}
function endFunction() {
animateElem.parentNode.removeChild(animateElem);
clearInterval(myInterval)
valuesX.push(valuesX[0]);
valuesY.push(valuesY[0]);
cx.setAttribute('values', valuesX.join('; '));
cy.setAttribute('values', valuesY.join('; '));
circle.setAttribute('cx', 0);
circle.setAttribute('cy', 0);
cx.beginElement();
cy.beginElement();
}
animateElem.addEventListener('beginEvent', () => {
console.log('beginEvent fired');
myInterval = setInterval(startFunction, 50);
})
animateElem.addEventListener('endEvent', () => {
console.log('endEvent fired');
endFunction();
})
person
Alex L
schedule
17.02.2020