# Why do my sprite animations leak memory after a few scene changes?

**URL:** <https://forum.kirupa.com/t/why-do-my-sprite-animations-leak-memory-after-a-few-scene-changes/680185>\
**Category:** web dev\
**Created:** [April 8, 2026, 4:00am UTC](https://forum.kirupa.com/t/why-do-my-sprite-animations-leak-memory-after-a-few-scene-changes/680185 "2026-04-08T04:00:12Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![BobaMilk](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/bobamilk/32/31157_2.png) [@BobaMilk](https://forum.kirupa.com/u/BobaMilk)\
**Post date:** [April 8, 2026, 4:00am UTC](https://forum.kirupa.com/t/why-do-my-sprite-animations-leak-memory-after-a-few-scene-changes/680185/1 "2026-04-08T04:00:12Z")

</div>

Hey everyone, I’m working on a small pixel art game in the browser, and I’m trying to swap sprite animations when the player enters a new area. It works at first, but after a few scene changes the tab gets heavy, and I think old animation state is still hanging around.

```js
function play(anim) {
  const img = new Image();
  img.src = anim.sheet;

  function tick() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(img, anim.frame * 16, 0, 16, 16, 40, 40, 64, 64);
    anim.frame = (anim.frame + 1) % anim.count;
    requestAnimationFrame(tick);
  }

  requestAnimationFrame(tick);
}

```

What is the clean way to switch animations here without leaking old loops or keeping dead sprite objects in memory?

BobaMilk

---

<div class="post-metadata">

**Author:** ![Yoshiii](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/yoshiii/32/31156_2.png) [@Yoshiii](https://forum.kirupa.com/u/Yoshiii)\
**Post date:** [April 8, 2026, 4:14am UTC](https://forum.kirupa.com/t/why-do-my-sprite-animations-leak-memory-after-a-few-scene-changes/680185/2 "2026-04-08T04:14:31Z")

</div>

@BobaMilk yup, every `play()` call starts another `requestAnimationFrame` loop, so the old one keeps running in the background with its own `img` and `anim`.

```auto

js
let rafId = null;

function play(anim) {
  if (rafId !== null) cancelAnimationFrame(rafId);

  const img = new Image();
  img.src = anim.sheet;
  anim.frame = 0;

  function tick() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(img, anim.frame * 16, 0, 16, 16, 40, 40, 64, 64);
    anim.frame = (anim.frame + 1) % anim.count;
    rafId = requestAnimationFrame(tick);
  }

  rafId = requestAnimationFrame(tick);
}

```

That gives you one active loop at a time. If you also destroy scenes, call `cancelAnimationFrame(rafId)` there too so a hidden tab or old area does not keep animating.

Yoshiii
