Как плавно перемещать линию SVG по прямоугольному пути?
Я пытаюсь воссоздать следующую анимацию:
У меня проблемы с правильной анимацией линии вокруг углов.
Я пробовал использовать такой элемент анимации - animateMotion:
<line class="testLine" x1="10" y1="10" x2="100" y2="10" stroke="white">
<animateMotion dur="1.6s" repeatCount="indefinite"
path="M 10 10 L 390 10
M 390 10 L 390 290
M 390 290 L 10 290
M 10 290 L 10 10">
</animateMotion>
</line>
Но линия не плавно закругляет углы.
Есть идеи, как заставить её плавно перемещаться по углам, как показано в GIF выше?
Свободный перевод вопроса Smoothly move an SVG line along a rectangular path от участника @HaakonFlaar.
Ответы (2 шт):
Автор решения: Alexandr_TT
→ Ссылка
Вам нужно будет создать путь с srtoke-dasharray = 1/2 стороны прямоугольника и анимировать смещение stroke-dashoffset пути до 0
Пожалуйста, прочтите комментарии в коде:
const SVG_NS = "http://www.w3.org/2000/svg";
let sz = 50;//initial size 1/2 rect side
//the array of the paths. Inside the array uou have a first object for the path #p
let sqRy = [{ s: sz, d: "", l: p.getTotalLength(), el: p }];
//create several paths and rotate those paths accordingly
for (let i = 1; i < 8; i++) {
let o = {};
let size = sqRy[i - 1].s / 2;
o.s = Math.sqrt(2 * size * size);
//значение атрибута d нового пути
o.d = `M-${o.s},-${o.s}L${o.s},-${o.s} ${o.s},${o.s} -${o.s},${o.s} -${o.s},-${o.s}z`;
o.el = document.createElementNS(SVG_NS, "path");
o.el.setAttribute("d", o.d);//установить атрибут d
o.el.setAttribute("transform", `rotate(${45 * i})`);//установить велечину угла вращения
svg.appendChild(o.el);//добавить новый патч
o.l = o.el.getTotalLength();//рассчитать общую длину нового пути
//push объект для пути к массиву
sqRy.push(o);
}
//для каждого элемента в массиве установите stroke-dasharray и stroke-dashoffset.
sqRy.map((sq) => {
sq.el.setAttribute("style", `stroke-dasharray:${sq.s};stroke-dashoffset:${sq.l}`);
});
svg{fill:none;stroke:black;}
path{
animation: dash 16s linear infinite;
}
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
<svg width="300" viewBox="-60 -60 120 120" id="svg">
<path id="p" d="M-50,-50L50,-50 50,50 -50,50 -50,-50z" />
</svg>
Автор решения: Stranger in the Q
→ Ссылка
Та же штуковина, только за счет скейла и ротейта, ну и поменьше кода
document.querySelector('svg').innerHTML = [...Array(11)]
.map((_, i) => Math.pow(2, i/2))
.map((s, i) => `
<path transform="scale(${s})rotate(${i*45})"
stroke-width="${2/s}"
d="m5,5h-10v-10h10z"></path>
`).join(',');
path {
stroke-dasharray: 5 5;
fill: none;
stroke: black;
animation: shift 3s infinite linear;
}
@keyframes shift {
100% {stroke-dashoffset: -20}
}
<svg viewBox='-200,-200,400,400' width="90vw" height="90vh"></svg>
