使用 {strong> <animate attributeName="cx">
和<attributeName="cy">
的组合来寻找最佳点以实现“ 8”字形动画时,我非常头痛。 >
我愿意使用它,因为按照我的指标,它在FPS,CPU和GPU使用方面似乎是性能最高的。
“理想”运动路径的快速演示:https://codepen.io/ivancis/pen/eYmZowz
使用 {strong> <animate attributeName="cx">
和<attributeName="cy">
的组合来寻找最佳点以实现“ 8”字形动画时,我非常头痛。 >
我愿意使用它,因为按照我的指标,它在FPS,CPU和GPU使用方面似乎是性能最高的。
“理想”运动路径的快速演示:https://codepen.io/ivancis/pen/eYmZowz
您没有说您真正想要哪种动画。
因此,我将提供不同类型动画的示例,您可以选择它们中的任何一个并以某种方式自行修改。
无限符号移动动画
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="100" viewBox="0 0 100 100">
<path fill="none" stroke="dodgerblue" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10">
<animateTransform
attributeName="transform"
type="translate"
values="0; 150; 0"
begin="0s"
dur="4s"
repeatCount="indefinite" />
</path>
</svg>
旋转
将鼠标悬停在符号上
.infinity1{
transform-box: fill-box;
transform-origin: center center;
transition: rotate 2s linear ;
}
.infinity1:hover {
animation: spin 2s linear infinite;
}
@keyframes spin {
100% {transform :rotate(360deg);}
}
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<path class="infinity1" fill="none" stroke="dodgerblue" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10" />
</svg>
绕Y轴旋转
.infinity1{
transform-box: fill-box;
transform-origin: center center;
transition: rotate 2s linear ;
fill:transparent;
}
.infinity1:hover {
animation: spin 2s linear infinite;
}
@keyframes spin {
100% {transform :rotateY(360deg);}
}
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100" >
<path class="infinity1" stroke="dodgerblue" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10" />
</svg>
通过更改属性stroke-dasharray填充无穷大符号的动画
点击圆圈中的彩色字母
.container {
width:40%;
height="40%";
background:black;
}
<div class="container">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 20 100 100">
<path fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="#d3d3d3" stroke-width="10" />
<!-- The midpoint of the beginning of the animation in the center of the figure. stroke-dashoffset="31.1" -->
<path id="center" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="crimson" stroke-width="10" stroke-dashoffset="31.1" stroke-dasharray="0 128.5" >
<animate attributeName="stroke-dasharray" values="0 128.5 0 128.5;0 0 257 0" begin="btn_C.click" dur="4s" restart="whenNotActive" />
</path>
<!-- Middle point on the left stroke-dashoffset="-159.5" -->
<path id="Left" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="yellowgreen" stroke-width="10" stroke-dashoffset="-159.5" stroke-dasharray="0 128.5" >
<animate attributeName="stroke-dasharray" values="0 128.5 0 128.5;0 0 257 0" begin="btn_L.click" dur="4s" restart="whenNotActive" />
</path>
<!-- Midpoint left top stroke-dashoffset="128.5" -->
<path id="Top" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="gold" stroke-width="10" stroke-dashoffset="128.5" stroke-dasharray="0 128.5" >
<animate attributeName="stroke-dasharray" values="0 128.5 0 128.5;0 0 257 0" begin="btn_T.click" dur="4s" restart="whenNotActive" />
</path>
<!-- Midpoint lower right stroke-dashoffset="192.7" -->
<path id="Bottom" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="dodgerblue" stroke-width="10" stroke-dashoffset="192.7" stroke-dasharray="0 128.5" >
<animate attributeName="stroke-dasharray" values="0 128.5 0 128.5;0 0 257 0" begin="btn_B.click" dur="4s" restart="whenNotActive" />
</path>
<!-- Middle point on the right stroke-dashoffset="223.9" -->
<path id="Bottom" fill="none" d="M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z" stroke="purple" stroke-width="10" stroke-dashoffset="223.9" stroke-dasharray="0 128.5" >
<animate attributeName="stroke-dasharray" values="0 128.5 0 128.5;0 0 257 0" begin="btn_R.click" dur="4s" restart="whenNotActive" />
</path>
<g id="btn_L" transform="translate(-17 0)" >
<rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/>
<text x="25" y="95" font-size="10" fill="green" >L</text>
</g>
<g id="btn_C" transform="translate(3 0)">
<rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/>
<text x="24" y="95" font-size="10" fill="crimson" >C</text>
</g>
<g id="btn_T" transform="translate(23 0)">
<rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/>
<text x="24" y="95" font-size="10" fill="orange" >T</text>
</g>
<g id="btn_B" transform="translate(43 0)">
<rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/>
<text x="25" y="95" font-size="10" fill="dodgerblue" >B</text>
</g>
<g id="btn_R" transform="translate(63 0)">
<rect x="20" y="84" width="15" height="15" rx="7.5" fill="none" stroke="#B2B2B2"/>
<text x="25" y="95" font-size="10" fill="purple" >R</text>
</g>
</svg>
</div>
,
我只需要使用组合动画svg元素
<animate attributeName="cx">
<animate attributeName="cy">
(对于 性能)来使运动成“ 8”形,循环
由于作者不想使用animateMotion
命令,因此在这种情况下
我只看到一种方法来实现沿无穷大符号的圆运动动画:
必须沿无穷大符号顺序选择许多点,并将其坐标分配给圆cx = "x"
,cy = "y"
选择的点越多,圆沿着无穷大符号的轨迹移动越近
在矢量编辑器中,我依次将圆放在无穷大符号上,并记下其在圆心的坐标。第一个圆的中心坐标为cx ="70"
cy ="60"
因此,对沿无穷大符号定位的所有圆进行了此操作。最后一个圆与第一个圆具有相同的坐标,从而实现闭合循环
仅在动画公式cx
,cy
圆周运动动画cx
,cy
,半径为r="5
<div class="group">
<svg class="ball" xmlns="http://www.w3.org/2000/svg" width="50%" height="50%" viewBox="0 0 120 120">
<circle fill="olive" cx="70" cy="60" r="5">
<animate
attributeName="cx"
attributeType="XML"
repeatCount="indefinite"
begin="0s"
dur="2s"
values="70;65;60;55;50;45;40.5;40.5;42.5;45.1;48.7;52;55;58;60;61;61;61;61;61;61;62.9;66;69;
73;76;79;81;80;78;74;70">
</animate>
<animate
attributeName="cy"
attributeType="XML"
repeatCount="indefinite"
begin="0"
dur="2s"
values="60;60;60;60;60;58.3;52.5;47.9;44.4;41.8;40.3;40;41;43;47;51;55;60;65;70;74;77;79;
80;80;79;76;72;67;64;61;60">
</animate>
</circle>
<path fill="none" stroke="black" stroke-dasharray="2" d="M70.5,60.5c5.5,10,4.5,10s-4.5,10-10,10s-10-4.5-10-10v-20c0-5.5-4.5-10-10-10s-10,4.5-10,10 s4.5,10H70.5z"/>
</svg>
</div>
半径r = 40
,例如问题作者的示例
<div class="group">
<svg class="ball" xmlns="http://www.w3.org/2000/svg" width="50%" height="50%" viewBox="0 0 120 120">
<circle fill="olive" cx="70" cy="60" r="40">
<animate
attributeName="cx"
attributeType="XML"
repeatCount="indefinite"
begin="0s"
dur="2s"
values="70;65;60;55;50;45;40.5;40.5;42.5;45.1;48.7;52;55;58;60;61;61;61;61;61;61;62.9;66;69;
73;76;79;81;80;78;74;70">
</animate>
<animate
attributeName="cy"
attributeType="XML"
repeatCount="indefinite"
begin="0"
dur="2s"
values="60;60;60;60;60;58.3;52.5;47.9;44.4;41.8;40.3;40;41;43;47;51;55;60;65;70;74;77;79;
80;80;79;76;72;67;64;61;60">
</animate>
</circle>
<path fill="none" stroke="black" stroke-dasharray="2" d="M70.5,10H70.5z"/>
</svg>
</div>
,
我正在研究类似的问题,并且遇到了这个答案。 @Alexandr_TT的回答使我开始思考一种更灵活的方法,而无需使用图形编辑器(例如Inkscape等)
我想到了以下想法:
<AnimateMotion/>
。circle.getBoundingClientRect()
和svg.matrixTransform()
开始)<AnimateMotion/>
标签<animate id="cx" attributeName="cx" values="" .../>
和<animate id="cy" attributeName="cy" values="" .../>
标签的values属性中cx.beginElement()
和cy.beginElement()
将这两个动画标签开始您可能对此性能感到满意,也可以使用其values="..."
属性复制粘贴DOM元素并将其保存为新的主文件,从而基本上实现了@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();
})