最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - CSS animation through JS slows down and then stops when using translate with rotate - Stack Overflow

programmeradmin1浏览0评论

const box = document.querySelector('.box');
let id = undefined;

function animateTest() {
  const style = window.getComputedStyle(box);
  const matrix = new DOMMatrixReadOnly(style.transform);
  const translateY = matrix.m42 + 2;
  box.style.transform = `rotate(12deg) translateY(${translateY}px)`;
  id = requestAnimationFrame(() => animateTest());
}
id = requestAnimationFrame(() => animateTest());

let button = document.querySelector('.button');
button.addEventListener('click', function() {
  cancelAnimationFrame(id);
  box.style.transform = `rotate(12deg) translateY(0px)`;
  id = requestAnimationFrame(() => animateTest());
}, false);
.box {
  margin-left: 300px;
  width: 10px;
  height: 10px;
  background-color: black;
  transform: rotate(15deg);
}
<button class='button'>rerun</button>
<div class="box"></div>

const box = document.querySelector('.box');
let id = undefined;

function animateTest() {
  const style = window.getComputedStyle(box);
  const matrix = new DOMMatrixReadOnly(style.transform);
  const translateY = matrix.m42 + 2;
  box.style.transform = `rotate(12deg) translateY(${translateY}px)`;
  id = requestAnimationFrame(() => animateTest());
}
id = requestAnimationFrame(() => animateTest());

let button = document.querySelector('.button');
button.addEventListener('click', function() {
  cancelAnimationFrame(id);
  box.style.transform = `rotate(12deg) translateY(0px)`;
  id = requestAnimationFrame(() => animateTest());
}, false);
.box {
  margin-left: 300px;
  width: 10px;
  height: 10px;
  background-color: black;
  transform: rotate(15deg);
}
<button class='button'>rerun</button>
<div class="box"></div>

Here is jsfiddle demonstrating the problem:-

jsfiddle

Reload or save to rerun animation.

I am trying to move a box 12 degrees straight using translateY but when I add rotate to make it go that direction, the animation runs for a while and then it stops moving.

I think the requestAnimationFrame is called but the translateY property stops working.

If i remove the rotate(..) it works indefinitely as normal.

Why it slows and and stops when using rotate and how to make it not do that? thank you.

More simplified example-

My Html:

<div class="box">
 
</div>

My CSS:

.box {
  margin-left: 300px;
  width: 10px;
  height: 10px;
  background-color: black;
  transform: rotate(15deg);
}

My Script:

let box = document.querySelector('.box');
function animate() {
  const style = window.getComputedStyle(box);
  const matrix = new DOMMatrixReadOnly(style.transform);
  const translateY = matrix.m42 + 2;
  box.style.transform = `rotate(12deg) translateY(${translateY}px)`;
  requestAnimationFrame(() => animate());
}
requestAnimationFrame(() => animate());
Share Improve this question edited Mar 28 at 0:24 Kaiido 138k14 gold badges259 silver badges324 bronze badges asked Mar 27 at 17:27 Sidharth BajpaiSidharth Bajpai 3623 silver badges15 bronze badges 3
  • 1 I don't know 3d matrix transforms well enough to understand why, but matrix.m42 + 2 eventually reaches a point where using it as the value for translateY gives you the same value when you run it through the matix. – Quentin Commented Mar 27 at 17:35
  • @Quentin Oh okay, thank you for pointing me in right direction! That must definitely be the reason. – Sidharth Bajpai Commented Mar 27 at 17:37
  • 1 That's because you first rotate then translate, so the translation is itself "rotated" and thus doesn't correspond to a raw translateY anymore. If you look at the e or m41 member of your matrix you can see it doesn't stay to 0, even though you didn't set a translateX. If you did first translate then rotate you wouldn't have had the same issue, but you wouldn't have had the same animation either, so it's hard to tell what fits your needs the best. – Kaiido Commented Mar 28 at 0:23
Add a comment  | 

1 Answer 1

Reset to default 0

Using @Quentin's advice in comments, as a workaround I am able to make it work using translateY as an external property, instead of getting previous one from DomMatrix.

const box = document.querySelector('.box');
let id = undefined;
let translateY = 0;

function animateTest() {
  box.style.transform = `rotate(12deg) translateY(${translateY}px)`;
  translateY = translateY+2;
  id = requestAnimationFrame(() => animateTest());
}
id = requestAnimationFrame(() => animateTest());

let button = document.querySelector('.button');
button.addEventListener('click', function() {
  cancelAnimationFrame(id);
  translateY = 0;
  id = requestAnimationFrame(() => animateTest());
}, false);

setTimeout(()=> {cancelAnimationFrame(id)}, 5000);
.box {
  margin-left: 300px;
  width: 10px;
  height: 10px;
  background-color: black;
  transform: rotate(15deg);
}
<button class='button'>rerun</button>
<div class="box"></div>

发布评论

评论列表(0)

  1. 暂无评论