समस्या: फॉन्ट लोडिंग रेस कंडीशन
जब @font-face के माध्यम से लोड किए गए फॉन्ट के साथ कैनवास पर टेक्स्ट ड्रा किया जाता है, तो ब्राउज़र द्वारा फॉन्ट पूरी तरह लोड होने से पहले ड्रॉइंग होने पर टेक्स्ट डिफ़ॉल्ट/फॉलबैक फॉन्ट में रेंडर होता है।
समाधान 1: Document Fonts API (आधुनिक, अनुशंसित)
<!DOCTYPE html>
<html>
<head>
<style>
@font-face {
font-family: 'MyCustomFont';
src: url('fonts/custom.woff2') format('woff2'),
url('fonts/custom.woff') format('woff');
font-display: swap;
}
</style>
</head>
<body>
<canvas id="canvas" width="600" height="200" style="border:1px solid #ccc;"></canvas>
<script>
async function drawWithFont() {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// फॉन्ट लोड होने तक प्रतीक्षा करें
try {
await document.fonts.load('24px "MyCustomFont"');
console.log('फॉन्ट लोड हुआ!');
} catch (e) {
console.warn('फॉन्ट लोड विफल, फॉलबैक उपयोग:', e);
}
// अब सुरक्षित रूप से ड्रा करें
ctx.font = '24px "MyCustomFont"';
ctx.fillStyle = '#333';
ctx.fillText('कस्टम फॉन्ट में टेक्स्ट!', 50, 100);
}
drawWithFont();
</script>
</body>
</html>
समाधान 2: FontFace API (अधिक नियंत्रण)
<script>
async function loadAndDraw() {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// FontFace ऑब्जेक्ट बनाएँ
const myFont = new FontFace('MyFont', 'url(https://example.com/font.woff2)', {
style: 'normal',
weight: '400',
display: 'swap'
});
try {
// फॉन्ट लोड करें
const loadedFont = await myFont.load();
// दस्तावेज़ में जोड़ें (वैकल्पिक, लेकिन CSS उपयोग के लिए अच्छा)
document.fonts.add(loadedFont);
console.log('फॉन्ट सफलतापूर्वक लोड हुआ!');
// कैनवास पर ड्रा करें
ctx.font = '30px "MyFont"';
ctx.fillStyle = '#2c3e50';
ctx.fillText('FontFace API के साथ ड्रा किया गया', 50, 100);
} catch (error) {
console.error('फॉन्ट लोडिंग विफल:', error);
// फॉलबैक फॉन्ट उपयोग करें
ctx.font = '30px sans-serif';
ctx.fillText('फॉन्ट लोड विफल - फॉलबैक उपयोग', 50, 100);
}
}
loadAndDraw();
</script>
समाधान 3: अदृश्य तत्व प्रीलोड (पुराना तरीका)
<!-- HTML में अदृश्य तत्व जोड़ें ताकि ब्राउज़र फॉन्ट डाउनलोड करे -->
<div style="font-family: 'MyCustomFont'; position: absolute; left: -9999px; visibility: hidden;">.</div>
<!-- या JavaScript में -->
<script>
function preloadFont(fontFamily) {
const div = document.createElement('div');
div.style.cssText = `
font-family: "${fontFamily}";
position: absolute;
left: -9999px;
visibility: hidden;
font-size: 16px;
`;
div.textContent = '.';
document.body.appendChild(div);
// थोड़ी देर बाद हटाएँ
setTimeout(() => div.remove(), 1000);
}
preloadFont('MyCustomFont');
</script>
समाधान 4: font-display: swap के साथ CSS
@font-face {
font-family: 'MyFont';
src: url('font.woff2') format('woff2');
font-display: swap; /* फॉलबैक तुरंत दिखाएँ, फॉन्ट तैयार होने पर स्वैप करें */
}
पूर्ण मजबूत समाधान
class CanvasTextRenderer {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
this.fontCache = new Map();
}
async ensureFontLoaded(fontFamily, fontSpec = {}) {
const cacheKey = `${fontFamily}-${JSON.stringify(fontSpec)}`;
if (this.fontCache.has(cacheKey)) {
return this.fontCache.get(cacheKey);
}
// FontFace से लोड करने का प्रयास करें
if (fontSpec.url) {
const fontFace = new FontFace(fontFamily, `url(${fontSpec.url})`, fontSpec);
try {
const loaded = await fontFace.load();
document.fonts.add(loaded);
this.fontCache.set(cacheKey, true);
return true;
} catch (e) {
console.warn(`फॉन्ट ${fontFamily} लोड विफल:`, e);
}
}
// फॉलबैक: document.fonts.load के साथ प्रतीक्षा करें
try {
await document.fonts.load(`16px "${fontFamily}"`);
this.fontCache.set(cacheKey, true);
return true;
} catch (e) {
this.fontCache.set(cacheKey, false);
return false;
}
}
async drawText(text, x, y, options = {}) {
const {
fontFamily = 'sans-serif',
fontSize = 16,
fontWeight = 'normal',
color = '#000',
fontUrl = null,
maxWidth = null
} = options;
// फॉन्ट सुनिश्चित करें
await this.ensureFontLoaded(fontFamily, { url: fontUrl, weight: fontWeight });
// ड्रा करें
this.ctx.font = `${fontWeight} ${fontSize}px "${fontFamily}"`;
this.ctx.fillStyle = color;
if (maxWidth) {
this.ctx.fillText(text, x, y, maxWidth);
} else {
this.ctx.fillText(text, x, y);
}
}
}
// उपयोग
const renderer = new CanvasTextRenderer('myCanvas');
await renderer.drawText('हैलो वर्ल्ड!', 50, 100, {
fontFamily: 'CustomFont',
fontSize: 32,
fontWeight: 'bold',
color: '#2c3e50',
fontUrl: 'https://example.com/custom.woff2'
});
ब्राउज़र समर्थन
document.fonts.load() |
Chrome 35+, Firefox 41+, Safari 10+, Edge 79+ |
FontFace |
Chrome 35+, Firefox 39+, Safari 10+, Edge 79+ |
font-display |
Chrome 60+, Firefox 58+, Safari 11.1+, Edge 79+ |