2025年12月19日 星期五

修正 iOS 10.3.4 CSS repeat function 的問題

2025年12月19日 星期五

前兩天在測試新遊戲 HTML5 FUN Make 10 時,發現在 iPad 4 的 iOS 10.3.4 居然不能玩!研究半天,找到讓程式卡住的地方是監聽畫面動態的「ResizeObserver」,iOS 10.3.4 不支援,只好多加幾行,讓它改用傳統監聽「resize」事件的方法。以為從此就可以過著幸福快樂的日子了嗎?

來看看 Make 10 正常的畫面應該像 [圖1] 這樣:

[圖1] 正常排列的 Make 10 按鈕

結果在 iOS 10.3.4 中是 [圖2] 這樣,全部疊成一排:

[圖2] iOS 10.3.4 中全部疊在一起

Make 10 中的數字方塊使用了 grid 來配置按鈕棋盤:

.board-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(6, 1fr);
  gap: 1%;
  width: 100%;
  height: 100%;
}

設計的是 8 x 6 的棋盤,在 iOS 10.3.4 中,8欄有正常分配了,6 排卻疊成一排。本來以為 iOS 10.3.4 不支援 repeat function,但實際用 getComputedStyle 取得 grid-template-rows 的值,它有執行 repeat(6, 1fr) ,只是回傳的值是「0px 0px 0px 0px 0px 0px」,分成六份了,但每一份都是 0px。

原來關鍵在 iOS 10.3.4 的 repeat 在計算寬度時,有正確解讀「width: 100%」,而在計算高度時,「height: 100%」使用了百分比,並沒有被正確解讀。如果換成別的單位,例如「height: 100vh」,就不會疊成一排了。

找到原因了,在 resize 的監聽程序中,加入程式計算高度即可,取得棋盤容器的總高,扣掉不能使用的空間,再將「height: 100%」最後用 px 的單位來設定。

不過,怎麼知道哪一個人用了像 iOS 10.3.4 這樣, repeat 有缺陷的瀏覽器呢?

本來是用前面提到的「0px 0px 0px 0px 0px 0px」,以按鈕的高度為 0 來判斷,但是這樣的方法只能在一進入遊戲時用,如果使用者旋轉了裝置或是讓視窗尺寸有所改變時,就無法再重新自動設定格子大小了。後來發現「gap: 1%;」這個也是個線索,因為 iOS 10.3.4 並不支援「gap」,所以用 getComputedStyle 取得的 gap 會是 undefined ,這個特性剛好可以用判斷是否為 iOS 10.3.4。

來看一下修改過後的畫面:

[圖3] 不使用 % 設定高度後的棋盤

套上修正方法後的 [圖3] ,和原始設計的 [圖1] 比較,可以看到 [圖3] 格子與格子沒有間隔,所以格線看不出來;不過修正過後,至少在 iOS 10.3.4 中可以玩 Make 10 了!

    ▋ 完美修正

    還是不能接受「gap: 1%;」沒被 iOS 10.3.4 處理到,那怎麼辦?

    把 1%  到底是多少算出來,然後將所有格子找出來設定它們的 width 和 height 為 calc(100% - gap) 就可以有 1% 的間隔了,底下是實作的程序:

    function gridRepeatFix() {
      const boardGrid = document.querySelector('.board-grid');
      if (boardGrid) {
        if (typeof getComputedStyle(boardGrid)['gap'] == 'undefined') {
          const style = getComputedStyle(boardGrid.parentElement);
          let height = parseFloat(style.height);
          height -= parseFloat(style.paddingTop);
          height -= parseFloat(style.paddingBottom);
          const gap = Math.floor(height * 0.01);
          boardGrid.style.height = Math.floor(height) + 'px';
          Array.from(boardGrid.children).forEach(cell => {
            cell.style.width = `calc(100% - ${gap}px)`;
            cell.style.height = `calc(100% - ${gap}px)`;
          });
        }
      }
    }


    ▋ 相關連結


    沒有留言:

    張貼留言

     
    雄::gsyan © 2009. Design by Pocket