ฟอนต์ SVG ใน resvg: โหลดแบบอักษรที่ภาพต้องใช้
แก้ข้อความ SVG ที่หายหรือถูกแทนฟอนต์ใน resvg ด้วยไฟล์ฟอนต์ที่ระบุชัด รันตัวอย่าง Node เล็ก เปรียบเทียบสามผลลัพธ์ และเก็บไฟล์ภาพต้นฉบับที่แก้ไขได้
ในหน้านี้
หากต้องการเรนเดอร์ฟอนต์ SVG ด้วย resvg อย่างเชื่อถือได้ ให้ส่งไฟล์ฟอนต์ให้ตัวเรนเดอร์และใช้ชื่อตระกูลฟอนต์ใน SVG สำหรับ binding แบบ native ของ Node @resvg/resvg-js หมายถึงตั้ง fontFiles; ตั้ง loadSystemFonts: false เมื่อต้องการทดสอบว่างานได้รับฟอนต์ใดแน่นอน ตัวอย่าง Node ของโครงการสาธิตการตั้งค่านี้
PNG อาจดูครบแต่ใช้แบบอักษรผิด ตรวจรูปตัวอักษรแม้คำสั่งส่งออกสำเร็จ
ขาเข้าฟอนต์สามแบบ SVG เดียว
เราสร้างตราภูเขาเล็กจากพาธและวางข้อความ PINE & FIELD ที่ยังแก้ได้ข้างกัน SVG ขอฟอนต์ตระกูล Abel น้ำหนักปกติ เราเรนเดอร์ต้นทางเดียวกันสามครั้งด้วย @resvg/resvg-js 2.6.2, Node 22.19.0 และ macOS arm64 โดยปิดการค้นหาฟอนต์ระบบทุกกรณี
| ไฟล์ฟอนต์ที่ส่งให้ | ผลที่สังเกต |
|---|---|
| ไม่มี | ตราที่เป็นพาธแสดง แต่ป้ายข้อความหาย |
| Anton เท่านั้น | ป้ายแสดงด้วยแบบอักษรที่ต่างชัดเจนและหนากว่า |
| Abel | ตัวอักษรบางตามที่ตั้งใจแสดง |

