Text wrap in a element

后端 未结 10 2180
[愿得一人]
[愿得一人] 2020-11-29 02:43

I am trying to add text on an image using the element. First the image is drawn and on the image the text is drawn. So far so good.

But w

相关标签:
10条回答
  • 2020-11-29 02:53

    A possible method (not completely tested, but as for now it worked perfectly)

        /**
         * Divide an entire phrase in an array of phrases, all with the max pixel length given.
         * The words are initially separated by the space char.
         * @param phrase
         * @param length
         * @return
         */
    function getLines(ctx,phrase,maxPxLength,textStyle) {
        var wa=phrase.split(" "),
            phraseArray=[],
            lastPhrase=wa[0],
            measure=0,
            splitChar=" ";
        if (wa.length <= 1) {
            return wa
        }
        ctx.font = textStyle;
        for (var i=1;i<wa.length;i++) {
            var w=wa[i];
            measure=ctx.measureText(lastPhrase+splitChar+w).width;
            if (measure<maxPxLength) {
                lastPhrase+=(splitChar+w);
            } else {
                phraseArray.push(lastPhrase);
                lastPhrase=w;
            }
            if (i===wa.length-1) {
                phraseArray.push(lastPhrase);
                break;
            }
        }
        return phraseArray;
    }
    
    0 讨论(0)
  • 2020-11-29 02:53

    I am posting my own version used here since answers here weren't insufficient for me. The first word needed to be measured in my case, to be able to deny too long words from small canvas areas. And I needed support for 'break+space, 'space+break' or double-break/paragraph-break combos.

    wrapLines: function(ctx, text, maxWidth) {
        var lines = [],
            words = text.replace(/\n\n/g,' ` ').replace(/(\n\s|\s\n)/g,'\r')
            .replace(/\s\s/g,' ').replace('`',' ').replace(/(\r|\n)/g,' '+' ').split(' '),
            space = ctx.measureText(' ').width,
            width = 0,
            line = '',
            word = '',
            len = words.length,
            w = 0,
            i;
        for (i = 0; i < len; i++) {
            word = words[i];
            w = word ? ctx.measureText(word).width : 0;
            if (w) {
                width = width + space + w;
            }
            if (w > maxWidth) {
                return [];
            } else if (w && width < maxWidth) {
                line += (i ? ' ' : '') + word;
            } else {
                !i || lines.push(line !== '' ? line.trim() : '');
                line = word;
                width = w;
            }
        }
        if (len !== i || line !== '') {
            lines.push(line);
        }
        return lines;
    }
    

    It supports any variants of lines breaks, or paragraph breaks, removes double spaces, as well as leading or trailing paragraph breaks. It returns either an empty array if the text doesn't fit. Or an array of lines ready to draw.

    0 讨论(0)
  • 2020-11-29 02:55

    This should bring the lines correctly from the textbox:-

     function fragmentText(text, maxWidth) {
        var lines = text.split("\n");
        var fittingLines = [];
        for (var i = 0; i < lines.length; i++) {
            if (canvasContext.measureText(lines[i]).width <= maxWidth) {
                fittingLines.push(lines[i]);
            }
            else {
                var tmp = lines[i];
                while (canvasContext.measureText(tmp).width > maxWidth) {
                    tmp = tmp.slice(0, tmp.length - 1);
                }
                if (tmp.length >= 1) {
                    var regex = new RegExp(".{1," + tmp.length + "}", "g");
                    var thisLineSplitted = lines[i].match(regex);
                    for (var j = 0; j < thisLineSplitted.length; j++) {
                        fittingLines.push(thisLineSplitted[j]);
                    }
                }
            }
        }
        return fittingLines;
    

    And then get draw the fetched lines on the canvas :-

     var lines = fragmentText(textBoxText, (rect.w - 10)); //rect.w = canvas width, rect.h = canvas height
                        for (var showLines = 0; showLines < lines.length; showLines++) { // do not show lines that go beyond the height
                            if ((showLines * resultFont.height) >= (rect.h - 10)) {      // of the canvas
                                break;
                            }
                        }
                        for (var i = 1; i <= showLines; i++) {
                            canvasContext.fillText(lines[i-1], rect.clientX +5 , rect.clientY + 10 + (i * (resultFont.height))); // resultfont = get the font height using some sort of calculation
                        }
    
    0 讨论(0)
  • 2020-11-29 03:07

    context.measureText(text).width is what you're looking for...

    0 讨论(0)
提交回复
热议问题