雜記 › 生活隨筆 › 字帖每頁放幾個字:預設 A4 是 20 個,不是 100÷4=25

字帖每頁放幾個字:預設 A4 是 20 個,不是 100÷4=25

幫一年級的孩子印一張字帖,狀態列寫著「每頁 10 行 · 每行 10 格」,那就是 100 個格子;一個「範字 + 描紅 + 2 空格」要吃 4 格,100 ÷ 4 = 25,我敲了 25 個字,列印出來卻是兩張紙,第二頁掛著 5 個字:預設的 A4 每頁只有 20 個字,而不是 100 ÷ 4 得到的 25 個。重現過裝箱程式碼才明白,它用的不是這道除法。

每頁字數 = floor(每行格數 ÷ 組寬) × 每頁行數

711–734 行的裝箱一組一組往當前行裡塞,「再塞一組就超過每行格數」(717 行)就整組另起一行:組不跨行,行末餘格作廢。

預設版式(A4 縱向、格寬 16mm、邊距 10mm、開拼音、每頁資訊欄)實測 cols=10、rowsPerPage=10,mtb 的組寬是 4,floor(10 ÷ 4) × 10 = 20,每行 2 組、餘 2 格;差的 5 組正是每行 2 格 × 10 行 = 20 個排不進內容的格子位。兒童練字字帖生成 的說明區寫的就是這道除法。

換 pattern 就是換組寬

格寬 12mm 配「窄」邊距 6mm 把每行頂到 14 格、每頁頂到 13 行,A5 同參數只剩 7 格 7 行;這五組在 Node 與 headless Chrome 上各跑一遍完全一致。

版式每行格數每頁行數每行組數 / 餘格每頁字數
A4 預設 mtb10102 組 / 餘 220
A4 預設 mb10103 組 / 餘 130
A4 預設 m(整行範字)101010 組 / 餘 0100
A4 格寬 12mm + 邊距 6mm14133 組 / 餘 239
A5 預設參數 mtb771 組 / 餘 37

關拼音只動行數

拼音那一橫帶高 = 格寬 × 0.4,16mm 即 6.4mm(662、671–672 行):關掉它每頁 13 行、26 個字,資訊欄改「不顯示」是 11 行、22 個字,兩個都關 14 行、28 個字。狀態列(1067–1069 行)原文「每頁 10 行 · 每行 10 格 · 格寬 16 mm · 練習位 44」,不說每頁幾個字。

三條上限各管一件事

600 數的是非空白字元(742–744 行):600 個字夾空格時原始長度已達 1,199 仍不截,640 個字(raw 1,279)才觸發「內容超過 600 個字,已截斷。」(1075 行)。

40 頁是一筆行預算,maxRows = rowsPerPage × 40(759–761 行):預設版式預算 400 行,600 個字只排到 300 行,「已達到 40 頁上限」在預設版式永遠印不出來。

組寬大於每行格數是第三條路:A5 + 格寬 30mm + 寬邊距 15mm → cols=3、rows=3,716 行的 slice(0, cols) 把組尾 1 個空格砍了,11 個字排 11 行 4 頁;提示前半句是「每行只放得下 3 格,裝不下『 4 格一組』,超出的空格已丟棄。」

讓 40 頁那條提示可達

A5 + 格寬 20mm + mtb:rowsPerPage 5、maxRows 200。201 個字開始提示並丟 1 個,600 個字被 slice 到 200 行、一次丟 400 個,而 pageCount 仍是 40,被丟掉的行不在預覽裡。

0 0 1 50 400 199 字 200 字 201 字 250 字 600 字 被丟掉的字數 行預算 200

圖 1:輸入長度對著行預算 200 的丟字量。

#py: 那一格認什麼、不認什麼

頁面提示(73 行)讓另起一行寫 #py: yin1 yue4,落不落得進格子取決於 586 行的守衛 /^[a-z]+[0-9]$/:

  • 純 ASCII 音節加數字聲調才轉:tian1 → tiān、lve4 → lüè;
  • 帶調字母原樣用,全形冒號 #py:、#PY: 和帶序號的寫法都認;
  • 混寫不轉,數字留在格子裡印出來:lüe4、yuè4、TIAN1。

