HTML5 कैनवास ctx.fillText लाइन ब्रेक नहीं करेगा?


108

मुझे लगता है कि यदि पाठ में "\ n" शामिल है तो मैं किसी कैनवास में पाठ जोड़ने में सक्षम नहीं हो सकता। मेरा मतलब है, लाइन ब्रेक शो / काम नहीं करता है।

ctxPaint.fillText("s  ome \n \\n <br/> thing", x, y);

उपरोक्त कोड "s ome \n <br/> thing"एक लाइन पर आ जाएगा ।

क्या यह फिलटैक्स की एक सीमा है या क्या मैं इसे गलत कर रहा हूं? "\ n" वहाँ हैं, और मुद्रित नहीं हैं, लेकिन वे या तो काम नहीं करते हैं।


1
क्या आप अंत तक पहुंचने पर स्वचालित रूप से लपेटना चाहते हैं? या सिर्फ पाठ में मौजूद newline वर्णों पर विचार करने के लिए?
गेब्रियल पेट्रीओली

टेक्स्ट को कई लाइनों में लपेटें।
टॉवर

हाय ट्वोडोर्डन, क्या यह सीमा क्रोम और मोज़िला दोनों पर मौजूद है? लोग अक्सर साधारण HTML पाठ का उपयोग करते हैं जो उन्होंने कैनवास को एक स्थिति के साथ रखा: उदाहरण के लिए निरपेक्ष। इसके अलावा, आप दो fillText कर सकते हैं और अपनी दूसरी पंक्तियों के लिए अपने पाठ का Y मूल स्थानांतरित कर सकते हैं।
टिम


TL; DR: या तो fillText()कई बार कॉल करें और अलग करने के लिए अपनी फ़ॉन्ट ऊंचाई का उपयोग करें, या डेवलपर. mozilla.org/en-US/docs/Web/API/TextMetrics डेवलपर. mozilla.org/en-US/docs/Web/API का उपयोग करें /… - या, नीचे दिए गए TextMetrics का उपयोग न करने वाले बहुत जटिल "समाधान" में से एक का उपयोग करें ...
एंड्रयू

जवाबों:


62

मुझे डर है कि यह कैनवस की एक सीमा है fillText। ' मल्टी-लाइन सपोर्ट नहीं है। इससे भी बदतर, लाइन की ऊंचाई को मापने के लिए कोई अंतर्निहित तरीका नहीं है, केवल चौड़ाई, यह खुद को और भी कठिन बना रही है!

बहुत सारे लोगों ने अपने स्वयं के बहु-लाइन समर्थन को लिखा है, शायद सबसे उल्लेखनीय परियोजना जो मोज़िला स्काईराइट है

fillTextहर बार जब आप पाठ की ऊँचाई को y मान में जोड़ते हैं, तो आपको जो करने की आवश्यकता होगी, वह है । (एम की चौड़ाई को मापना वही है जो आकाशवाणी के लोग अनुमानित पाठ के लिए करते हैं, मेरा मानना ​​है।)


धन्यवाद! मुझे लग रहा था कि यह परेशान करने वाला होगा ... SKYWRITER के बारे में जानकर अच्छा लगा, लेकिन जब तक fillText () में सुधार नहीं होता मैं बस "इंतजार" करूंगा। यह मेरे मामले में बहुत महत्वपूर्ण सौदा नहीं था। हाहा, कोई लाइन ऊंचाई नहीं, यह ऐसा है जैसे किसी ने उद्देश्य से किया हो। : डी
स्पेक्ट्रलजम्प

18
ईमानदारी से, मैं इसका समर्थन करने के लिए आपकी सांस को नहीं भर पाऊंगा, क्योंकि मैं यह महसूस करता हूं कि इसका उपयोग इसी तरह किया जाता है (कई कॉल और खुद की गणना करना)। मुझे लगता है कि कैनवास एपीआई के साथ बहुत सारी शक्ति यह है कि यह निचले स्तर की ड्राइंग कार्यक्षमता को अलग करता है जो आप पहले से ही कर सकते हैं (आवश्यक माप प्रदर्शन कर सकते हैं)। इसके अलावा, आप केवल पिक्सेल में पाठ का आकार प्रदान करके पाठ की ऊंचाई जान सकते हैं; दूसरे शब्दों में: reference.font = "16px एरियल"; - आप वहाँ ऊंचाई है; चौड़ाई केवल एक ही है जो गतिशील है।
लेव

