Skip to main content
Participant
July 28, 2017
Answered

HTML Animation Flickers When Resizing Browser Window

  • July 28, 2017
  • 1 reply
  • 5276 views

This issue seems to be still very common, even with the latest Adobe Animate CC 2017. I created an animation logo, and published it. When I place the HTML code in the website and link the javascript file, the logo animation will flicker when the browser window is being resized. This flickering will also happen when scrolling up and down quickly on an iPhone or iPad. This seems to be an ongoing issue, I see it in a lot of Google search results, including here: Canvas flickers when resizing window 

Apparently this "flickering" is because in the code there is some resizing of the canvas that occurs or it's something to do with HiDPI support. Even when trying people's certain solutions, I could never get the logo animation to be at the right size across all devices and with no flickering. I gave up in the end, and just exported the animation as a 20MB GIF file (at a larger scale), then reduced it using CSS, so that it looked more crisp and clear on the desktop and retina displays.

Adobe really need to look into this "flickering" issue because it looks tacky and unprofessional - I hope a solution is created soon in the next software update. 

This topic has been closed for replies.
Correct answer ClayUUID

Anyway, I've discovered the source of the problem. When you resize the browser window, a function in the HTML that Animate publishes gets called. This function always sets the width and height attribute of the canvas element, even when it hasn't changed. But surprise, setting the width or height of an element makes browsers consider that element to have been resized, even when the size hasn't changed. This wouldn't be a problem, except that resizing a canvas element clears its contents. So the canvas content disappears until CreateJS's next scheduled redraw. It's a perfect storm of unintuitive behaviors.

Here's my suggested fix. In the HTML that Animate publishes, there's a function called makeResponsive. It starts after the line "//Code to support hidpi screens and responsive scaling." and ends right before "makeResponsive(true, "both", false, 1);" (or similar). Replace that function definition with this code:

function makeResponsive(isResp, respDim, isScale, scaleType) {

    var lastW, lastH, lastS = 1;

    window.addEventListener("resize", window.requestAnimationFrame ? resizeCanvasReq : resizeCanvas);

    resizeCanvas();

    function resizeCanvasReq() {

        window.requestAnimationFrame(resizeCanvas);

    }

    function resizeCanvas() {

        var w = lib.properties.width, h = lib.properties.height;

        var iw = window.innerWidth, ih = window.innerHeight;

        var pRatio = window.devicePixelRatio || 1, xRatio = iw / w, yRatio = ih / h, sRatio = 1;

        if (isResp) {

            if ((respDim === "width" && lastW === iw) || (respDim === "height" && lastH === ih)) {

                sRatio = lastS;

            }

            else if (!isScale) {

                if (iw < w || ih < h) {

                    sRatio = Math.min(xRatio, yRatio);

                }

            }

            else if (scaleType === 1) {

                sRatio = Math.min(xRatio, yRatio);

            }

            else if (scaleType === 2) {

                sRatio = Math.max(xRatio, yRatio);

            }

        }

        if (iw !== lastW || ih !== lastH) {

            canvas.width = w * pRatio * sRatio;

            canvas.height = h * pRatio * sRatio;

            canvas.style.width = dom_overlay_container.style.width = anim_container.style.width = w * sRatio + "px";

            canvas.style.height = anim_container.style.height = dom_overlay_container.style.height = h * sRatio + "px";

            stage.scaleX = pRatio * sRatio;

            stage.scaleY = pRatio * sRatio;

            stage.update();

        }

        lastW = iw; lastH = ih; lastS = sRatio;

    }

}

This makes three major tweaks to Adobe's code.

  1. It pipes the window resize event through requestAnimationFrame instead of calling resizeCanvas directly. This ensures the resize code isn't executed more often than once per window redraw.
  2. It only resizes the canvas when its size has actually changed, eliminating needless redraws.
  3. When the canvas is resized, it tells CreateJS to immediately redraw the stage, minimizing flicker.

Tested in desktop IE11, Firefox, and Chrome. Seems to work okay.

1 reply

Legend
July 28, 2017