ข้อสังเกตเหล่านี้อธิบายตัวอย่างและการตั้งค่านี้ ไม่ได้ยืนยันว่าชุดฟอนต์ binding หรือเวอร์ชันอื่นจะเลือกฟอนต์สำรองใด ประเด็นวินิจฉัยที่มีประโยชน์เรียบง่ายกว่า: การไม่มีตระกูลที่ขออาจทำให้ข้อความหายหรือได้ข้อความฟอนต์แทนที่ดูสมเหตุสมผล
โหลดฟอนต์ในเครื่องด้วย resvg-js
ตัวอย่างนี้ใช้ แพ็กเกจ Node แบบ native ไม่ใช่แพ็กเกจ WebAssembly แยก นิยามชนิดตามเวอร์ชัน ของ binding แสดง fontFiles, fontDirs และ loadSystemFonts ภายใต้ตัวเลือก font
ในโฟลเดอร์ทำงานใหม่ ติดตั้งเวอร์ชันที่ใช้ในบทความ:
npm install --save-exact @resvg/resvg-js@2.6.2ดาวน์โหลด Abel-Regular.ttf และ OFL.txt ที่มาด้วยจากไดเรกทอรี Abel ของ Google Fonts เก็บทั้งคู่ในโฟลเดอร์ย่อย fonts Abel แจกภายใต้ SIL Open Font License เก็บใบอนุญาตไว้กับฟอนต์เมื่อแจกตัวอย่างนี้
บันทึกเป็น label.svg:
<svg xmlns="http://www.w3.org/2000/svg"
width="880" height="240" viewBox="0 0 880 240">
<rect width="880" height="240" fill="#f6f2e8"/>
<path d="M46 155 L96 57 L147 155 Z" fill="#176b5b"/>
<path d="M75 155 L112 88 L166 155 Z" fill="#81ab78"/>
<text x="195" y="151" font-family="Abel"
font-size="82" font-weight="400" fill="#152e29">
PINE & FIELD
</text>
</svg>จากนั้นบันทึก render.mjs ข้าง SVG:
import { access, readFile, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { Resvg } from '@resvg/resvg-js';
const fontFile = fileURLToPath(
new URL('./fonts/Abel-Regular.ttf', import.meta.url)
);
await access(fontFile);
const svg = await readFile(new URL('./label.svg', import.meta.url));
const renderer = new Resvg(svg, {
font: {
loadSystemFonts: false,
fontFiles: [fontFile],
},
});
const png = renderer.render().asPng();
await writeFile(new URL('./label.png', import.meta.url), png);รัน node render.mjs URL ไฟล์ทำให้พาธขาเข้าและขาออกอิงสคริปต์ การเปลี่ยนไดเรกทอรีทำงานของเทอร์มินัลจึงไม่เปลี่ยนฟอนต์ที่เปิด access() ให้ข้อผิดพลาดระบบไฟล์โดยตรงหากฟอนต์ไม่มีหรือเข้าถึงไม่ได้ แต่ไม่ได้ตรวจความถูกต้องของเนื้อหาฟอนต์
หากต้องการทำชุดควบคุมซ้ำ ให้คง SVG เดิม ใช้อาร์เรย์ fontFiles ว่างสำหรับแถวแรก สำหรับแถวที่สอง ดาวน์โหลด Anton-Regular.ttf จากไดเรกทอรี Anton ของ Google Fonts เก็บใบอนุญาต และส่งไฟล์นั้นแทน Abel ตรวจ PNG แต่ละไฟล์ก่อนเปลี่ยนสิ่งอื่น
ให้ชื่อตระกูลตรงกัน ไม่ใช่ชื่อไฟล์
Abel-Regular.ttf เป็นพาธไฟล์ ส่วน Abel คือตระกูลที่ SVG ขอ การเขียน font-family="Abel-Regular.ttf" ไม่ได้บอกตัวเรนเดอร์ให้เปิดไฟล์นั้น
แอตทริบิวต์ font-family ของ SVG รับชื่อตระกูลหรือกลุ่มฟอนต์ทั่วไป และใช้รายการตามลำดับความสำคัญเมื่อระบุหลายชื่อ นอกจากนี้มีพร็อพเพอร์ตี CSS คู่กัน: การประกาศ CSS font-family ที่ตรงกันมีลำดับความสำคัญเหนือแอตทริบิวต์นำเสนอ
สำหรับภาพของคุณ ตรวจสามอย่างร่วมกัน:
- ตระกูล: ชื่อที่บันทึกภายในฟอนต์และที่ SVG ขอ
- สไตล์และน้ำหนัก: ฟอนต์ที่ส่งให้ตรงตัวอักษรที่ตั้งใจหรือไม่
- อักขระ: ฟอนต์มีตัวอักษรและสัญลักษณ์ในป้ายจริงหรือไม่
readFile ที่สำเร็จพิสูจน์เพียงว่าอ่านไบต์ได้ คำที่มองเห็นพิสูจน์เพียงว่ามีตัวอักษรบางแบบเรนเดอร์ ทั้งสองอย่างไม่พิสูจน์ว่าฟอนต์ที่เลือกเป็นฟอนต์ของงานออกแบบ
สำหรับการวินิจฉัยข้อความที่ยังแก้ได้เทียบกับเส้นรอบรูปที่กว้างขึ้น ดูทำไมฟอนต์ SVG เปลี่ยนหลังส่งออก
ตรวจขาเข้าเดียวกันในสภาพแวดล้อมส่งออก
ถือฟอนต์เป็นขาเข้าของงานภาพ รวมไฟล์ฟอนต์ที่จำเป็นในการนำขึ้นใช้งานหรือชุดไฟล์งาน แล้วตรวจว่าพาธที่หาตำแหน่งได้ในสภาพแวดล้อมนั้นชี้ไปยังไฟล์ฟอนต์จริง แบบอักษรที่ติดตั้งในแล็ปท็อปออกแบบมักถูกมองข้ามง่ายเมื่อจัดงานบนเซิร์ฟเวอร์
เริ่มด้วยปิดการค้นหาฟอนต์ระบบและรายการฟอนต์ชัดเจนที่เล็กที่สุดซึ่งครอบคลุมป้ายทดสอบ เมื่อผลถูกต้องแล้ว ทดสอบคำ เครื่องหมายวรรคตอน น้ำหนัก และภาษาที่ภาพใช้จริง ป้ายละตินน้ำหนักปกติของเราไม่ได้ทดสอบอักษรอื่นหรือตระกูลฟอนต์ซับซ้อน
หากตัวอักษรยังดูผิด ตรวจต้นทางว่ามี CSS แทนค่าและสไตล์ <tspan> ซ้อนหรือไม่ หากทั้งตราและป้ายถูกตัดหรือปรับสเกลผิดคาด ให้ตรวจขอบเขต SVG กับขนาดราสเตอร์แยกกัน คู่มือขนาด CairoSVG ทีละขั้น ของเราอธิบายความต่างนี้ในตัวเรนเดอร์อีกตัว ตัวเลือกของมันใช้เฉพาะ CairoSVG
เมื่อแชร์รายงานบั๊กหรืองานส่งออกที่ทำซ้ำได้ ให้รวม SVG เวอร์ชัน binding ที่แน่นอน ชื่อไฟล์และเวอร์ชันฟอนต์ ตัวเลือกตัวเรนเดอร์ และภาพที่คาดหวัง คำนึงถึงสิทธิ์แจกจ่ายฟอนต์เมื่อจัดแพ็กเกจไฟล์
เก็บต้นทางที่แก้ได้ข้าง PNG
โค้ดด้านบนเขียน PNG ซึ่งเป็นไฟล์ส่งมอบราสเตอร์ ตัวอักษรที่มองเห็นไม่ใช่ข้อความ SVG ที่แก้ได้อีก เก็บ label.svg และฟอนต์ขาเข้าเป็นต้นทางสำหรับเปลี่ยนถ้อยคำภายหลัง
หากผู้รับต้องการโลโก้เวกเตอร์ที่ตัวอักษรคงที่ ให้เตรียมสำเนา SVG ส่งมอบที่แปลงตัวอักษรเป็นเส้นรอบรูปในโปรแกรมเวกเตอร์แล้วตรวจในโปรแกรมนั้น เก็บไฟล์หลักที่ยังแก้ข้อความได้ คู่มือรูปแบบไฟล์โลโก้ ของเราอธิบายว่าไฟล์ต้นทางและส่งมอบต่างกันทำหน้าที่อย่างไร
หากตราที่ต้องการมีเพียง PNG หรือ JPG เครื่องมือแปลงโลโก้เป็นเวกเตอร์ของ PerfectVector ช่วยสร้างภาพเวกเตอร์ส่วนนั้นกลับมาได้ ตรวจพาธที่ได้ ลบตัวอักษรที่ไล่เส้นมาโดยไม่ต้องการ และพิมพ์ป้ายใหม่ด้วยฟอนต์ที่ทราบก่อนส่งออก resvg การแปลงเวกเตอร์ไม่ได้ระบุฟอนต์ต้นฉบับหรือคืนข้อความที่แก้ได้ คู่มือการแปลงภาพเป็นเวกเตอร์ อธิบายสิ่งที่เปลี่ยนจากการแปลงนี้
คำถามที่พบบ่อย
ทำไมข้อความหายเมื่อปิดฟอนต์ระบบ? ในการทดสอบฟอนต์ว่าง ตัวเรนเดอร์ไม่มีฟอนต์ที่ส่งให้สำหรับป้ายข้อความ จึงแสดงเฉพาะภาพพาธ โหลดฟอนต์เหมาะสมชัดเจน แล้วตรวจตระกูล สไตล์ และอักขระที่รองรับ
ใช้ชื่อไฟล์ฟอนต์เป็นชื่อ family ของ SVG ได้หรือไม่? ใช้ชื่อตระกูลของฟอนต์ใน SVG ส่งชื่อไฟล์ในเครื่องแยกผ่าน fontFiles การเปลี่ยนชื่อไฟล์ฟอนต์ไม่เปลี่ยนชื่อตระกูลภายใน
resvg เปลี่ยนโลโก้ PNG เป็น SVG ที่แก้ได้หรือไม่? ตัวอย่างนี้เรนเดอร์ SVG เป็น PNG ไม่ได้แปลงโลโก้ราสเตอร์เป็นเวกเตอร์ สร้างตรากลับด้วยกระบวนการแปลงเวกเตอร์หากจำเป็น แล้วเพิ่มข้อความที่แก้ได้และเก็บ SVG นั้นเป็นไฟล์หลัก
แหล่งอ้างอิง
- resvg-js — README เวอร์ชัน 2.6.2 — การใช้ Node แบบ native และโหลดฟอนต์ชัดเจน
- resvg-js — นิยามชนิดเวอร์ชัน 2.6.2 — การตั้งค่าฟอนต์และ API ภาพที่เรนเดอร์
- MDN — font-family ของ SVG — รายการตระกูลและลำดับความสำคัญ CSS
- Google Fonts — Abel — ฟอนต์น้ำหนักปกติและใบอนุญาตที่ใช้กับป้ายที่ต้องการ
- Google Fonts — Anton — ฟอนต์และใบอนุญาตที่ใช้เป็นตัวควบคุมการแทนฟอนต์
หากตราราสเตอร์ทำให้งานภาพติดขัด แปลงภาพโลโก้เป็นเวกเตอร์ ตรวจขอบในโปรแกรมแก้ไข แล้วเพิ่มป้ายเป็นข้อความที่แก้ได้ จากนั้นเรนเดอร์ด้วยไฟล์ฟอนต์ชัดเจน และเทียบ PNG กับไฟล์หลักก่อนส่งมอบ
เพิ่มเติมจากบล็อก

Matplotlib SVG: เก็บกราฟและโลโก้เป็นพาธ
ส่งออกกราฟ Matplotlib เป็น SVG จัดวางพาธโลโก้แยกด้วย svgutils แล้วตรวจไฟล์ที่ส่งมอบว่ามีพิกเซลฝังอยู่หรือไม่ รวมถึงตำแหน่งและการเปลี่ยนฟอนต์

ข้อความ SVG foreignObject: แก้ป้ายหายเมื่อส่งออก
แก้ป้าย SVG ที่เห็นในเบราว์เซอร์แต่หายเมื่อส่งออก เปรียบเทียบ foreignObject กับข้อความ SVG โดยตรง ตรวจเนมสเปซ และรักษาภาพเดิมไว้