1

In Firefox (121.0b9), when scaling canvas elements, I notice slight jitteriness. I don't experience this in Safari or Chromium. Is there a way to work around this in Firefox?

Here's an example (JSFiddle). (If you're on macOS, activate "Use scroll gesture with modifier keys to zoom" to zoom in on the bottom right corner. On JSFiddle, when you're zoomed in, use "Command + Enter" to rerun.)

<!DOCTYPE html>

<style>
  canvas {
    margin: 100px;
  }
</style>

<canvas width="400" height="400" />

<script>
  window.onload = function () {
    // make canvas
    const elem = document.querySelector("canvas");
    const ctx = elem.getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.fillRect(0, 0, elem.width, elem.height);
    ctx.fillStyle = "black";
    ctx.fillRect(50, 50, 300, 300);

    // scale loop
    const start = performance.now();
    const end = start + 2000;

    const tick = () => {
      const now = performance.now();
      const t = Math.min(1, (now - start) / (end - start));
      const t2 = 1 - Math.pow(2, -10 * t); // easeOutExpo
      elem.style.transform = `scale(${1 - 0.5 * t2})`;
      if (now < end) {
        requestAnimationFrame(tick);
      }
    };

    tick();
  };
</script>

Possibly related: https://bugzilla.mozilla.org/show_bug.cgi?id=663776

1 Answer 1

1

here is a different approach, you could use delta time instead

const tick = (timestamp) => {
        if (!start) {
            start = timestamp || performance.now();
        }
        const elapsed = (timestamp || performance.now()) - start;
        const t = Math.min(1, elapsed / (end - start));
        const t2 = parseFloat(1 - Math.pow(2, -10 * t).toFixed(3)) + 0.0002;
        elem.style.transform = `scale(${1 - (0.5 * parseFloat(t2.toFixed(3)))})`;
        if (elapsed < end - start) {
            requestAnimationFrame(tick);
        }
    };
    requestAnimationFrame(tick);

Demo

jsfiddle link

Snippet

<!DOCTYPE html>

<style>
  canvas {
    margin: 100px;
  }
</style>

<canvas width="400" height="400" />

<script>
  window.onload = function () {
    // make canvas
    const elem = document.querySelector("canvas");
    const ctx = elem.getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.fillRect(0, 0, elem.width, elem.height);
    ctx.fillStyle = "black";
    ctx.fillRect(50, 50, 300, 300);

    // scale loop
    const start = parseFloat(performance.now().toFixed(3));
    const end = start + 2000;

    const tick = (timestamp) => {
        if (!start) {
            start = timestamp || performance.now();
        }
        const elapsed = (timestamp || performance.now()) - start;
        const t = Math.min(1, elapsed / (end - start));
        const t2 = parseFloat(1 - Math.pow(2, -10 * t).toFixed(3)) + 0.0002;
        elem.style.transform = `scale(${1 - (0.5 * parseFloat(t2.toFixed(3)))})`;
        if (elapsed < end - start) {
            requestAnimationFrame(tick);
        }
    };
    requestAnimationFrame(tick);
  };
</script>

Sign up to request clarification or add additional context in comments.

2 Comments

@Michael I've updated my answer with a new appoarch (still using my old code) but now with support for firefox
I appreciate the fast responses. I tried your old and your new version (as of 2023-12-15 12:58:29Z) and both have shakiness for me in Firefox (121.0b9).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.