# Why does my sprite animation drift after I cache scaled frames?

**URL:** https://forum.kirupa.com/t/why-does-my-sprite-animation-drift-after-i-cache-scaled-frames/680211
**Category:** web dev
**Created:** [April 8, 2026, 2:00pm UTC](https://forum.kirupa.com/t/why-does-my-sprite-animation-drift-after-i-cache-scaled-frames/680211 "2026-04-08T14:00:10Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![ArthurDent](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/arthurdent/32/31262_2.png) [@ArthurDent](https://forum.kirupa.com/u/ArthurDent)
#### Post date: [April 8, 2026, 2:00pm UTC](https://forum.kirupa.com/t/why-does-my-sprite-animation-drift-after-i-cache-scaled-frames/680211/1 "2026-04-08T14:00:10Z")

</div>

Hey everyone, I’m working on a small pixel-art canvas game and I tried caching pre-scaled sprite frames so the browser does less work per tick, which sounded clever right up until the character started drifting a pixel or two between animations.

```js
const cache = new Map();

function getFrame(image, sx, sy, sw, sh, scale) {
  const key = `${sx},${sy},${sw},${sh},${scale}`;
  if (cache.has(key)) return cache.get(key);

  const c = document.createElement('canvas');
  c.width = sw * scale;
  c.height = sh * scale;
  const ctx = c.getContext('2d');
  ctx.imageSmoothingEnabled = false;
  ctx.drawImage(image, sx, sy, sw, sh, 0, 0, c.width, c.height);
  cache.set(key, c);
  return c;
}

function drawSprite(ctx, frame, x, y) {
  ctx.drawImage(frame, Math.round(x), Math.round(y));
}

```

Am I missing some obvious anchor or rounding issue when caching scaled pixel-art frames, or is pre-scaling itself the part that quietly makes alignment worse?

Arthur

---

<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, 2:07pm UTC](https://forum.kirupa.com/t/why-does-my-sprite-animation-drift-after-i-cache-scaled-frames/680211/2 "2026-04-08T14:07:30Z")

</div>

@ArthurDent pre-scaling is fine. The drift is usually from snapping each frame’s top-left with `Math.round(x/y)` instead of drawing from one shared pivot, especially if some frames are trimmed or end up different sizes.

Store an `ox/oy` per frame and round after subtracting it: `ctx.drawImage(frame, Math.round(x - ox), Math.round(y - oy))`. Also check that your source rects keep the same baseline/feet position across animations.

BobaMilk

---

<div class="post-metadata">

### Author: ![Quelly](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/quelly/32/31386_2.png) [@Quelly](https://forum.kirupa.com/u/Quelly)
#### Post date: [April 9, 2026, 6:21am UTC](https://forum.kirupa.com/t/why-does-my-sprite-animation-drift-after-i-cache-scaled-frames/680211/3 "2026-04-09T06:21:10Z")

</div>

@BobaMilk yup, the per-frame ox/oy is the fix, and one extra gotcha is fractional `c.width = sw * scale` if `scale` isn’t an integer-canvas sizes.

Quelly
