From e45343cc238c87b789fd25a71db48659519f9e72 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 29 Dec 2022 19:18:13 +0100 Subject: [PATCH] Yet more transition tweaks. First, put them all into one big rAF now (this requires some inlining, but they are so small that it's really fine). Second, add a backup timeout so that we should never really see ghost pieces remaining. --- www/js/chessboard-0.3.0.js | 123 +++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 67 deletions(-) diff --git a/www/js/chessboard-0.3.0.js b/www/js/chessboard-0.3.0.js index b58c589..412df02 100644 --- a/www/js/chessboard-0.3.0.js +++ b/www/js/chessboard-0.3.0.js @@ -550,57 +550,6 @@ function findSquarePosition(square) { }; } -function animateSquareToSquare(move_pieces, complete) { - for (const [piece, destination] of move_pieces) { - // Move it to the end of the stack, which changes the implicit z-index - // so that it will go on top of any pieces it's replacing. - piece.remove(); - boardEl.appendChild(piece); - - // animate the piece to the destination square - piece.addEventListener('transitionend', complete, {once: true}); - } - requestAnimationFrame(() => { - for (const [piece, destination] of move_pieces) { - let destSquarePosition = findSquarePosition(destination); - piece.style.transitionProperty = 'top, left'; - piece.style.transitionDuration = cfg.moveSpeed + 'ms'; - piece.style.top = destSquarePosition.top; - piece.style.left = destSquarePosition.left; - } - }); -} - -function fadeIn(pieces, onFinish) { - pieces.forEach((piece) => { - piece.style.opacity = 0; - piece.style.display = null; - piece.addEventListener('transitionend', onFinish, {once: true}); - }); - requestAnimationFrame(() => { - pieces.forEach((piece) => { - piece.style.transitionProperty = 'opacity'; - piece.style.transitionDuration = cfg.appearSpeed + 'ms'; - piece.style.opacity = 1; - }); - }); -} - -function fadeOut(pieces, onFinish) { - pieces.forEach((piece) => { - piece.style.opacity = 1; - piece.style.display = null; - piece.addEventListener('transitionend', onFinish, {once: true}); - }); - requestAnimationFrame(() => { - pieces.forEach((piece) => { - piece.style.transitionProperty = 'opacity'; - piece.style.transitionDuration = cfg.trashSpeed + 'ms'; - piece.style.opacity = 0; - }); - }); -} - // execute an array of animations function doAnimations(a, oldPos, newPos) { let fadeout_pieces = []; @@ -658,16 +607,23 @@ function doAnimations(a, oldPos, newPos) { } var numFinished = 0; - function onFinish(e) { + function onFinish(e, opt_force) { if (e && e.target) { e.target.transitionProperty = null; e.target.transitionDuration = null; } - numFinished++; - - // exit if all the animations aren't finished - if (numFinished !== a.length) return; + if (opt_force) { + // For whatever reason, the transition didn't seem to actually run + // (and thus, we didn't get an end event). Finish off now. + // (In particular, this seems to happen in Chrome if the tab is + // hidden and left alone for a while.) + if (numFinished == a.length) return; + numFinished = a.length; // Make sure a very delayed later event will be ignored. + } else { + numFinished++; + if (numFinished !== a.length) return; + } for (let piece of removed_pieces) { piece.remove(); @@ -680,17 +636,50 @@ function doAnimations(a, oldPos, newPos) { } } - requestAnimationFrame(() => { // Firefox workaround. - if (fadeout_pieces.length > 0) { - fadeOut(fadeout_pieces, onFinish); - } - if (fadein_pieces.length > 0) { - fadeIn(fadein_pieces, onFinish); - } - if (move_pieces.length > 0) { - animateSquareToSquare(move_pieces, onFinish); - } - }); + if (fadeout_pieces.length == 0 || fadein_pieces.length > 0 || move_pieces.length > 0) { + requestAnimationFrame(() => { // Firefox workaround. + // Backup in case the transition never runs. + setTimeout(() => onFinish(null, true), + cfg.appearSpeed + cfg.trashSpeed + cfg.moveSpeed + 100); + + fadein_pieces.forEach((piece) => { + piece.style.opacity = 0; + piece.style.display = null; + piece.addEventListener('transitionend', onFinish, {once: true}); + }); + fadeout_pieces.forEach((piece) => { + piece.style.opacity = 1; + piece.style.display = null; + piece.addEventListener('transitionend', onFinish, {once: true}); + }); + for (const [piece, destination] of move_pieces) { + // Move it to the end of the stack, which changes the implicit z-index + // so that it will go on top of any pieces it's replacing. + piece.remove(); + boardEl.appendChild(piece); + piece.addEventListener('transitionend', onFinish, {once: true}); + } + requestAnimationFrame(() => { + fadein_pieces.forEach((piece) => { + piece.style.transitionProperty = 'opacity'; + piece.style.transitionDuration = cfg.appearSpeed + 'ms'; + piece.style.opacity = 1; + }); + fadeout_pieces.forEach((piece) => { + piece.style.transitionProperty = 'opacity'; + piece.style.transitionDuration = cfg.trashSpeed + 'ms'; + piece.style.opacity = 0; + }); + for (const [piece, destination] of move_pieces) { + let destSquarePosition = findSquarePosition(destination); + piece.style.transitionProperty = 'top, left'; + piece.style.transitionDuration = cfg.moveSpeed + 'ms'; + piece.style.top = destSquarePosition.top; + piece.style.left = destSquarePosition.left; + } + }); + }); + } } // returns the distance between two squares -- 2.39.2