最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Need to split a string to character and align to the container equally - Stack Overflow

programmeradmin1浏览0评论

origin

result

I want to split a string into character, and make each of the character fit the container equally, this is my work for the time being: /

The first item must attached to the left, and the last item must attached to the right.

  $.fn.textjustify = function() {
        return this.each(function() {
            var text = $(this).text(),
                containerWidth = $(this).width(),
                character = '',
                string = '',
                singleWidth = 0,
                firstItemWidth = 0,
                lastItemWidth = 0,
                alignWidth = 0;

            if ('' !== text) {
                $(this).css('position', 'relative');
                textArray = text.split('');
                singleWidth = Math.floor(containerWidth / textArray.length);

                for (i in textArray) {
                    // Wrapp with div to get character width
                    character = ('' === $.trim(textArray[i])) ? '&nbsp' : textArray[i];
                    string += '<span>' + character + '</span>';
                }

                $(this).html(string);

                firstItemWidth = $(this).find('span:first').width();
                lastItemWidth = $(this).find('span:last').width();
                alignWidth = containerWidth - (firstItemWidth + lastItemWidth);

                $(this).find('span').each(function(i) {
                    if (0 === parseInt(i)) {
                        // The first item
                        $(this).css({position: 'absolute', left: 0, top: 0});
                    } else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
                        // The last item
                        $(this).css({position: 'absolute', right: 0, top: 0});
                    } else {
                        // Other items
                        // stuck in here......
                        var left = (i * singleWidth) - $(this).width() + firstItemWidth;
                        $(this).css({position: 'absolute', left: left, top: 0});
                    }
                });

            }
        });
    }

stuck in the algorithm of middle items's position.

origin

result

I want to split a string into character, and make each of the character fit the container equally, this is my work for the time being: http://jsfiddle/d5fu9/

The first item must attached to the left, and the last item must attached to the right.

  $.fn.textjustify = function() {
        return this.each(function() {
            var text = $(this).text(),
                containerWidth = $(this).width(),
                character = '',
                string = '',
                singleWidth = 0,
                firstItemWidth = 0,
                lastItemWidth = 0,
                alignWidth = 0;

            if ('' !== text) {
                $(this).css('position', 'relative');
                textArray = text.split('');
                singleWidth = Math.floor(containerWidth / textArray.length);

                for (i in textArray) {
                    // Wrapp with div to get character width
                    character = ('' === $.trim(textArray[i])) ? '&nbsp' : textArray[i];
                    string += '<span>' + character + '</span>';
                }

                $(this).html(string);

                firstItemWidth = $(this).find('span:first').width();
                lastItemWidth = $(this).find('span:last').width();
                alignWidth = containerWidth - (firstItemWidth + lastItemWidth);

                $(this).find('span').each(function(i) {
                    if (0 === parseInt(i)) {
                        // The first item
                        $(this).css({position: 'absolute', left: 0, top: 0});
                    } else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
                        // The last item
                        $(this).css({position: 'absolute', right: 0, top: 0});
                    } else {
                        // Other items
                        // stuck in here......
                        var left = (i * singleWidth) - $(this).width() + firstItemWidth;
                        $(this).css({position: 'absolute', left: left, top: 0});
                    }
                });

            }
        });
    }

stuck in the algorithm of middle items's position.

Share Improve this question edited Dec 12, 2013 at 10:23 Chan asked Dec 12, 2013 at 9:27 ChanChan 1,9696 gold badges29 silver badges38 bronze badges 1
  • Posted a fix where you loop all divs with the "spread" class and then fix the chars within them. – KungWaz Commented Dec 12, 2013 at 10:23
Add a ment  | 

6 Answers 6

Reset to default 1

I think this is the simplest solution. Works great with All browsers (IE included)

  1. without plex (and unreliable) width detection and calculation.
  2. without specifying the words width/height
  3. without relative/absolute positioning
  4. using pure HTML/CSS/JS/JQ tricks.

Working Fiddle

HTML:(very simple)

<div class="Box">
    <div class="Centered">
        <div class="Spread">Lighting</div>
        <div class="Spread">我是中文</div>
    </div>
</div>

CSS:(neat and tricky)

*
{
    margin: 0;
    padding: 0;
}
.Box
{
    width: 150px;
    height: 150px;
    border: 1px solid red;
    margin: 6px;
}
.Box:before
{
    content: '';
    display: inline-block;
    height: 100%;
    vertical-align: middle;
    margin-left: -5px;
}
.Centered
{
    display: inline-block;
    vertical-align: middle;
    width: 100%;
}
.Spread
{
    width: 100%;
    text-align: justify;
    font-size: 0;
}
    .Spread span
    {
        font-size: medium;
    }
.Spread:after
{
    content: '';
    display: inline-block;
    height: 0px;
    width: 100%;
}

JS/JQ:

$.fn.SplitText = function () {
    return this.each(function () {
            return $(this).html('<span>' + $(this).text().split('').join(' ') + '</span>');
    });
}

$(function () {
    $('.Spread').SplitText();
})

Explanations: as mentioned by wared in the ments, IE7 doesn't support the use of pseudo classes. but they are not necessary for the solution. Here's a Fiddle for IE7 (and all other browsers of course).

