开发者

Pre-formatting text to prevent reflowing

I've written a fairly simple script that will take elements (in this case, <p> elements are the main concern) and type their contents out like a typewriter, one by one.

The problem is that as it types, when it reaches the edge of the container mid-word, it reflows the text and jumps to the next line (like word wrap in any text editor).

This is, of course, expected behavior; however, I would like to pre-format the text so that this does not happen.

I figure that inserting <br> before the word that will wrap would be the best solution, but I'm not quite sure what the best way to go about doing that is that supports all font sizes and container widths, while also keeping any HTML tags intact.

I figure something involving a hidden <span> element, adding text to it gradually and checking its width against the container width might be on the right track, but I'm not quite sure how to actually put this together. Any help or suggestions on better methods would be appreciated.


Edit:

I've managed to write something that sort of works using jQuery, although it's very sloppy, and more importantly, sometimes it seems to skip words, and I can't figure out why. #content is the name of the container, and #ruler is the name of the hidden <span>. I'm sure there's a much better way to do this.

function formatText(html) {
    var textArray = html.split(" ");
    var assembledLine = 开发者_JAVA百科"";
    var finalArray = new Array();
    var lastI = 0;
    var firstLine = true;
    for(i = 0; i <= textArray.length; i++) {
        assembledLine = assembledLine + " " + textArray[i];
        $('#ruler').html(assembledLine);
        var lineWidth = $('#ruler').width();
        if ((lineWidth >= $('#content').width()) || (i == textArray.length)) {                  
            if (firstLine) { var tempArray = textArray.slice(lastI, i); }
            else { var tempArray = textArray.slice(lastI+1, i); }
            var finalLine = tempArray.join(" ");
            finalArray.push(finalLine);
            assembledLine = "";
            if (lineWidth > $('#content').width()) { i = i-1; }
            lastI = i;
            firstLine = false;
        }
    }
    return finalArray.join("<br>");
}


You could use the pre tag:

Which displays pre-formatted text,
or you could put the content into a div tag, set a fixed width, and script based upon that.


The best way (IMO) would be to add the whole word, but have the un-"typed" letters invisible. E.g:

H<span style="visibility: hidden;">ello</span>
He<span style="visibility: hidden;">llo</span>
Hel<span style="visibility: hidden;">lo</span>
Hell<span style="visibility: hidden;">o</span>
Hello

To make it easier, give the span a name, and delete it from the DOM each time.


A possible approach is to set p display inline (because default display-block will make p to consume all width even if it has just 1 character) and then as you 'type' check the element width.
Set a tolerance in px (25px for example) and once p's width reaches total available width minus width tolerance you insert <br />

I think this should work...


After playing with the code I edited into the question, I managed to get it working decently.

Code:

function formatText(html) {
    var textArray = html.split(" ");
    var assembledLine = "";
    var finalArray = new Array();
    var lastI = 0;
    var firstLine = true;
    for(i = 0; i <= textArray.length; i++) {
        assembledLine = assembledLine + " " + textArray[i];
        $('#ruler').html(assembledLine);
        var lineWidth = $('#ruler').width();
        if ((lineWidth >= $('#content').width()) || (i == textArray.length)) {                  
            if (firstLine) { var tempArray = textArray.slice(lastI, i); }
            else { var tempArray = textArray.slice(lastI+1, i); }
            var finalLine = tempArray.join(" ");
            finalArray.push(finalLine);
            assembledLine = "";
            if (lineWidth >= $('#content').width()) { i = i-1; }
            lastI = i;
            firstLine = false;
        }
    }
    return finalArray.join("<br>");
}

Not perfect, but it'll do. Thanks, everyone.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