沿矩形路径平滑移动 SVG 线
Smoothly move an SVG line along a rectangular path
我正在尝试重新创建以下动画:
我无法让一条线在拐角处正确设置动画。我试过像这样使用 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 中所示,有什么想法吗?
您需要创建一个路径,其中 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);
//the value od the d attribute of the new path
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);//set the d attribute
o.el.setAttribute("transform", `rotate(${45 * i})`);//set the rotation
svg.appendChild(o.el);//append the new path to the svg element
o.l = o.el.getTotalLength();//calculate the total length of the new path
//push the object for the path to the array
sqRy.push(o);
}
//for every element in the array set the stroke-dasharray and the 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>
同样的事情只是缩放旋转和平方的对角线乘数 - sqrt(2)
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>
不是计算出来的,而是通过svg属性变换对齐svg矩形(首选svg路径)并利用css stroke-dasharray 和 stroke-offset 进行动画处理,可以获得结果
if js is not an option then you can just add and align the rectangles you need
代码
svg>rect {
stroke-dasharray: 100;
-webkit-animation: draw 5s infinite linear;
/* Chrome, Safari, Opera */
animation: draw 5s infinite linear;
}
@keyframes draw {
to {
stroke-dashoffset: 1000;
}
}
@-moz-keyframes draw {
to {
stroke-dashoffset: 1000;
}
}
@-webkit-keyframes draw {
to {
stroke-dashoffset: 1000;
}
}
<svg width="500" height="500">
<rect width="300" height="300" style="fill:none;stroke-width:2;stroke:black" />
<rect width="210" height="210" transform='translate(150 1) rotate(45)' style="fill:none;stroke-width:2;stroke:black" />
<rect width="150" height="150" transform='translate(75 75)' style="fill:none;stroke-width:2;stroke:black" />
</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 中所示,有什么想法吗?
您需要创建一个路径,其中 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);
//the value od the d attribute of the new path
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);//set the d attribute
o.el.setAttribute("transform", `rotate(${45 * i})`);//set the rotation
svg.appendChild(o.el);//append the new path to the svg element
o.l = o.el.getTotalLength();//calculate the total length of the new path
//push the object for the path to the array
sqRy.push(o);
}
//for every element in the array set the stroke-dasharray and the 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>
同样的事情只是缩放旋转和平方的对角线乘数 - sqrt(2)
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>
不是计算出来的,而是通过svg属性变换对齐svg矩形(首选svg路径)并利用css stroke-dasharray 和 stroke-offset 进行动画处理,可以获得结果
if js is not an option then you can just add and align the rectangles you need
代码
svg>rect {
stroke-dasharray: 100;
-webkit-animation: draw 5s infinite linear;
/* Chrome, Safari, Opera */
animation: draw 5s infinite linear;
}
@keyframes draw {
to {
stroke-dashoffset: 1000;
}
}
@-moz-keyframes draw {
to {
stroke-dashoffset: 1000;
}
}
@-webkit-keyframes draw {
to {
stroke-dashoffset: 1000;
}
}
<svg width="500" height="500">
<rect width="300" height="300" style="fill:none;stroke-width:2;stroke:black" />
<rect width="210" height="210" transform='translate(150 1) rotate(45)' style="fill:none;stroke-width:2;stroke:black" />
<rect width="150" height="150" transform='translate(75 75)' style="fill:none;stroke-width:2;stroke:black" />
</svg>