Как анимировать отскок теннисного мячика
У меня есть изображение теннисного мяча:
Необходимо сделать анимацию падения мячика с последующими отскоками от твердой поверхности.
У меня получилось такого рода анимация, но она выглядит не реалистично:
Для начала анимации кликните по изображению:
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet" style="border:1px solid" >
<image xlink:href="https://i.stack.imgur.com/hXyA5.png" x="82" width="25px" height="25px" >
<animateTransform attributeName="transform" type="translate" dur="1s" begin="svg1.click" values="0,0;0,168;0" repeatCount="3" />
</image>
<polyline points="5,190 190,190" stroke="silver" stroke-width="4" />
</svg>
Необходимо, чтобы первый отскок был меньше высоты падения мяча, второй отскок был меньше по высоте первого отскока, третий отскок меньше второго.
Как добиться этого? Решение может быть, на SMIL SVG, CSS, JS
Предпочтительнее решение SMIL SVG
Ответы (2 шт):
Какая-то такая зависимость, например, не имеет ничего общего с физикой, просто на глазок
let t, h, max = 165;
function start() {
t = Date.now();
h = max;
};
addEventListener('click', start);
start();
requestAnimationFrame(function a(){
const dt = Date.now() - t;
h *= 0.97;
const wave = Math.cos(dt/(200 - dt/25));
ball.setAttribute('y', max - Math.abs(wave)*h);
requestAnimationFrame(a)
})
<svg width="200" height="200"viewBox="0 0 200 200" style="border:1px solid" >
<image id="ball" xlink:href="https://i.stack.imgur.com/hXyA5.png" x="82" width="25px" height="25px" />
<polyline points="5,190 190,190" stroke="silver" stroke-width="4" />
</svg>
Решение SVG
Изменяемую величину отскока шарика, можно задать в значениях атрибута values="",
команды анимации animateTransform
Скоростью полета мяча на каждом отрезке времени можно управлять с помощью значений атрибута keyTimes
restart="whenNotActive" - защита от повторного запуска анимации пока она полностью не закончилась.
Анимация начнется после клика
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet" style="border:1px solid" >
<image xlink:href="https://i.stack.imgur.com/hXyA5.png" x="82" width="25px" height="25px" >
<animateTransform id="anT"
attributeName="transform"
type="translate"
dur="3s"
begin="svg1.click+0.5s"
values="
0,0;
0,168;
0,84;
0,168;
0,126;
0,168;
0,148;
0,168;
0,158;
0,168;
0,163;
0,168;
0,166;
0,168;"
keyTimes="0;0.066;0.13;0.198;0.264;0.33;0.396;0.462;0.528;0.594;0.66;0.726;0.792;1"
repeatCount="1"
fill="freeze"
restart="whenNotActive" />
</image>
<polyline points="5,193 194,193" stroke="silver" stroke-width="4" />
</svg>
Пример с зацикливанием анимации
Для этого в условии запуска анимации пишется следующее условие:
begin="svg1.click;anT.end+1s", где
svg1.click- первый запуск анимации после клика
anT.end+1s - повторный запуск анимации через 1 секунду, после окончания анимации c id="anT"
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet" style="border:1px solid" >
<image xlink:href="https://i.stack.imgur.com/hXyA5.png" x="82" width="25px" height="25px" >
<animateTransform id="anT"
attributeName="transform"
type="translate"
dur="3s"
begin="svg1.click+0.5s;anT.end+1s"
values="
0,0;
0,168;
0,84;
0,168;
0,126;
0,168;
0,148;
0,168;
0,158;
0,168;
0,163;
0,168;
0,166;
0,168;
"
keyTimes="0;0.066;0.13;0.198;0.264;0.33;0.396;0.462;0.528;0.594;0.66;0.726;0.792;1"
repeatCount="1"
fill="freeze"
restart="whenNotActive" />
</image>
<polyline points="5,193 194,193" stroke="silver" stroke-width="4" />
</svg>
