Giới thiệu
Trong quá trình phát triển ứng dụng với node-canvas, một vấn đề phổ biến mà các nhà phát triển Windows gặp phải là việc không thể sử dụng hàm registerFont() để tải các font chữ tùy chỉnh. Kể từ phiên bản v2.10.2, hàm này không hoạt động trên Windows, gây khó khăn cho việc hiển thị văn bản với các font chữ tùy chỉnh trên canvas. Bài viết này sẽ hướng dẫn bạn cách khắc phục vấn đề này và cung cấp một phương pháp hiệu quả để tải font chữ vào canvas.
Nội dung chính
- Tổng quan về vấn đề với
registerFont()trên Windows - Hướng dẫn chi tiết cách tải font chữ tùy chỉnh vào node-canvas
- Các lưu ý và mẹo để tránh gặp phải các vấn đề tương tự
Tổng quan về vấn đề
Khi sử dụng registerFont() trong node-canvas trên hệ điều hành Windows, bạn sẽ gặp phải lỗi không thể tải được các font chữ. Điều này không xảy ra trên các hệ điều hành khác như macOS, nơi mà việc đăng ký font chữ diễn ra suôn sẻ. Vấn đề này ảnh hưởng đến việc hiển thị đúng font chữ trong ứng dụng của bạn.
Cách tải font chữ tùy chỉnh vào canvas
Bước 1: Cài đặt font chữ
Để sử dụng các font chữ tùy chỉnh, bạn cần thực hiện các bước sau:
- Sao chép các file font chữ vào thư mục
%LOCALAPPDATA%\Fonts. - Sử dụng script để cài đặt và đăng ký font.
- Font đã đăng ký sẽ có sẵn cho tất cả các tiến trình, điều này có nghĩa là khi bạn tạo một instance của canvas bằng node-canvas, bạn sẽ nhận được các font đã cài đặt trong hệ thống.
Ví dụ về mã nguồn
Dưới đây là mã nguồn hoàn chỉnh để cài đặt font chữ trên Windows:
javascript
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
import { execFileSync } from 'node:child_process';
// Đường dẫn đến thư mục font trên Windows
const WINDOWS_FONTS_DIR = path.join(process.env.WINDIR || 'C:\\Windows', 'Fonts');
function ensureDirSync(dir) {
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
}
function copyIfNeeded(src, destDir) {
ensureDirSync(destDir);
const dest = path.join(destDir, path.basename(src));
try {
if (fs.existsSync(dest)) {
const srcStat = fs.statSync(src);
const dstStat = fs.statSync(dest);
if (srcStat.size === dstStat.size) return dest; // Có thể đã cài đặt
}
fs.copyFileSync(src, dest);
return dest;
} catch {
return null;
}
}
export async function installWindowsFontsIfNeeded(fontsDir) {
const result = { installedTo: [], skipped: [], errors: [], registry: [] };
if (process.platform !== 'win32') {
return result;
}
try {
const candidates = [
{ file: 'Roboto-Regular.ttf', regName: 'Roboto (TrueType)' },
{ file: 'Merriweather-Regular.ttf', regName: 'Merriweather (TrueType)' },
{ file: 'RobotoMono-Regular.ttf', regName: 'Roboto Mono (TrueType)' },
];
const perUserFontsDir = path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), 'Microsoft', 'Windows', 'Fonts');
for (const item of candidates) {
try {
const src = path.join(fontsDir, item.file);
if (!fs.existsSync(src)) {
result.skipped.push(`${src} (không tìm thấy)`);
continue;
}
let installedPath = copyIfNeeded(src, WINDOWS_FONTS_DIR);
if (!installedPath) {
installedPath = copyIfNeeded(src, perUserFontsDir);
}
if (installedPath) {
result.installedTo.push(installedPath);
try {
const regKey = 'HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts';
execFileSync('reg', ['add', regKey, '/v', item.regName, '/t', 'REG_SZ', '/d', installedPath, '/f'], { stdio: 'ignore' });
result.registry.push(`${item.regName} -> ${installedPath}`);
} catch (e) {
result.errors.push(`Thêm vào registry không thành công cho ${item.regName}: ${e.message}`);
}
} else {
result.errors.push(`Không thể sao chép ${path.basename(src)} vào thư mục Fonts`);
}
} catch (e) {
result.errors.push(`${item.file}: ${e.message}`);
}
}
} catch (e) {
result.errors.push(e.message);
}
return result;
}
Bước 2: Xác minh font đã được cài đặt
Để kiểm tra xem font có được cài đặt hay không, bạn có thể thực hiện các bước sau:
- Nhấn
⊞ Win + R. - Nhập
shell:fontsvà nhấn Enter.
Điều này sẽ hiển thị danh sách các font đã cài đặt. Nếu bạn chỉ cài đặt một file font duy nhất, bạn có thể không tìm thấy tên font. Bạn có thể kiểm tra bằng cách sử dụng lệnh PowerShell sau (thay thế tên font):
powershell
Add-Type -AssemblyName System.Drawing
(New-Object System.Drawing.Text.InstalledFontCollection).Families |
ForEach-Object { $_.Name } | Where-Object { $_ -match 'Merriweather' }
Bước 3: Sử dụng font trong canvas
Sau khi đã cài đặt thành công font, bạn có thể sử dụng nó trong canvas như sau:
javascript
import { createCanvas } from 'canvas';
const canvas = createCanvas(0, 0);
const ctx = canvas.getContext('2d');
ctx.font = '20px ''Merriweather'''; // Đặt tên font chữ trong ''
Các thực hành tốt nhất
- Kiểm tra quyền truy cập: Đảm bảo ứng dụng của bạn có quyền truy cập để ghi vào registry và thư mục font trên Windows.
- Sao lưu dữ liệu: Luôn sao lưu dữ liệu trước khi thực hiện các thay đổi trong hệ thống.
Những cạm bẫy thường gặp
- Không tìm thấy font: Đảm bảo rằng tên font được sử dụng đúng với tên đã đăng ký.
- Lỗi quyền truy cập: Nếu ứng dụng không có quyền truy cập thích hợp, việc cài đặt font có thể thất bại.
Mẹo hiệu suất
- Sử dụng các font chữ nhẹ hơn có thể cải thiện hiệu suất render của canvas.
- Tối ưu hóa các thao tác vẽ trên canvas để giảm thiểu thời gian xử lý.
Kết luận
Việc sử dụng hàm registerFont() trên Windows có thể gặp một số trở ngại, nhưng với hướng dẫn này, bạn đã có thể cài đặt font chữ tùy chỉnh cho ứng dụng của mình một cách dễ dàng. Hãy chắc chắn kiểm tra xem font đã được cài đặt thành công và sử dụng nó trong canvas của bạn. Đừng quên theo dõi các tài nguyên và cập nhật mới nhất từ cộng đồng phát triển để cải thiện quy trình làm việc của bạn. Nếu bạn có bất kỳ câu hỏi nào, hãy để lại chúng trong phần bình luận bên dưới!
Câu hỏi thường gặp (FAQ)
1. Tôi có thể sử dụng font chữ nào với node-canvas?
Bạn có thể sử dụng bất kỳ font chữ nào đã được cài đặt trên hệ thống Windows.
2. Có cách nào khác để tải font chữ vào canvas không?
Có thể sử dụng các thư viện khác như @font-face trong CSS, nhưng sẽ không hoạt động trực tiếp với node-canvas.
3. Làm thế nào để kiểm tra font chữ đã cài đặt?
Bạn có thể sử dụng PowerShell hoặc kiểm tra trong thư mục Fonts của Windows.