If you think forcing EVERY user to download a 20 megabyte animated GiF is preferable to some flicker for a few people, your priorities are very much misplaced. Especially on mobile devices, where data is often limited.

I will agree though that this could use fixing.

Incidentally, it's generally agreed by usability experts that constant peripheral animations are bad design, because they distract the eye from whatever the user is actually trying to concentrate on.

Animation for Attention and Comprehension

Corryt32Author
Participant
July 28, 2017

Thanks for the feedback. Being a graphic and web designer, I'm just quite picky with how the logo was flickering.

There is one more issue I should note.  I produced the animation at 2 x the intended size, then scaled it down on the website, because I thought retina devices needed images 2x for them to be clear. However on normal screens, when the browser is resized smaller, and hence the logo becomes smaller, the HTML animation became very unclear, almost like the sharpness was set at 500%.

In regards to your comment about animations being "bad design" - my client wanted part of the logo to animate, and you'll see on the site, it's not too distracting at all. That's the animated logo GIF on the website: http://www.covadis.online/wordpress - I used 3G on my smartphone and the page seemed to load at a good speed - if you found that it loaded very slow, please let me know. 

Also if you find a solution to fixing the flickering please let me know, otherwise hopefully it's fixed in the next update.

ClayUUIDCorrect answer
Legend
July 28, 2017

Anyway, I've discovered the source of the problem. When you resize the browser window, a function in the HTML that Animate publishes gets called. This function always sets the width and height attribute of the canvas element, even when it hasn't changed. But surprise, setting the width or height of an element makes browsers consider that element to have been resized, even when the size hasn't changed. This wouldn't be a problem, except that resizing a canvas element clears its contents. So the canvas content disappears until CreateJS's next scheduled redraw. It's a perfect storm of unintuitive behaviors.

Here's my suggested fix. In the HTML that Animate publishes, there's a function called makeResponsive. It starts after the line "//Code to support hidpi screens and responsive scaling." and ends right before "makeResponsive(true, "both", false, 1);" (or similar). Replace that function definition with this code:

function makeResponsive(isResp, respDim, isScale, scaleType) {

    var lastW, lastH, lastS = 1;

    window.addEventListener("resize", window.requestAnimationFrame ? resizeCanvasReq : resizeCanvas);

    resizeCanvas();

    function resizeCanvasReq() {

        window.requestAnimationFrame(resizeCanvas);

    }

    function resizeCanvas() {

        var w = lib.properties.width, h = lib.properties.height;

        var iw = window.innerWidth, ih = window.innerHeight;

        var pRatio = window.devicePixelRatio || 1, xRatio = iw / w, yRatio = ih / h, sRatio = 1;

        if (isResp) {

            if ((respDim === "width" && lastW === iw) || (respDim === "height" && lastH === ih)) {

                sRatio = lastS;

            }

            else if (!isScale) {

                if (iw < w || ih < h) {

                    sRatio = Math.min(xRatio, yRatio);

                }

            }

            else if (scaleType === 1) {

                sRatio = Math.min(xRatio, yRatio);

            }

            else if (scaleType === 2) {

                sRatio = Math.max(xRatio, yRatio);

            }

        }

        if (iw !== lastW || ih !== lastH) {

            canvas.width = w * pRatio * sRatio;

            canvas.height = h * pRatio * sRatio;

            canvas.style.width = dom_overlay_container.style.width = anim_container.style.width = w * sRatio + "px";

            canvas.style.height = anim_container.style.height = dom_overlay_container.style.height = h * sRatio + "px";

            stage.scaleX = pRatio * sRatio;

            stage.scaleY = pRatio * sRatio;

            stage.update();

        }

        lastW = iw; lastH = ih; lastS = sRatio;

    }

}

This makes three major tweaks to Adobe's code.

  1. It pipes the window resize event through requestAnimationFrame instead of calling resizeCanvas directly. This ensures the resize code isn't executed more often than once per window redraw.
  2. It only resizes the canvas when its size has actually changed, eliminating needless redraws.
  3. When the canvas is resized, it tells CreateJS to immediately redraw the stage, minimizing flicker.

Tested in desktop IE11, Firefox, and Chrome. Seems to work okay.