]> git.sesse.net Git - remoteglot/blobdiff - www/js/chessboard-0.3.0.js
Batch fade-in/fade-out, for ~5 ms less FCP.
[remoteglot] / www / js / chessboard-0.3.0.js
index 451f1a9f4d17cf73ed93c0b52788ccfb2cda1577..cbd46f4f4f064f0ac67620b7bdd93c4842635af7 100644 (file)
@@ -641,23 +641,20 @@ function buildPieceImgSrc(piece) {
  * @param {!string=} id
  */
 function buildPiece(piece, hidden, id) {
-  var html = '<img src="' + buildPieceImgSrc(piece) + '" ';
+  let img = document.createElement('img');
+  img.src = buildPieceImgSrc(piece);
   if (id && typeof id === 'string') {
-    html += 'id="' + id + '" ';
+    img.setAttribute('id', id);
   }
-  html += 'alt="" ' +
-  'class="' + CSS.piece + '" ' +
-  'data-piece="' + piece + '" ' +
-  'style="width: ' + SQUARE_SIZE + 'px;' +
-  'height: ' + SQUARE_SIZE + 'px;';
+  img.setAttribute('alt', '');
+  img.classList.add(CSS.piece);
+  img.setAttribute('data-piece', piece);
+  img.style.width = SQUARE_SIZE + 'px';
+  img.style.height = SQUARE_SIZE + 'px';
   if (hidden === true) {
-    html += 'display:none;';
+    img.style.display = 'none';
   }
-  html += '" />';
-
-  let elem = document.createElement('template');
-  elem.innerHTML = html;
-  return elem.content;
+  return img;
 }
 
 function buildSparePieces(color) {
@@ -771,25 +768,33 @@ function animateSparePieceToSquare(piece, dest, completeFn) {
   //$(animatedPieceEl).animate(destOffset, opts);
 }
 
-function fadeIn(piece, onFinish) {
-  piece.style.opacity = 0;
-  piece.style.display = null;
-  piece.addEventListener('transitionend', onFinish, {once: true});
+function fadeIn(pieces, onFinish) {
+  pieces.forEach((piece) => {
+    piece.style.opacity = 0;
+    piece.style.display = null;
+    piece.addEventListener('transitionend', onFinish, {once: true});
+  });
   requestAnimationFrame(() => {
-    piece.style.transitionProperty = 'opacity';
-    piece.style.transitionDuration = cfg.appearSpeed + 'ms';
-    piece.style.opacity = 1;
+    pieces.forEach((piece) => {
+      piece.style.transitionProperty = 'opacity';
+      piece.style.transitionDuration = cfg.appearSpeed + 'ms';
+      piece.style.opacity = 1;
+    });
   });
 }
 
-function fadeOut(piece, onFinish) {
-  piece.style.opacity = 1;
-  piece.style.display = null;
-  piece.addEventListener('transitionend', onFinish, {once: true});
+function fadeOut(pieces, onFinish) {
+  pieces.forEach((piece) => {
+    piece.style.opacity = 1;
+    piece.style.display = null;
+    piece.addEventListener('transitionend', onFinish, {once: true});
+  });
   requestAnimationFrame(() => {
-    piece.style.transitionProperty = 'opacity';
-    piece.style.transitionDuration = cfg.trashSpeed + 'ms';
-    piece.style.opacity = 0;
+    pieces.forEach((piece) => {
+      piece.style.transitionProperty = 'opacity';
+      piece.style.transitionDuration = cfg.trashSpeed + 'ms';
+      piece.style.opacity = 0;
+    });
   });
 }
 
@@ -819,11 +824,14 @@ function doAnimations(a, oldPos, newPos) {
   }
 
   requestAnimationFrame(() => {  // Firefox workaround.
+    let fadeout_pieces = [];
+    let fadein_pieces = [];
+
     for (var i = 0; i < a.length; i++) {
       // clear a piece
       if (a[i].type === 'clear') {
         document.getElementById(SQUARE_ELS_IDS[a[i].square]).querySelectorAll('.' + CSS.piece).forEach(
-          (piece) => fadeOut(piece, onFinish)
+          (piece) => fadeout_pieces.push(piece)
         );
       }
 
@@ -832,7 +840,7 @@ function doAnimations(a, oldPos, newPos) {
         let square = document.getElementById(SQUARE_ELS_IDS[a[i].square]);
         square.append(buildPiece(a[i].piece, true));
         let piece = square.querySelector('.' + CSS.piece);
-        fadeIn(piece, onFinish);
+        fadein_pieces.push(piece);
       }
 
       // add a piece from a spare piece
@@ -846,6 +854,15 @@ function doAnimations(a, oldPos, newPos) {
           onFinish);
       }
     }
+
+    // TODO: Batch moves as well, not just fade in/out.
+    // (We batch them because requestAnimationFrame seemingly costs real time.)
+    if (fadeout_pieces.length > 0) {
+      fadeOut(fadeout_pieces, onFinish);
+    }
+    if (fadein_pieces.length > 0) {
+      fadeIn(fadein_pieces, onFinish);
+    }
   });
 }
 
@@ -1548,7 +1565,6 @@ function touchstartSquare(e) {
     return;
   }
 
-  e = e.originalEvent;
   beginDraggingPiece(square, CURRENT_POSITION[square],
     e.changedTouches[0].pageX, e.changedTouches[0].pageY);
 }
@@ -1576,7 +1592,6 @@ function touchstartSparePiece(e) {
 
   var piece = e.target.getAttribute('data-piece');
 
-  e = e.originalEvent;
   beginDraggingPiece('spare', piece,
     e.changedTouches[0].pageX, e.changedTouches[0].pageY);
 }
@@ -1595,8 +1610,8 @@ function touchmoveWindow(e) {
   // prevent screen from scrolling
   e.preventDefault();
 
-  updateDraggedPiece(e.originalEvent.changedTouches[0].pageX,
-    e.originalEvent.changedTouches[0].pageY);
+  updateDraggedPiece(e.changedTouches[0].pageX,
+    e.changedTouches[0].pageY);
 }
 
 function mouseupWindow(e) {
@@ -1614,8 +1629,8 @@ function touchendWindow(e) {
   if (DRAGGING_A_PIECE !== true) return;
 
   // get the location
-  var location = isXYOnSquare(e.originalEvent.changedTouches[0].pageX,
-    e.originalEvent.changedTouches[0].pageY);
+  var location = isXYOnSquare(e.changedTouches[0].pageX,
+    e.changedTouches[0].pageY);
 
   stopDraggedPiece(location);
 }