how the vertical aligning works? when vertical-align:middle; is used on an inline element, it will align the middle of this element with the other inline elements in the same line. that's why I'm creating an inline element with height:100%;, so when we align our inline element to his middle, it will actually be the middle of the container.

how the horizontal distribution works? taking advantage of the text-align:justify;, we create an empty inline element (height:0;) with width:100%;, we can imagine that it takes a full line, and the rest of the text takes the second line. using justify makes the second line spread evenly to take the exact space as the first.

let me know if you need more explanation.

I added a fixed with for spanelements for the widest char which was W in your fiddle with 15px.

span {
    width: 15px;
}

Then substracted 20px from container width which will be the free space on the sides later.

singleWidth = Math.floor((containerWidth-20) / textArray.length);

Added this extra Space to the firstitemWidth so that the other chars align correctly:

firstItemWidth = $(this).find('span:first').width() + 10;

And set the position of first and last to 10 from left and right here:

if (0 === parseInt(i)) {
               // The first item
               $(this).css({position: 'absolute', left: 10, top: 0});
} else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
               // The last item
               $(this).css({position: 'absolute', right: 10, top: 0});

Here is the updated Fiddle

I hope this will work out for you ;)

I have made a script for you if you do not mind left and right spaces. You can set the right and left margins making some little modifications.

$(document).ready(function(){

    var txt = $(".container").text(); //get the text
    var txt2 = "";
    var len = txt.length;

    $(".container").empty();  //clear the content

    for(i=0; i<len; i++) //surround all characters with span
    {
        txt2 += "<span>" + txt.substr(i,1) + "</span>";    
    }

    $(".container").html(txt2);

    $("span").css({"width":  Math.round($(".container").width())/len + "px", "display":"inline-block", "text-align":"center"});
});

Fiddle is here

Try this:

DEMO: http://jsfiddle/jc2mm/4/

JS:

$(".spread").each(function(idx, elem) {
    var titleElem = $(this),
        titleStr = titleElem.html(),
        charWidth = Math.floor(($(".box").width() / titleStr.length) * 100) / 100;

    titleElem.html("");

    for(var i = 0; i < titleStr.length; i++) {
        titleElem.append($("<span>", {"class" : "singleChar"}).css("width", charWidth).html(titleStr[i]));
    }
});

CSS:

.box {
    width: 150px;
    height: 150px;
    border: 1px solid red;
    margin: 6px;
}
.title {
    margin-top: 40px;
    height: 16px;
}
.singleChar {
    float: left;   
    text-align: center;
    display: block;
    min-height: 1px;
}

Try this: http://jsfiddle/d5fu9/5/

Each character is contained in a box of width singleWidth, left is puted counting the preceding character boxes, characters are centered. Changes:

$(this).css({width: singleWidth,position: 'absolute', left: 0, top: 0});

and

var left = i* singleWidth + (i-1)*(textArray.length-2)/(textArray.length+1);

and in CSS:

.spread {
    text-align: center;
}

Here is another version http://jsfiddle/d5fu9/6/ where leftmost and rightmost characters are attached to the border.

Modified width of a single character container:

singleWidth = Math.floor((containerWidth -firstItemWidth - lastItemWidth)/ (textArray.length-2));

and how much each inner character moves from the left:

var left = firstItemWidth+(i-1)* singleWidth ;

I've made this stuff : http://jsfiddle/wared/HDbA5/.

The idea is to use paddings to create space between chars. Tested with Chrome only. It seems to fail when the DIV has no explicit fixed width, and sometimes there is one pixel remaining, I haven't investigated. Lastly, this script does not support single characters. If you're interested in this answer, this job is for you :)


I must show some code to be able to post this answer, so, here it is :

<div><span>hello</span></div>
jQuery.fn.justify = function () {
    return this.each(function () {
        var el = $(this),
            ct = el.parent(),
            chars = el.text().split(''),
            bits = (chars.length - 1) * 2,
            freeSpace = ct.width() - el.width(),
            bitWidth = Math.floor(freeSpace / bits),
            gap = freeSpace % bits;
        el.html(jQuery.map(chars, function (char, i) {
            var paddings = ['0', null, '0', null];
            if (!i) {
                paddings[1] = (bitWidth + (gap && (--gap, 1))) + 'px';
                paddings[3] = '0';
            } else if (i + 1 === chars.length) {
                paddings[1] = '0';                
                paddings[3] = (bitWidth + (gap && (--gap, 1))) + 'px';
            } else {
                paddings[1] = (bitWidth + (gap && (--gap, 1))) + 'px';                
                paddings[3] = (bitWidth + (gap && (--gap, 1))) + 'px';
            }
            return '<span style="padding:' + paddings.join(' ') + '">' + char + '</span>';
        }).join(''));
    });
};

A "bit" is a portion of the free space. It's half the space between two characters :

"abc"   : 4 bits ("a..b..c").
"ab cd" : 8 bits ("a..b.. ..c..d").

The "gap" is the number of pixels remaining after splitting the free space into bits. Those pixels are assigned to each "bit" until no pixels remain. Let's say gap = 1 :

bitWidth + (gap && (--gap, 1)) // gap = gap - 1 THEN bitWidth + 1
// next bit
bitWidth + (gap && (--gap, 1)) // bitWidth + 0
发布评论

评论列表(0)

  1. 暂无评论