The Deep Dive
A6 → A4 Label Printer
เครื่องมือจัดป้าย A6 ลงกระดาษ A4 แผ่นละ 4 ใบ ทำงานจากไฟล์ HTML ไฟล์เดียว ไม่ต้องติดตั้ง ไม่ต้องต่อเน็ต
- Year
- 2026
- Category
- Code
- Tags
- React, PDF, Print, Offline-first, Tooling

Context
เครื่องมือจัดป้ายขนาด A6 ลงกระดาษ A4 แผ่นละ 4 ใบ หรือ N-up ขนาดใดก็ได้ พร้อมพรีวิว WYSIWYG หน่วยมิลลิเมตร
เป็นไฟล์ HTML ไฟล์เดียว ดาวน์โหลดแล้วดับเบิลคลิกเปิดในเบราว์เซอร์ได้เลย ไม่ต้องติดตั้ง ไม่ต้องต่ออินเทอร์เน็ต
Problem
ป้ายที่พิมพ์ออกมาผิดขนาดมีสาเหตุอันดับหนึ่งอยู่ที่การตั้งค่าในกล่องพิมพ์ของเบราว์เซอร์ — ตัวเลือก Fit to printable area ย่องานลงประมาณ 96% และระยะขอบที่ไม่ได้ตั้งเป็น None จะซ้อนกับระยะขอบที่ตั้งไว้ในแอปแล้ว
Role
ออกแบบและพัฒนาทั้งหมด
Process
งานจัดหน้าเริ่มจากคิวเดียว — อัปโหลด PDF หรือรูปได้หลายไฟล์พร้อมกัน ทุกหน้าไหลลงคิวเดียวแล้วจัด N-up ต่อเนื่องข้ามไฟล์ ลากสลับลำดับ หมุน 90 องศารายหน้า ลบรายหน้าหรือรายไฟล์ กำหนดจำนวนสำเนาต่อป้าย เลือกหน้าพิมพ์ด้วย 1,3-5 หรือ 4- และเติมช่องว่างแผ่นสุดท้ายอัตโนมัติ
รองรับกระดาษ A4 A5 A3 Letter Legal และกำหนดเอง ขนาดป้ายเป็นมิลลิเมตร คอลัมน์คูณแถวถึง 12×12 พร้อมปุ่มคำนวณอัตโนมัติ โหมดจัดวางรูปมีพอดีกรอบ เต็มกรอบครอป และยืดเต็มกรอบ
ซอร์สแยกจากไฟล์ที่ใช้จริง — แก้ที่ src/index.src.html ซึ่งโหลดไลบรารีจาก CDN และคอมไพล์ JSX ตอนรัน แล้ว build เป็น dist/index.html ที่ฝังทุกอย่างไว้และทำงานออฟไลน์
Design Decisions
พรีวิวใช้หน่วยมิลลิเมตรจริง ตรงกับเอกสารที่ส่งเข้าเครื่องพิมพ์
หน้าสอบเทียบพิมพ์กรอบ 100×100 มิลลิเมตรจริงออกมาให้วัด แล้วกรอกค่าที่วัดได้กลับเข้าไปเพื่อชดเชย scale และ offset ของเครื่องพิมพ์
เช็คลิสต์ก่อนพิมพ์เตือน Scale = 100% (ไม่ใช่ Fit to printable area) และ Margins = None ซึ่งเป็นสาเหตุอันดับหนึ่งที่ป้ายพิมพ์ออกมาผิดขนาด
เตือนเมื่อหน้าไหนความละเอียดต่ำกว่า 200 DPI ที่ขนาดป้ายจริง หรือสัดส่วนไม่ตรงกรอบ
เส้นตัดเลือกได้ทั้งเส้นประและ crop mark มุมสำหรับเครื่องตัด พร้อมชดเชยขอบที่พิมพ์ไม่ได้ของเครื่องพิมพ์แยกต่อป้าย
Technical Decisions
React, pdf.js, jsPDF และฟอนต์ไทยถูกฝังอยู่ใน bundle ทั้งหมด ไม่มีการเรียกเน็ตแม้แต่ครั้งเดียว
พิมพ์ผ่าน hidden iframe เพื่อไม่ให้โดน popup blocker
Export PDF ขนาด A4 จริงด้วย jsPDF ซึ่งใช้รูปเดียวซ้ำได้ ไฟล์จึงเล็กกว่าการพิมพ์จาก HTML มาก เพราะเอกสาร HTML ฝังรูปซ้ำทุกใบ — เมื่องานพิมพ์ใหญ่มาก แอปจะเตือนและแนะนำให้ใช้ Export PDF แทน
จำงานไว้ใน IndexedDB ปิดเบราว์เซอร์แล้วกลับมาทำต่อได้ และบอกตรง ๆ เมื่อพื้นที่ไม่พอ
ลายน้ำข้อความรองรับภาษาไทยทั้งการพิมพ์และ Export PDF โดยฝังฟอนต์ Sarabun อัตโนมัติเมื่อพบอักษรไทย
Result
เทสต์ 44 ข้อครอบคลุมเรขาคณิต N-up เส้นตัด crop mark คิวพิมพ์ การสอบเทียบ และ guard ขนาดไฟล์
e2e อีก 21 ข้อเปิด dist/index.html จาก file:// ใน Chromium จริง พร้อมบล็อกทุก request ที่เป็น http/https จึงพิสูจน์ทั้งความถูกต้องของขนาดและความเป็นออฟไลน์ไปพร้อมกัน ตรวจถึงขั้นดาวน์โหลด PDF ออกมาอ่าน /MediaBox ว่าเป็น A4 จริง และวัดว่ากรอบป้ายในเอกสารพิมพ์กว้าง 101 mm สูง 144 mm
Reflection
สาเหตุอันดับหนึ่งที่ป้ายพิมพ์ออกมาผิดขนาดคือการตั้งค่าในกล่องพิมพ์ เครื่องมือจึงต้องเตือนเรื่อง Scale และ Margins และมีหน้าสอบเทียบไว้ให้วัดกลับ
ความเป็นออฟไลน์เป็นสิ่งที่พิสูจน์ได้ ไม่ใช่แค่คำอ้าง — เทสต์ที่บล็อกทุก request แล้วยืนยันว่าแอปยังทำงานครบคือหลักฐานนั้น
การเป็นไฟล์เดียวมีราคาที่ต้องจ่าย: หน้าที่เปิดจาก file:// สร้าง Web Worker ไม่ได้ pdf.js จึงต้องทำงานบน main thread และไฟล์ใหญ่จะเรนเดอร์ช้ากว่าเปิดผ่านเว็บเซิร์ฟเวอร์ ส่วน jsPDF ไม่ทำ text shaping สระและวรรณยุกต์ไทยในลายน้ำของไฟล์ PDF จึงอาจวางตำแหน่งไม่สวยเท่าการพิมพ์ผ่านเบราว์เซอร์
Context
เครื่องมือจัดป้ายขนาด A6 ลงกระดาษ A4 แผ่นละ 4 ใบ หรือ N-up ขนาดใดก็ได้ พร้อมพรีวิว WYSIWYG หน่วยมิลลิเมตร
เป็นไฟล์ HTML ไฟล์เดียว ดาวน์โหลดแล้วดับเบิลคลิกเปิดในเบราว์เซอร์ได้เลย ไม่ต้องติดตั้ง ไม่ต้องต่ออินเทอร์เน็ต
Problem
ป้ายที่พิมพ์ออกมาผิดขนาดมีสาเหตุอันดับหนึ่งอยู่ที่การตั้งค่าในกล่องพิมพ์ของเบราว์เซอร์ — ตัวเลือก Fit to printable area ย่องานลงประมาณ 96% และระยะขอบที่ไม่ได้ตั้งเป็น None จะซ้อนกับระยะขอบที่ตั้งไว้ในแอปแล้ว
Role
ออกแบบและพัฒนาทั้งหมด
Process
งานจัดหน้าเริ่มจากคิวเดียว — อัปโหลด PDF หรือรูปได้หลายไฟล์พร้อมกัน ทุกหน้าไหลลงคิวเดียวแล้วจัด N-up ต่อเนื่องข้ามไฟล์ ลากสลับลำดับ หมุน 90 องศารายหน้า ลบรายหน้าหรือรายไฟล์ กำหนดจำนวนสำเนาต่อป้าย เลือกหน้าพิมพ์ด้วย 1,3-5 หรือ 4- และเติมช่องว่างแผ่นสุดท้ายอัตโนมัติ
รองรับกระดาษ A4 A5 A3 Letter Legal และกำหนดเอง ขนาดป้ายเป็นมิลลิเมตร คอลัมน์คูณแถวถึง 12×12 พร้อมปุ่มคำนวณอัตโนมัติ โหมดจัดวางรูปมีพอดีกรอบ เต็มกรอบครอป และยืดเต็มกรอบ
ซอร์สแยกจากไฟล์ที่ใช้จริง — แก้ที่ src/index.src.html ซึ่งโหลดไลบรารีจาก CDN และคอมไพล์ JSX ตอนรัน แล้ว build เป็น dist/index.html ที่ฝังทุกอย่างไว้และทำงานออฟไลน์
Design Decisions
พรีวิวใช้หน่วยมิลลิเมตรจริง ตรงกับเอกสารที่ส่งเข้าเครื่องพิมพ์
หน้าสอบเทียบพิมพ์กรอบ 100×100 มิลลิเมตรจริงออกมาให้วัด แล้วกรอกค่าที่วัดได้กลับเข้าไปเพื่อชดเชย scale และ offset ของเครื่องพิมพ์
เช็คลิสต์ก่อนพิมพ์เตือน Scale = 100% (ไม่ใช่ Fit to printable area) และ Margins = None ซึ่งเป็นสาเหตุอันดับหนึ่งที่ป้ายพิมพ์ออกมาผิดขนาด
เตือนเมื่อหน้าไหนความละเอียดต่ำกว่า 200 DPI ที่ขนาดป้ายจริง หรือสัดส่วนไม่ตรงกรอบ
เส้นตัดเลือกได้ทั้งเส้นประและ crop mark มุมสำหรับเครื่องตัด พร้อมชดเชยขอบที่พิมพ์ไม่ได้ของเครื่องพิมพ์แยกต่อป้าย
Technical Decisions
React, pdf.js, jsPDF และฟอนต์ไทยถูกฝังอยู่ใน bundle ทั้งหมด ไม่มีการเรียกเน็ตแม้แต่ครั้งเดียว
พิมพ์ผ่าน hidden iframe เพื่อไม่ให้โดน popup blocker
Export PDF ขนาด A4 จริงด้วย jsPDF ซึ่งใช้รูปเดียวซ้ำได้ ไฟล์จึงเล็กกว่าการพิมพ์จาก HTML มาก เพราะเอกสาร HTML ฝังรูปซ้ำทุกใบ — เมื่องานพิมพ์ใหญ่มาก แอปจะเตือนและแนะนำให้ใช้ Export PDF แทน
จำงานไว้ใน IndexedDB ปิดเบราว์เซอร์แล้วกลับมาทำต่อได้ และบอกตรง ๆ เมื่อพื้นที่ไม่พอ
ลายน้ำข้อความรองรับภาษาไทยทั้งการพิมพ์และ Export PDF โดยฝังฟอนต์ Sarabun อัตโนมัติเมื่อพบอักษรไทย
Result
เทสต์ 44 ข้อครอบคลุมเรขาคณิต N-up เส้นตัด crop mark คิวพิมพ์ การสอบเทียบ และ guard ขนาดไฟล์
e2e อีก 21 ข้อเปิด dist/index.html จาก file:// ใน Chromium จริง พร้อมบล็อกทุก request ที่เป็น http/https จึงพิสูจน์ทั้งความถูกต้องของขนาดและความเป็นออฟไลน์ไปพร้อมกัน ตรวจถึงขั้นดาวน์โหลด PDF ออกมาอ่าน /MediaBox ว่าเป็น A4 จริง และวัดว่ากรอบป้ายในเอกสารพิมพ์กว้าง 101 mm สูง 144 mm
Reflection
สาเหตุอันดับหนึ่งที่ป้ายพิมพ์ออกมาผิดขนาดคือการตั้งค่าในกล่องพิมพ์ เครื่องมือจึงต้องเตือนเรื่อง Scale และ Margins และมีหน้าสอบเทียบไว้ให้วัดกลับ
ความเป็นออฟไลน์เป็นสิ่งที่พิสูจน์ได้ ไม่ใช่แค่คำอ้าง — เทสต์ที่บล็อกทุก request แล้วยืนยันว่าแอปยังทำงานครบคือหลักฐานนั้น
การเป็นไฟล์เดียวมีราคาที่ต้องจ่าย: หน้าที่เปิดจาก file:// สร้าง Web Worker ไม่ได้ pdf.js จึงต้องทำงานบน main thread และไฟล์ใหญ่จะเรนเดอร์ช้ากว่าเปิดผ่านเว็บเซิร์ฟเวอร์ ส่วน jsPDF ไม่ทำ text shaping สระและวรรณยุกต์ไทยในลายน้ำของไฟล์ PDF จึงอาจวางตำแหน่งไม่สวยเท่าการพิมพ์ผ่านเบราว์เซอร์
No code snippets in this project