Pretext – ไลบรารีเลย์เอาต์ JavaScript ล้วนสำหรับวัดความสูงข้อความโดยไม่ต้องใช้ DOM
(github.com/chenglou)การรู้ว่าข้อความหนึ่งกินพื้นที่กี่บรรทัดในเบราว์เซอร์นั้นยากกว่าที่คิด โดยปกติจะใช้ getBoundingClientRect หรือ offsetHeight แต่วิธีเหล่านี้จะบังคับให้เบราว์เซอร์คำนวณเลย์เอาต์ใหม่อีกครั้ง หรือที่เรียกว่า layout reflow ซึ่งเป็นงานที่ค่อนข้างหนักสำหรับเบราว์เซอร์
Pretext แก้ปัญหานี้ด้วยแนวทางที่ต่างออกไป โดยใช้ measureText() ของ Canvas เพื่อดึงความกว้างของตัวอักษรจากฟอนต์เอนจินโดยตรง จากนั้นการคำนวณบรรทัดจะทำด้วยค่าความกว้างที่แคชไว้และใช้เพียงการคำนวณเชิงคณิตศาสตร์ล้วน ๆ โดยไม่แตะ DOM เลยแม้แต่น้อย
const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')
const { height, lineCount } = layout(prepared, textWidth, 20)
ประสิทธิภาพก็น่าประทับใจเช่นกัน สำหรับการจัดวางข้อความ 500 ชุด prepare() ใช้เวลาประมาณ 19ms และหลังจากนั้น layout() อยู่ที่ระดับ 0.09ms
มีวิธีใช้งานอยู่ 2 แบบ
ถ้าต้องการแค่ความสูง การใช้ prepare() + layout() ก็เพียงพอแล้ว สามารถนำไปใช้กับการทำ virtualized list, การคงตำแหน่งการเลื่อน, หรือใช้ตรวจสอบว่าข้อความที่ AI สร้างขึ้นล้นออกนอกปุ่มหรือไม่
หากต้องการควบคุมเลย์เอาต์ในระดับบรรทัดด้วยตัวเอง ก็สามารถใช้ API อย่าง layoutWithLines(), walkLineRanges(), layoutNextLine() ได้ โดยนำไปผูกกับ Canvas, SVG, WebGL, หรือ server-side rendering ก็ได้ และยังรองรับเลย์เอาต์ที่ความกว้างแต่ละบรรทัดไม่เท่ากัน เช่น รูปแบบที่ข้อความไหลอ้อมภาพ
รองรับอีโมจิ ภาษาจีน ญี่ปุ่น เกาหลี รวมถึงภาษาอาหรับและข้อความแบบสองทิศทางด้วย เป็นโปรเจกต์ของ chenglou ผู้สร้าง React และ Relay ⭐ 7.1k
https://github.com/chenglou/pretext
3 ความคิดเห็น
ตรงลิงก์ github ด้านล่างสุดเหมือนมี
%E2%80%8B(zero-width space) ต่อท้ายอยู่หลายตัวนะครับjs
.replace(/\u200b/g, '')ดูเหมือนว่าหน้า https://chenglou.me/pretext/editorial-engine/ ที่อยู่ในเดโมจะแสดงให้เห็นได้ดีที่สุดนะ
ไม่ได้ใช้อย่างเข้าใจถ่องแท้นัก ต้องขออภัยไว้ล่วงหน้าด้วย
เห็นว่ามันคำนวณใหม่โดยอิงจาก
measureTextของ canvas แต่...ผมไม่ค่อยไว้ใจ API นั้นเท่าไร
พูดให้ตรงกว่านั้นไม่ใช่ว่าไม่ไว้ใจตัว API เอง
แต่เวลาจะเรนเดอร์ DOM แบบเดียวกัน ต้องทำให้ค่าเงื่อนไขต่าง ๆ ตรงกันอย่างสมบูรณ์ ถึงจะได้
ความสูงหรือรูปทรงที่เห็นในเบราว์เซอร์เหมือนกับตอนดึงออกมาในรูปแบบ API
เคยมีฝันร้ายชวนสะพรึงอยู่ครั้งหนึ่งที่ไม่ทันตระหนักถึงจุดนี้ แล้วสงสัยว่าทำไมค่าถึงไม่ตรงและบั๊กถึงเกิดขึ้น...