समस्या
fillText() मेथड लाइन ब्रेक (\n) का सम्मान नहीं करता। यह टेक्स्ट को एक ही लाइन पर ड्रा करता है। बहु-लाइन टेक्स्ट के लिए, मैन्युअल रूप से लाइन्स को विभाजित करके प्रत्येक को अलग से ड्रा करना पड़ता है।
समाधान: कस्टम wrapText फंक्शन
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="500" height="300" style="border:1px solid #ccc; background:#fafafa;"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
/**
* कैनवास पर लपेटा हुआ टेक्स्ट ड्रा करता है
* @param {CanvasRenderingContext2D} ctx - कैनवास कॉन्टेक्स्ट
* @param {string} text - ड्रा करने वाला टेक्स्ट
* @param {number} x - शुरुआती X स्थिति
* @param {number} y - शुरुआती Y स्थिति (बेसलाइन)
* @param {number} maxWidth - अधिकतम चौड़ाई (पिक्सेल्स में)
* @param {number} lineHeight - लाइन ऊंचाई (पिक्सेल्स में)
*/
function wrapText(ctx, text, x, y, maxWidth, lineHeight) {
const words = text.split(' ');
let line = '';
let currentY = y;
for (let i = 0; i < words.length; i++) {
const testLine = line + words[i] + ' ';
const metrics = ctx.measureText(testLine);
const testWidth = metrics.width;
if (testWidth > maxWidth && i > 0) {
ctx.fillText(line, x, currentY);
line = words[i] + ' ';
currentY += lineHeight;
} else {
line = testLine;
}
}
ctx.fillText(line, x, currentY); // अंतिम लाइन
return currentY; // अंतिम Y स्थिति लौटाएँ
}
// उपयोग
ctx.font = '18px "Segoe UI", sans-serif';
ctx.fillStyle = '#2c3e50';
const longText = 'यह एक लंबा टेक्स्ट है जो स्वचालित रूप से कई लाइनों में लपेट जाएगा जब यह निर्दिष्ट अधिकतम चौड़ाई से अधिक हो जाएगा। कैनवास fillText मूल रूप से लाइन ब्रेक का समर्थन नहीं करता, इसलिए हमें इस लॉजिक को स्वयं लागू करना पड़ता है।';
wrapText(ctx, longText, 20, 40, 460, 28);
// स्पष्ट लाइन ब्रेक (\n) के साथ टेक्स्ट
function wrapTextWithNewlines(ctx, text, x, y, maxWidth, lineHeight) {
const paragraphs = text.split('\n');
let currentY = y;
for (const paragraph of paragraphs) {
if (paragraph.trim() === '') {
currentY += lineHeight; // खाली लाइन
continue;
}
currentY = wrapText(ctx, paragraph, x, currentY, maxWidth, lineHeight);
currentY += lineHeight / 2; // पैराग्राफ स्पेसिंग
}
return currentY;
}
const multiPara = 'पहला पैराग्राफ।\n\nदूसरा पैराग्राफ जिसमें लंबा टेक्स्ट है जो स्वचालित रूप से लपेटा जाएगा।\n\nतीसरा पैराग्राफ।';
ctx.font = '16px Georgia, serif';
ctx.fillStyle = '#555';
wrapTextWithNewlines(ctx, multiPara, 20, 180, 460, 24);
</script>
</body>
</html>
सरल दृष्टिकोण: \n पर विभाजित करें
function drawMultilineText(ctx, text, x, y, lineHeight) {
const lines = text.split('\n');
lines.forEach((line, index) => {
ctx.fillText(line, x, y + index * lineHeight);
});
}
// उपयोग
ctx.font = '16px Arial';
ctx.fillStyle = 'black';
drawMultilineText(ctx, 'लाइन 1\nलाइन 2\nलाइन 3', 50, 50, 24);
उन्नत: TextMetrics के साथ सटीक नियंत्रण
function drawTextAdvanced(ctx, text, x, y, options = {}) {
const {
maxWidth = Infinity,
lineHeight = 1.2,
align = 'left', // 'left', 'center', 'right', 'justify'
font = '16px sans-serif',
color = '#000',
baseline = 'top'
} = options;
ctx.font = font;
ctx.fillStyle = color;
ctx.textBaseline = baseline;
const lines = text.split('\n');
let currentY = y;
const fontSize = parseFloat(font);
const actualLineHeight = fontSize * lineHeight;
for (const line of lines) {
if (maxWidth !== Infinity) {
// शब्द लपेटन
const words = line.split(' ');
let currentLine = '';
for (const word of words) {
const testLine = currentLine + word + ' ';
if (ctx.measureText(testLine).width > maxWidth && currentLine) {
drawAlignedLine(ctx, currentLine, x, currentY, maxWidth, align);
currentLine = word + ' ';
currentY += actualLineHeight;
} else {
currentLine = testLine;
}
}
drawAlignedLine(ctx, currentLine, x, currentY, maxWidth, align);
} else {
drawAlignedLine(ctx, line, x, currentY, maxWidth, align);
}
currentY += actualLineHeight;
}
return currentY;
}
function drawAlignedLine(ctx, line, x, y, maxWidth, align) {
const width = ctx.measureText(line.trimEnd()).width;
let drawX = x;
switch (align) {
case 'center': drawX = x + (maxWidth - width) / 2; break;
case 'right': drawX = x + maxWidth - width; break;
case 'justify':
// जस्टिफाई के लिए शब्दों के बीच स्पेस जोड़ें
const words = line.trim().split(' ');
if (words.length > 1 && maxWidth !== Infinity) {
const totalWordsWidth = words.reduce((sum, w) => sum + ctx.measureText(w).width, 0);
const spaceWidth = (maxWidth - totalWordsWidth) / (words.length - 1);
let curX = x;
words.forEach((word, i) => {
ctx.fillText(word, curX, y);
curX += ctx.measureText(word).width + (i < words.length - 1 ? spaceWidth : 0);
});
return;
}
break;
}
ctx.fillText(line.trimEnd(), drawX, y);
}
Path2D के साथ टेक्स्ट पथ (उन्नत)
// टेक्स्ट को पथ में बदलें (क्लिपिंग, स्ट्रोकिंग, ट्रांसफॉर्म के लिए)
const path = new Path2D();
path.font = 'bold 48px serif';
path.fillText('कर्व्ड टेक्स्ट', 0, 0);
// पथ को ट्रांसफॉर्म करके ड्रा करें
ctx.save();
ctx.translate(100, 100);
ctx.rotate(-0.2);
ctx.fill(path);
ctx.restore();