直調 applyToneMarks 傳 lüe4 只剩 è(377 行的正則不收 ü),但 586 行把它擋在介面外,頁面上只是殘留數字。

拼音表 2,639 個鍵,44 個重複

Object.keys(PINYIN_MAP).length 是 2,639:303–350 行字面寫了 2,676 條、44 個鍵重複(去重剩 2,632),353–359 行補錄 7 個漏掉的高頻字(粒 得 區 我 為 而 西)。後寫蓋先寫,9 個取值相同沒有副作用,35 個兩讀不同的留下常常不是常用音——了 → liǎo(le0 寫在 325 行前面)、阿 → ē、省 → xǐng。核對讀音可先用 漢字轉拼音 轉一遍,兩邊是同一份表。

空格不分組,標點和數字都佔格

漢字模式下 567–578 行把空白全部丟棄,天 地、天地、換行、製表符四種輸入等價——「不佔格子」對,「用來分組」不成立。只有拼音和數字那條分支按空白分組(605–614 行,609 行連製表符都不算):ni hao 是 2 個 unit、nihao 是 1 個。快捷字表「詞語練習」那串 朋友 同学 … 因此排成 21 個連排單字。

標點和數字一格一個:123 456 是 6 個 unit,「靜夜思」的 , 。 也各佔一格。沒收錄的不猜:魃鑫龘弼黉 5 個字留空並計入 miss 提示(1081 行),^丨丶 這類字元也計 miss(實測 2)。

整行範字後面的空格不另起行

mrow 的 hint 說空格數就是空臨行數,但 696–709 行是把 b 份「與內容等長的空格串」接在範字流尾巴上再連續裝箱。預設 10 列下 11 字配空格數 1,行內是 MMMMMMMMMM / M········· / ··(空格數 8 時總格數 99 = 11×9)。

匯出體積與 PDF 裡裝了什麼

A4 單頁 11 個字實測:JPEG 514,478 B、PNG 950,158 B(1.85 倍)、工具自寫的 PDF 515,288 B,容器 810 B。PDF 每頁是一張點陣圖:內容流只有 36 字元的 q … cm /ImN Do Q、沒有文字操作符(1450、1454 行)。匯出按 12 px/mm=305dpi,直接列印是 8 px/mm≈203dpi,超過 15 頁降到 6 px/mm≈152dpi(470–472、1255 行)。

把頁面文案逐條對回程式碼

config/tools.php 裡 2205–2209 行那段說明對著當前模板重現,是 33 條 = 28 條 [一致] / 5 條 [衝突]:寫死的 2639、每頁 20 / 30 / 100 / 39、關拼音 13 行、A5 的 7×7×1、305 / 203 / 152dpi 全部命中;剩下 5 條都是口徑級,把「按空白分組」「常用音」「都認」「40 頁」「空臨行數」說得太滿。拼音資料的另一面見站內那篇 漢字加拼音注音。

三個容易踩的坑

Q1:把格距調到 0 多出一列,能多放一組嗎?

不能。實測格距 0 時 cols 變 11,11 ÷ 4 仍取 2,每頁還是 20 個字。

Q2:600 個字是從哪一段開始被丟的?

提示只說「已截斷」(1075 行),不報起始位置,被丟的行也不在預覽裡。

Q3:不心算能不能知道一頁放幾個字?

頁面上給不出,只能導一版數末頁:預設每頁 20 個字,25 個字就分兩頁;排長文換 mb(每頁 30 個字)。

📎 相關文章

同一天既是週末又被登記成補班,工作日計算器聽誰的 2026-10-27 倒數計時裡的 86400 秒一天,碰上夏令時間會少給你 1 天 2026-10-27 世界時間的偏移是誰給的:一條正則,和一個沒有夏令時間的寫死小時數 2026-10-27 同一次計算給出兩個體脂率:預設一組差 6.1 個百分點,腰圍 1 cm 值 0.7 2026-10-26 照片轉了 90°,換一部裝置方向又回來了:EXIF 標記與真實旋轉的分工 2026-10-22