1
कुछ अतिरिक्त गुण के लिए measureText()जोड़ दिया गया है जो मैं इस समस्या का समाधान कर सकता है। Chrome के पास उन्हें सक्षम करने के लिए एक ध्वज है, लेकिन अन्य ब्राउज़र नहीं ... अभी तक!
SWDV

@ एसडवीवी सिर्फ स्पष्ट होने के लिए, जो लोग वर्षों से कल्पना में हैं, अब साल हो सकते हैं, जब तक कि हमारे पास उपयोग करने के लिए व्यापक रूप से न हों :(
साइमन सरिस

67

यदि आप केवल पाठ में newline वर्णों का ध्यान रखना चाहते हैं तो आप इसे newlines पर पाठ को विभाजित करके और कई बार कॉल करके अनुकरण कर सकते हैं fillText()

की तरह कुछ http://jsfiddle.net/BaG4J/1/

var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';
    console.log(c);
var txt = 'line 1\nline 2\nthird line..';
var x = 30;
var y = 30;
var lineheight = 15;
var lines = txt.split('\n');

for (var i = 0; i<lines.length; i++)
    c.fillText(lines[i], x, y + (i*lineheight) );
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>


मैंने सिर्फ अवधारणा का एक रैपिंग प्रूफ बनाया ( निर्दिष्ट चौड़ाई में पूर्ण रैप। कोई शब्द नहीं तोड़ना, अभी तक )
उदाहरण http://jsfiddle.net/BaG4J/2/ पर

var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';

var txt = 'this is a very long text to print';

printAt(c, txt, 10, 20, 15, 90 );


function printAt( context , text, x, y, lineHeight, fitWidth)
{
    fitWidth = fitWidth || 0;
    
    if (fitWidth <= 0)
    {
         context.fillText( text, x, y );
        return;
    }
    
    for (var idx = 1; idx <= text.length; idx++)
    {
        var str = text.substr(0, idx);
        console.log(str, context.measureText(str).width, fitWidth);
        if (context.measureText(str).width > fitWidth)
        {
            context.fillText( text.substr(0, idx-1), x, y );
            printAt(context, text.substr(idx-1), x, y + lineHeight, lineHeight,  fitWidth);
            return;
        }
    }
    context.fillText( text, x, y );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>


और एक शब्द-रैपिंग ( रिक्त स्थान पर तोड़कर ) अवधारणा का प्रमाण। http://jsfiddle.net/BaG4J/5/
पर उदाहरण

var c = document.getElementById('c').getContext('2d');
c.font = '11px Courier';

var txt = 'this is a very long text. Some more to print!';

printAtWordWrap(c, txt, 10, 20, 15, 90 );


function printAtWordWrap( context , text, x, y, lineHeight, fitWidth)
{
    fitWidth = fitWidth || 0;
    
    if (fitWidth <= 0)
    {
        context.fillText( text, x, y );
        return;
    }
    var words = text.split(' ');
    var currentLine = 0;
    var idx = 1;
    while (words.length > 0 && idx <= words.length)
    {
        var str = words.slice(0,idx).join(' ');
        var w = context.measureText(str).width;
        if ( w > fitWidth )
        {
            if (idx==1)
            {
                idx=2;
            }
            context.fillText( words.slice(0,idx-1).join(' '), x, y + (lineHeight*currentLine) );
            currentLine++;
            words = words.splice(idx-1);
            idx = 1;
        }
        else
        {idx++;}
    }
    if  (idx > 0)
        context.fillText( words.join(' '), x, y + (lineHeight*currentLine) );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>


दूसरे और तीसरे उदाहरण में मैं उस measureText()पद्धति का उपयोग कर रहा हूं जो दिखाता है कि ( पिक्सेल में ) एक स्ट्रिंग मुद्रित होने पर कितनी देर होगी।


पूरे लंबे पाठ को सही कैसे ठहराया जाए?
अमीरहोसिन तार्मास्ट

यदि आपको एक लंबे, औचित्यपूर्ण पाठ की आवश्यकता है, तो आप कैनवास का उपयोग क्यों करेंगे?
माइक 'पोमैक्स' कामेरमेंस

39

हो सकता है कि इस पार्टी में आने में थोड़ी देर हो गई हो, लेकिन मुझे एक कैनवस पर टेक्स्ट को रैप करने के लिए निम्नलिखित ट्यूटोरियल मिला।

http://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/

इससे मुझे लगता है कि काम करने के लिए बहु लाइनें मिल सकती हैं (क्षमा करें रामिरेज़, आपका काम मेरे लिए नहीं था!)। एक कैनवास में पाठ लपेटने के लिए मेरा पूरा कोड इस प्रकार है:

<script type="text/javascript">

     // http: //www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/
     function wrapText(context, text, x, y, maxWidth, lineHeight) {
        var cars = text.split("\n");

        for (var ii = 0; ii < cars.length; ii++) {

            var line = "";
            var words = cars[ii].split(" ");

            for (var n = 0; n < words.length; n++) {
                var testLine = line + words[n] + " ";
                var metrics = context.measureText(testLine);
                var testWidth = metrics.width;

                if (testWidth > maxWidth) {
                    context.fillText(line, x, y);
                    line = words[n] + " ";
                    y += lineHeight;
                }
                else {
                    line = testLine;
                }
            }

            context.fillText(line, x, y);
            y += lineHeight;
        }
     }

     function DrawText() {

         var canvas = document.getElementById("c");
         var context = canvas.getContext("2d");

         context.clearRect(0, 0, 500, 600);

         var maxWidth = 400;
         var lineHeight = 60;
         var x = 20; // (canvas.width - maxWidth) / 2;
         var y = 58;


         var text = document.getElementById("text").value.toUpperCase();                

         context.fillStyle = "rgba(255, 0, 0, 1)";
         context.fillRect(0, 0, 600, 500);

         context.font = "51px 'LeagueGothicRegular'";
         context.fillStyle = "#333";

         wrapText(context, text, x, y, maxWidth, lineHeight);
     }

     $(document).ready(function () {

         $("#text").keyup(function () {
             DrawText();
         });

     });

    </script>

cमेरे कैनवास की आईडी कहां है औरtext मेरे टेक्स्टबॉक्स की आईडी है।

जैसा कि आप शायद देख सकते हैं कि एक गैर-मानक फ़ॉन्ट का उपयोग कर रहा हूं। जब तक आपने कैनवास को हेरफेर करने के लिए कुछ पाठ PRIOR पर फ़ॉन्ट का उपयोग किया है, तब तक आप @ फ़ॉन्ट-फेस का उपयोग कर सकते हैं - अन्यथा कैनवास फ़ॉन्ट को नहीं उठाएगा।

आशा है कि यह किसी की मदद करता है।


26

टेक्स्ट को लाइनों में विभाजित करें, और प्रत्येक को अलग से ड्रा करें:

function fillTextMultiLine(ctx, text, x, y) {
  var lineHeight = ctx.measureText("M").width * 1.2;
  var lines = text.split("\n");
  for (var i = 0; i < lines.length; ++i) {
    ctx.fillText(lines[i], x, y);
    y += lineHeight;
  }
}

17

यहां मेरा समाधान है, लोकप्रिय रैपटेक्स्ट () फ़ंक्शन को संशोधित करना जो पहले से ही यहां प्रस्तुत किया गया है। मैं जावास्क्रिप्ट के प्रोटोटाइप सुविधा का उपयोग कर रहा हूं ताकि आप कैनवास संदर्भ से फ़ंक्शन को कॉल कर सकें।

CanvasRenderingContext2D.prototype.wrapText = function (text, x, y, maxWidth, lineHeight) {

    var lines = text.split("\n");

    for (var i = 0; i < lines.length; i++) {

        var words = lines[i].split(' ');
        var line = '';

        for (var n = 0; n < words.length; n++) {
            var testLine = line + words[n] + ' ';
            var metrics = this.measureText(testLine);
            var testWidth = metrics.width;
            if (testWidth > maxWidth && n > 0) {
                this.fillText(line, x, y);
                line = words[n] + ' ';
                y += lineHeight;
            }
            else {
                line = testLine;
            }
        }

        this.fillText(line, x, y);
        y += lineHeight;
    }
}

मूल उपयोग:

var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");
ctx.fillStyle = "black";
ctx.font = "12px sans-serif";
ctx.textBaseline = "top";
ctx.wrapText("Hello\nWorld!",20,20,160,16);

यहाँ एक प्रदर्शन है जिसे मैंने एक साथ रखा है: http://jsfiddle.net/7RdbL/


एक जादू की तरह काम किया। धन्यवाद।
फिरोजी

13

मैंने सिर्फ CanvasRenderingContext2D को दो फ़ंक्शंस को बढ़ाया: mlFillText और mlStrokeText।

आप GitHub में अंतिम संस्करण पा सकते हैं :

इस फ़ंक्शन के साथ आप एक बॉक्स में मिल्टिलिन टेक्स्ट को भर सकते हैं। आप पाठ को ऊर्ध्वाधर और क्षैतिज रूप से संरेखित कर सकते हैं। (यह खाता \ n में लेता है और पाठ को सही भी कर सकता है)।

प्रोटोटाइप हैं:

function mlFillText (पाठ, x, y, w, h, vAlign, hAlign, lineheight); function mlStrokeText (पाठ, x, y, w, h, vAlign, hAlign, lineheight);

जहां vAlign हो सकता है: "टॉप", "सेंटर" या "बटन" और hAlign हो सकता है: "लेफ्ट", "सेंटर", "राइट" या "जस्टिफाई"

आप यहां परिवाद का परीक्षण कर सकते हैं: http://jsfiddle.net/4WRZj/1/

यहां छवि विवरण दर्ज करें

यहाँ पुस्तकालय का कोड है:

// Library: mltext.js
// Desciption: Extends the CanvasRenderingContext2D that adds two functions: mlFillText and mlStrokeText.
//
// The prototypes are: 
//
// function mlFillText(text,x,y,w,h,vAlign,hAlign,lineheight);
// function mlStrokeText(text,x,y,w,h,vAlign,hAlign,lineheight);
// 
// Where vAlign can be: "top", "center" or "button"
// And hAlign can be: "left", "center", "right" or "justify"
// Author: Jordi Baylina. (baylina at uniclau.com)
// License: GPL
// Date: 2013-02-21

function mlFunction(text, x, y, w, h, hAlign, vAlign, lineheight, fn) {
    text = text.replace(/[\n]/g, " \n ");
    text = text.replace(/\r/g, "");
    var words = text.split(/[ ]+/);
    var sp = this.measureText(' ').width;
    var lines = [];
    var actualline = 0;
    var actualsize = 0;
    var wo;
    lines[actualline] = {};
    lines[actualline].Words = [];
    i = 0;
    while (i < words.length) {
        var word = words[i];
        if (word == "\n") {
            lines[actualline].EndParagraph = true;
            actualline++;
            actualsize = 0;
            lines[actualline] = {};
            lines[actualline].Words = [];
            i++;
        } else {
            wo = {};
            wo.l = this.measureText(word).width;
            if (actualsize === 0) {
                while (wo.l > w) {
                    word = word.slice(0, word.length - 1);
                    wo.l = this.measureText(word).width;
                }
                if (word === "") return; // I can't fill a single character
                wo.word = word;
                lines[actualline].Words.push(wo);
                actualsize = wo.l;
                if (word != words[i]) {
                    words[i] = words[i].slice(word.length, words[i].length);
                } else {
                    i++;
                }
            } else {
                if (actualsize + sp + wo.l > w) {
                    lines[actualline].EndParagraph = false;
                    actualline++;
                    actualsize = 0;
                    lines[actualline] = {};
                    lines[actualline].Words = [];
                } else {
                    wo.word = word;
                    lines[actualline].Words.push(wo);
                    actualsize += sp + wo.l;
                    i++;
                }
            }
        }
    }
    if (actualsize === 0) lines[actualline].pop();
    lines[actualline].EndParagraph = true;

    var totalH = lineheight * lines.length;
    while (totalH > h) {
        lines.pop();
        totalH = lineheight * lines.length;
    }

    var yy;
    if (vAlign == "bottom") {
        yy = y + h - totalH + lineheight;
    } else if (vAlign == "center") {
        yy = y + h / 2 - totalH / 2 + lineheight;
    } else {
        yy = y + lineheight;
    }

    var oldTextAlign = this.textAlign;
    this.textAlign = "left";

    for (var li in lines) {
        var totallen = 0;
        var xx, usp;
        for (wo in lines[li].Words) totallen += lines[li].Words[wo].l;
        if (hAlign == "center") {
            usp = sp;
            xx = x + w / 2 - (totallen + sp * (lines[li].Words.length - 1)) / 2;
        } else if ((hAlign == "justify") && (!lines[li].EndParagraph)) {
            xx = x;
            usp = (w - totallen) / (lines[li].Words.length - 1);
        } else if (hAlign == "right") {
            xx = x + w - (totallen + sp * (lines[li].Words.length - 1));
            usp = sp;
        } else { // left
            xx = x;
            usp = sp;
        }
        for (wo in lines[li].Words) {
            if (fn == "fillText") {
                this.fillText(lines[li].Words[wo].word, xx, yy);
            } else if (fn == "strokeText") {
                this.strokeText(lines[li].Words[wo].word, xx, yy);
            }
            xx += lines[li].Words[wo].l + usp;
        }
        yy += lineheight;
    }
    this.textAlign = oldTextAlign;
}

(function mlInit() {
    CanvasRenderingContext2D.prototype.mlFunction = mlFunction;

    CanvasRenderingContext2D.prototype.mlFillText = function (text, x, y, w, h, vAlign, hAlign, lineheight) {
        this.mlFunction(text, x, y, w, h, hAlign, vAlign, lineheight, "fillText");
    };

    CanvasRenderingContext2D.prototype.mlStrokeText = function (text, x, y, w, h, vAlign, hAlign, lineheight) {
        this.mlFunction(text, x, y, w, h, hAlign, vAlign, lineheight, "strokeText");
    };
})();

और यहाँ उपयोग उदाहरण है:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

var T = "This is a very long line line with a CR at the end.\n This is the second line.\nAnd this is the last line.";
var lh = 12;

ctx.lineWidth = 1;

ctx.mlFillText(T, 10, 10, 100, 100, 'top', 'left', lh);
ctx.strokeRect(10, 10, 100, 100);

ctx.mlFillText(T, 110, 10, 100, 100, 'top', 'center', lh);
ctx.strokeRect(110, 10, 100, 100);

ctx.mlFillText(T, 210, 10, 100, 100, 'top', 'right', lh);
ctx.strokeRect(210, 10, 100, 100);

ctx.mlFillText(T, 310, 10, 100, 100, 'top', 'justify', lh);
ctx.strokeRect(310, 10, 100, 100);

ctx.mlFillText(T, 10, 110, 100, 100, 'center', 'left', lh);
ctx.strokeRect(10, 110, 100, 100);

ctx.mlFillText(T, 110, 110, 100, 100, 'center', 'center', lh);
ctx.strokeRect(110, 110, 100, 100);

ctx.mlFillText(T, 210, 110, 100, 100, 'center', 'right', lh);
ctx.strokeRect(210, 110, 100, 100);

ctx.mlFillText(T, 310, 110, 100, 100, 'center', 'justify', lh);
ctx.strokeRect(310, 110, 100, 100);

ctx.mlFillText(T, 10, 210, 100, 100, 'bottom', 'left', lh);
ctx.strokeRect(10, 210, 100, 100);

ctx.mlFillText(T, 110, 210, 100, 100, 'bottom', 'center', lh);
ctx.strokeRect(110, 210, 100, 100);

ctx.mlFillText(T, 210, 210, 100, 100, 'bottom', 'right', lh);
ctx.strokeRect(210, 210, 100, 100);

ctx.mlFillText(T, 310, 210, 100, 100, 'bottom', 'justify', lh);
ctx.strokeRect(310, 210, 100, 100);

ctx.mlStrokeText("Yo can also use mlStrokeText!", 0 , 310 , 420, 30, 'center', 'center', lh);

Uncaught ReferenceError: Words is not definedअगर मैं फॉन्ट बदलने की कोशिश करूं। उदाहरण के लिए: ctx.font = '40px Arial';- अपने फिडल में डालने की कोशिश करें
साइको brm

Btw, जहां नरक Words(मामले के प्रति संवेदनशील) चर आता है ?? यह कहीं भी परिभाषित नहीं है। कोड का वह हिस्सा केवल तभी निष्पादित होता है जब आप फ़ॉन्ट बदलते हैं ..
साइको brm

1
@psychobrm आप बिल्कुल सही हैं। यह एक बग है (मैं पहले से ही इसे ठीक करता हूं)। कोड के इस भाग को केवल तभी निष्पादित किया जाता है यदि आपको किसी शब्द को दो पंक्तियों में विभाजित करना है। धन्यवाद!
jbaylina

मैंने कुछ अपग्रेड किए हैं जिनकी मुझे आवश्यकता है: रिक्त स्थान प्रस्तुत करना, प्रमुख / अनुगामी newlines को प्रस्तुत करना, स्ट्रोक को प्रस्तुत करना और एक कॉल से भरना (पाठ को दो बार मापना नहीं है), मुझे भी पुनरावृत्ति को बदलना होगा, क्योंकि for inविस्तारित के साथ अच्छी तरह से काम नहीं करता है Array.prototype। क्या आप इसे गीथब पर रख सकते हैं ताकि हम उस पर पुनरावृति कर सकें?
साइको ब्रम

@psychobrm मैंने आपके परिवर्तनों को मर्ज कर दिया है। धन्यवाद!
jbaylina 12

8

जावास्क्रिप्ट का उपयोग करके मैंने एक समाधान विकसित किया। यह सुंदर नहीं है, लेकिन यह मेरे लिए काम करता है:


function drawMultilineText(){

    // set context and formatting   
    var context = document.getElementById("canvas").getContext('2d');
    context.font = fontStyleStr;
    context.textAlign = "center";
    context.textBaseline = "top";
    context.fillStyle = "#000000";

    // prepare textarea value to be drawn as multiline text.
    var textval = document.getElementByID("textarea").value;
    var textvalArr = toMultiLine(textval);
    var linespacing = 25;
    var startX = 0;
    var startY = 0;

    // draw each line on canvas. 
    for(var i = 0; i < textvalArr.length; i++){
        context.fillText(textvalArr[i], x, y);
        y += linespacing;
    }
}

// Creates an array where the <br/> tag splits the values.
function toMultiLine(text){
   var textArr = new Array();
   text = text.replace(/\n\r?/g, '<br/>');
   textArr = text.split("<br/>");
   return textArr;
}

उम्मीद है की वो मदद करदे!


1
हैलो, मान लीजिए अपने पाठ इस वर पाठ = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" की तरह है; तो क्या कैनवास में खुश है ???
अमोल नवसुपे

यह कैनवास से बाहर निकल जाएगा, क्योंकि @Rireirez ने फिल्टक्स्ट में अधिकतम पैरामीटर नहीं डाला है :)
KaHa6uc

6

@ गैबी पेट्रीओली द्वारा प्रदान किए गए शब्द-रैपिंग (रिक्त स्थान को तोड़ना) के लिए कोड बहुत उपयोगी है। न्यूलाइन वर्णों के लिए सहायता प्रदान करने के लिए मैंने उसका कोड बढ़ाया है \n। साथ ही, कई बार यह बाउंडिंग बॉक्स के आयामों के लिए उपयोगी होता है, इसलिए multiMeasureText()चौड़ाई और ऊंचाई दोनों को लौटाता है।

आप यहां कोड देख सकते हैं: http://jsfiddle.net/jeffchan/WHgaY/76/


लिंक समाप्त हो रहे हैं, कृपया इस उत्तर को इस कोड में डाल दें, भले ही आपके पास एक लिंक हो। यदि jsfiddle बंद हो जाता है, तो यह उत्तर पूरी तरह से बेकार हो जाता है।
माइक 'पोमैक्स' कामेरमेंस

5

यहां कॉलिन का एक संस्करण है wrapText()जो इसके साथ लंबवत केंद्रित पाठ का समर्थन करता है context.textBaseline = 'middle':

var wrapText = function (context, text, x, y, maxWidth, lineHeight) {
    var paragraphs = text.split("\n");
    var textLines = [];

    // Loop through paragraphs
    for (var p = 0; p < paragraphs.length; p++) {
        var line = "";
        var words = paragraphs[p].split(" ");
        // Loop through words
        for (var w = 0; w < words.length; w++) {
            var testLine = line + words[w] + " ";
            var metrics = context.measureText(testLine);
            var testWidth = metrics.width;
            // Make a line break if line is too long
            if (testWidth > maxWidth) {
                textLines.push(line.trim());
                line = words[w] + " ";
            }
            else {
                line = testLine;
            }
        }
        textLines.push(line.trim());
    }

    // Move text up if centered vertically
    if (context.textBaseline === 'middle')
        y = y - ((textLines.length-1) * lineHeight) / 2;

    // Render text on canvas
    for (var tl = 0; tl < textLines.length; tl++) {
        context.fillText(textLines[tl], x, y);
        y += lineHeight;
    }
};

5

यदि आपको केवल पाठ की दो पंक्तियों की आवश्यकता है, तो आप उन्हें दो अलग-अलग भरण कॉल में विभाजित कर सकते हैं और प्रत्येक को एक अलग आधार रेखा दे सकते हैं।

ctx.textBaseline="bottom";
ctx.fillText("First line", x-position, y-position);
ctx.textBaseline="top";
ctx.fillText("Second line", x-position, y-position);

4

यह सवाल कैनवास के काम करने के तरीके के बारे में नहीं सोच रहा है। यदि आप एक लाइन ब्रेक चाहते हैं तो बस अपने अगले के निर्देशांक समायोजित करें ctx.fillText

ctx.fillText("line1", w,x,y,z)
ctx.fillText("line2", w,x,y,z+20)

3

मुझे लगता है कि आप अभी भी CSS पर भरोसा कर सकते हैं

ctx.measureText().height doesnt exist.

सौभाग्य से, सीएसएस हैक-आर्डी के माध्यम से (सीएसएस माप का उपयोग करने के पुराने कार्यान्वयन को ठीक करने के लिए और अधिक तरीकों के लिए SeeTypographic मेट्रिक्स), हम एक ही फ़ॉन्ट-गुणों के साथ ऑफसेट के माप के माध्यम से पाठ की ऊंचाई पा सकते हैं:

var d = document.createElement(”span”);
d.font = 20px arial
d.textContent = Hello world!”
var emHeight = d.offsetHeight;

से: http://www.html5rocks.com/en/tutorials/canvas/texteffects/


यह एक अच्छा समाधान है यदि आपके पास एक तत्व बनाने की स्मृति है जो हर बार आपको मापने की आवश्यकता है। आप भी कर सकते हैं ctx.save()तो, ctx.font = '12pt Arial' है, तो parseInt( ctx.font, 10 )। ध्यान दें कि मैं इसे सेट करते समय 'pt' का उपयोग करता हूं। यह तब पीएक्स में अनुवाद करेगा और फ़ॉन्ट की ऊंचाई के रूप में खपत के लिए एक अंक में बदल सकता है।
एरिक होडोंस्की

3

मैंने यहां इस परिदृश्य के लिए एक छोटी सी लाइब्रेरी बनाई: कैनवस-टीएक्सटी

यह बहु-पंक्ति में पाठ प्रस्तुत करता है और यह सभ्य संरेखण मोड प्रदान करता है।

इसका उपयोग करने के लिए, आपको इसे स्थापित करने या CDN का उपयोग करने की आवश्यकता होगी।

स्थापना

npm install canvas-txt --save

जावास्क्रिप्ट

import canvasTxt from 'canvas-txt'

var c = document.getElementById('myCanvas')
var ctx = c.getContext('2d')

var txt = 'Lorem ipsum dolor sit amet'

canvasTxt.fontSize = 24

canvasTxt.drawText(ctx, txt, 100, 200, 200, 200)

यह एक अदृश्य बॉक्स में टेक्स्ट को स्थिति / आयामों के साथ प्रस्तुत करेगा:

{ x: 100, y: 200, height: 200, width: 200 }

उदाहरण फिडल

/* https://github.com/geongeorge/Canvas-Txt  */

const canvasTxt = window.canvasTxt.default;
const ctx = document.getElementById('myCanvas').getContext('2d');

const txt = "Lorem ipsum dolor sit amet";
const bounds = { width: 240, height: 80 };

let origin = { x: ctx.canvas.width / 2, y: ctx.canvas.height / 2, };
let offset = { x: origin.x - (bounds.width / 2), y: origin.y - (bounds.height / 2) };

canvasTxt.fontSize = 20;

ctx.fillStyle = '#C1A700';
ctx.fillRect(offset.x, offset.y, bounds.width, bounds.height);

ctx.fillStyle = '#FFFFFF';
canvasTxt.drawText(ctx, txt, offset.x, offset.y, bounds.width, bounds.height);
body {
  background: #111;
}

canvas {
  border: 1px solid #333;
  background: #222; /* Could alternatively be painted on the canvas */
}
<script src="https://unpkg.com/canvas-txt@2.0.6/build/index.js"></script>

<canvas id="myCanvas" width="300" height="160"></canvas>


मैंने आगे बढ़कर "स्व-दस्तावेज" उदाहरण की मदद के लिए कुछ चर को परिभाषित किया। यह कैनवास के भीतर बाउंडिंग बॉक्स को केंद्र में रखता है। मैंने पीछे एक आयत भी जोड़ी है, इसलिए आप वास्तव में इसे संबंध में केंद्रित देख सकते हैं। अच्छा कार्य! +1 एक छोटी बात जो मैंने देखी वह यह है कि लपेटने वाली लाइनों में उनके प्रमुख स्थान दबे नहीं होंगे। आप प्रत्येक पंक्ति को ट्रिम करना चाह सकते हैं जैसे ctx.fillText(txtline.trim(), textanchor, txtY)मैंने केवल आपकी वेबसाइट पर आपके इंटरैक्टिव डेमो में इस पर ध्यान दिया है।
श्री पॉलीविरल

@ Mr.Polywhirl उत्तर को साफ़ करने के लिए धन्यवाद। मैंने ट्रिम मुद्दा तय कर दिया है और 2.0.9संस्करण प्रकाशित किया है । डेमो संस्करण पैकेज संस्करण को अपडेट करके तय किया गया है। कई स्थानों के साथ एक समस्या है। मुझे नहीं पता कि एक राय पैकेज के साथ जाना या समस्या को अनदेखा करना बेहतर है। इसके लिए कई जगहों से अनुरोध मिल रहे हैं। मैं आगे गया और वैसे भी ट्रिम जोड़ा। Lorem ipsum dolor, sit <many spaces> amet यही कारण था कि मैंने इसे पहले स्थान पर नहीं किया। आपको क्या लगता है कि मुझे कई स्थानों पर विचार करना चाहिए और केवल एक होने पर हटा दें?
जौन जॉर्ज

संपादित करें: ऐसा लगता है कि स्टैकऑवरफ्लो कोड ब्लॉक मल्टी स्पेस को नजरअंदाज करता है
जियोन जॉर्ज

2

मुझे नहीं लगता कि यह संभव है और न ही, लेकिन इसके लिए एक वर्कअराउंड एक <p>तत्व बनाना है और इसे जावास्क्रिप्ट के साथ पोजिशन करना है।


हां, यही मैं करने की सोच रहा हूं। यह सिर्फ इतना है कि fillText()और strokeText(), आप सीएसएस क्या कर सकते हैं इससे परे चीजें कर सकते हैं।
टॉवर

मैंने इसका परीक्षण नहीं किया है, लेकिन मुझे लगता है कि यह एक बेहतर समाधान हो सकता है - फिलटेक्स्ट () का उपयोग करते हुए अन्य समाधान यहां हैं ताकि पाठ का चयन नहीं किया जा सके (या संभवतः चिपकाया जाए)।
जेरी अशर

2

मैं एक ही समस्या होने के कारण इस पार हुआ। मैं वैरिएबल फॉन्ट साइज़ के साथ काम कर रहा हूँ, इसीलिए इसे ध्यान में रखना चाहिए:

var texts=($(this).find('.noteContent').html()).split("<br>");
for (var k in texts) {
    ctx.fillText(texts[k], left, (top+((parseInt(ctx.font)+2)*k)));
}

जहाँ .noteContent उपयोगकर्ता द्वारा संपादित की गई सामग्री है, यह (यह एक jQuery के प्रत्येक फ़ंक्शन में नेस्टेड है), और ctx.font "14px एरियल" है (ध्यान दें कि पिक्सेल आकार पहले आता है)


0

कैनवास तत्व ऐसे वर्णों का समर्थन नहीं करता है जैसे कि newline '\ n', टैब '\ t' या <br /> टैग।

कोशिश करो:

var newrow = mheight + 30;
ctx.fillStyle = "rgb(0, 0, 0)";
ctx.font = "bold 24px 'Verdana'";
ctx.textAlign = "center";
ctx.fillText("Game Over", mwidth, mheight); //first line
ctx.fillText("play again", mwidth, newrow); //second line 

या शायद कई लाइनें:

var textArray = new Array('line2', 'line3', 'line4', 'line5');
var rows = 98;
ctx.fillStyle = "rgb(0, 0, 0)";
ctx.font = "bold 24px 'Verdana'";
ctx.textAlign = "center";
ctx.fillText("Game Over", mwidth, mheight); //first line

for(var i=0; i < textArray.length; ++i) {
rows += 30;
ctx.fillText(textArray[i], mwidth, rows); 
}  

0

समस्या के लिए मेरा ES5 समाधान:

var wrap_text = (ctx, text, x, y, lineHeight, maxWidth, textAlign) => {
  if(!textAlign) textAlign = 'center'
  ctx.textAlign = textAlign
  var words = text.split(' ')
  var lines = []
  var sliceFrom = 0
  for(var i = 0; i < words.length; i++) {
    var chunk = words.slice(sliceFrom, i).join(' ')
    var last = i === words.length - 1
    var bigger = ctx.measureText(chunk).width > maxWidth
    if(bigger) {
      lines.push(words.slice(sliceFrom, i).join(' '))
      sliceFrom = i
    }
    if(last) {
      lines.push(words.slice(sliceFrom, words.length).join(' '))
      sliceFrom = i
    }
  }
  var offsetY = 0
  var offsetX = 0
  if(textAlign === 'center') offsetX = maxWidth / 2
  for(var i = 0; i < lines.length; i++) {
    ctx.fillText(lines[i], x + offsetX, y + offsetY)
    offsetY = offsetY + lineHeight
  }
}

इस मुद्दे पर अधिक जानकारी मेरे ब्लॉग पर है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.