Skip to content

手機上點開「選片理由與自我檢核」,影片被壓成 206×116,且頁面無法捲動 #5

Description

@fringmin

環境

main @ 0c327f7courses/gym(未改動任何資料),
Chromium 141.0.7390.37 headless,390×844(iPhone 尺寸)。

現象

手機寬度下進入上課頁,點開影片下方的 <details>「選片理由與自我檢核」,
影片立刻縮成一小塊、播放清單同時被擠掉,而且頁面不能捲動
沒有任何方法把影片變回正常大小,只能再把 <details> 收合。

重現與實測

  1. COURSE=courses/gym make build
  2. 390×844 開 dist/gym/index.html?tab=player&play=324
    (CH9「什麼是動力鏈?如何增加殺球能力?」,whyassessment 合計 425 字,
    是 gym 裡最長的一個;44 個主課全部都有 why,中位數合計 296 字)
  3. 點一下 summary「選片理由與自我檢核」
狀態 影片尺寸 資訊區高度 清單高度 頁面可捲動
收合(預設) 366×206 162px 279px false
展開(點一下) 206×116 624px 107px false

390px 寬的手機上影片只剩 206px 寬,左右各空掉 92px,比一半還小;
播放清單從 279px 掉到 107px。window.scrollTo(0, 99999) 之後 scrollY 仍然是 0,
scrollHeight === innerHeight,捲不動。

資訊區再長一點(我的 fork 在影片頁多放了講者資歷、查核日期、字幕提示,實測到 1111px),
就會有 553px 的內容直接被 overflow: hidden 裁掉,同樣捲不到。
所以在原版是「影片被壓扁」,資訊欄位更多的課程會惡化成「內容根本看不到」。

根因

三個地方各自成立,湊在一起才壞:

1. .Player 在窄螢幕仍然是固定視窗高+裁切

player.css:6-15height: calc(100dvh - var(--stick-top))overflow: hidden
player.css:322-327 的窄螢幕區塊裡沒有被解除,只換成上下堆疊。
上下堆疊之後總內容高度會超過一個視窗,但容器仍然不許它長高、也不許捲。

2. fitFrame() 用「舞台高 − 資訊區高」搶剩餘空間player.js:185-197

左右並排時這個算法是對的(資訊區在影片下方、共用一欄高度);
上下堆疊時它會讓影片與資訊區互相爭高度,資訊區越長影片越小。
另外 if (avail <= 0) return; 會保留上一次算出來的 --frame-w
所以資訊區長到一定程度之後影片尺寸就凍在殘值上,看起來像是「有時候又會好」,
實際上只是沒有重算。

watchFrame() 的 ResizeObserver 有 ro.observe(info),所以 <details> 一展開
就即時重算 fitFrame()——壓扁是當下發生的,因果很直接。

3. scrollIntoView 連文件一起捲app.js:303

$(".PlaylistItem.is-playing")?.scrollIntoView({ block: "nearest" })
目前頁面不能捲所以看不出來;一旦照下面讓頁面可捲,進上課頁的瞬間影片會被推出畫面外。
修 1 之前不會顯現、修 1 之後一定顯現,所以一起提。

我的修法

/* player.css,@media (max-width: 1012px) 內 */
.Player {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto;
  height: auto;
  min-height: calc(100dvh - var(--stick-top));
  overflow: visible;
}
.Player__list { height: 70dvh; min-height: 200px; }
// player.js,fitFrame() 開頭
// 窄螢幕是上下堆疊、整頁可捲:影片按寬度定高就好,不跟資訊區搶高度
if (matchMedia("(max-width: 1012px)").matches) {
  frame.style.setProperty("--frame-w", `${stage.clientWidth}px`);
  return;
}
// app.js,playAt() 內,取代 scrollIntoView
const playing = $(".PlaylistItem.is-playing");
const listBox = $("#playlist");
if (playing && listBox) {
  const er = playing.getBoundingClientRect();
  const sr = listBox.getBoundingClientRect();
  listBox.scrollTop += er.top - sr.top - (listBox.clientHeight - er.height) / 2;
}

我的 fork 上驗過:390×844 影片完整 16:9、載入停在頁頂、整頁可捲;
1280×900 桌面行為不變(影片 465px、清單滿高、整頁不捲)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions