形状内文本环绕的算法

时间:2010-06-15 19:20:53

标签: javascript algorithm graphics text word-wrap

我正在寻找一种算法来将文本包装在非矩形形状内,最好是基于Knuth和Plass算法。最难的部分是由于文本中的字体大小不同,线条可能具有不同的高度。下图是算法应该能够生成的示例。

Text shaped like a heart

3 个答案:

答案 0 :(得分:5)

修改,更新

尝试

text / html

    
        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g

JS

var text =  "Lorem ipsum dolor sit amet," // `string` , `array` 
, i = -1
, elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });


        Lorem ipsum do              lor sit amet,  
     consectetur adipisci         ng elit. Vivamus b
   landit nisl eu posuere s     uscipit. Etiam at quam
  sed nulla consequat finibu   s et eget ligula. Nam sit
 amet imperdiet eros. Ut a congue nibh. Sed ac arcu non r
isus commodo lobortis et at lorem. Pellentesque pulvinar v
enenatis pellentesque. Praesent sed pulvinar justo. Ut nec
 turpis lectus. Suspendisse porta ipsum orci, nec vestibul
um tellus luctus quis. Morbi eleifend vel nibh sed rutrum.
 Etiam feugiat, nunc et efficitur accumsan, quam magna lac
 inia neque, eu ullamcorper purus turpis eget urna. Etiam
   lacus mi, gravida vel mollis ut, viverra sed ipsum. M
   auris in augue turpis.Nulla facilisi. In tristique t
     ortor sit amet leo cursus, sit amet varius ligula
       sollicitudin. Mauris commodo et sapien id sce
        lerisque. Integer et diam eget arcu bibend
           um ornare a in tortor. Lorem ipsum do
              lor sit amet, consectetur adip
                 iscing elit. Aliquam veh
                    icula diam ac laor
                       eet tincidun
                         t. Integ
                           er se
                            d t
                             e



var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus blandit nisl eu posuere suscipit. Etiam at quam sed nulla consequat finibus et eget ligula. Nam sit amet imperdiet eros. Ut a congue nibh. Sed ac arcu non risus commodo lobortis et at lorem. Pellentesque pulvinar venenatis pellentesque. Praesent sed pulvinar justo. Ut nec turpis lectus. Suspendisse porta ipsum orci, nec vestibulum tellus luctus quis. Morbi eleifend vel nibh sed rutrum. Etiam feugiat, nunc et efficitur accumsan, quam magna lacinia neque, eu ullamcorper purus turpis eget urna. Etiam lacus mi, gravida vel mollis ut, viverra sed ipsum. Mauris in augue turpis."

+ "Nulla facilisi. In tristique tortor sit amet leo cursus, sit amet varius ligula sollicitudin. Mauris commodo et sapien id scelerisque. Integer et diam eget arcu bibendum ornare a in tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vehicula diam ac laoreet tincidunt. Integer sed tellus sit amet lacus bibendum tristique a a nulla. Quisque venenatis suscipit est eget ultricies. Quisque ac orci convallis, interdum enim quis, dictum justo. Phasellus tincidunt nisi vitae justo fringilla, sit amet pellentesque enim dictum. Duis porttitor convallis feugiat. Sed lectus massa, consectetur et vestibulum a, egestas ac eros. Proin mollis ligula tellus, a dignissim eros placerat sed. Donec vel blandit magna. Etiam quis tortor rhoncus, porta ante et, pretium mi."

+ "Vestibulum ut risus convallis, sagittis orci sed, faucibus erat. Aliquam maximus suscipit lectus, vel pellentesque enim dictum nec. Sed et ex id mauris finibus molestie. Aliquam erat volutpat. Etiam nec ultricies est. Aenean vitae mi id neque vulputate suscipit vel vitae ante. Nam sit amet mi diam. Phasellus efficitur faucibus viverra. Proin cursus purus et tortor dictum elementum. Nunc vehicula erat volutpat, rutrum metus bibendum, blandit sem."

+ "Nam eu ante eros. Sed pellentesque accumsan neque, eu vulputate lectus luctus ac. In hac habitasse platea dictumst. Nulla vitae dictum diam. Sed eget mauris in felis luctus luctus. Mauris volutpat lacus in est dignissim, sit amet venenatis ipsum laoreet. Phasellus semper id velit ut tristique. Proin dictum erat at mauris lacinia blandit. Ut scelerisque mi ex, ut pretium elit commodo sit amet. Praesent faucibus turpis tellus, ac vulputate felis aliquet eget. Ut est urna, dignissim nec risus sit amet, eleifend lacinia enim. Donec non massa in purus efficitur placerat. Donec accumsan neque elit, eget vulputate metus finibus quis. Ut interdum sem vel felis imperdiet pretium. Integer erat neque, bibendum id egestas nec, facilisis sed massa."

+ "Curabitur sit amet mattis odio. Mauris mattis turpis eu lectus eleifend, semper ultrices elit malesuada. Mauris fringilla arcu sed sem vehicula vulputate. Donec semper nisl ut urna bibendum, quis eleifend tortor commodo. Pellentesque vehicula est et neque vulputate accumsan. Duis faucibus sodales lacus et suscipit. Pellentesque tortor enim, pulvinar scelerisque pretium non, aliquam sed risus. Vestibulum aliquam dolor ipsum, eget pretium ante fermentum a. Donec semper lectus pulvinar tellus hendrerit sagittis. Nunc blandit sed ligula vel consequat. Etiam sed est quis nulla blandit blandit. Sed in enim pulvinar elit accumsan faucibus sed sodales lorem. Aenean ac efficitur arcu, sed fringilla lectus."

, i = -1;
var elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });

<pre>    
        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g
</pre>
&#13;
&#13;
&#13;

答案 1 :(得分:4)

对于一个简单的算法,我们假设您可以计算每个单词周围的边界框,并且您有一个图像,其中包含您要填充的形状的蒙版。

从图像蒙版的顶部向下扫描,直到找到与第一个单词一样长的行。看看是否可以将其向下延伸到边界框大小的矩形中。如果是这样,请将第一个单词放在那里。如果没有,请继续扫地。

删除单词后,查看是否可以将边界框扩展为(第一个框+第二个框+空格)的宽度和最大高度(第一个框,第二个框)。如果是这样,请将第二个字放在那里。如果没有,请将第一个单词从左到右居中放置在适合图像蒙版(从左到右)的边界框内,从蒙版中移除该边界框,然后继续。

你可以通过坚持线条具有相同的基线即使被形状打破(例如,心脏的顶部小块上的线条),也可以使它略微变得更加迷人;然后你需要有一个替代“沿着这个基线继续”的条件。但是上面的基本思想,使用一个图像蒙板,你用来试图在你完成之后去掉那些被删除的矩形,就可以完成这项工作。

(使用几何操作比这里描述的基于像素的操作更快,但是人们必须担心所有的情况,以确定边界框如何适合任意多边形,这里有点长的解释。)

答案 2 :(得分:0)

让我们说每个字母都有一个特定的尺寸(宽度和高度,在这种情况下,我们可能只关心宽度,因为所有字母都有相同的高度)。然后我们需要以下内容:

  1. 每个单词的被包裹的对象 - 以确保没有单词的碎片
  2. 给出每个单词的宽度。
  3. 将多边形划分为作为单词高度的块。所以你有x个水平条纹组成图像。
  4. 然后,如果要在里面刻字,找到内部多边形的宽度。这意味着您要移除心脏的圆形边缘。如果垂直线可以与条带上的心脏边缘相交,则可以移除圆边。
  5. 现在我们已经知道了每个图像条的大小,我们说我们有这个(我使用任意宽度的单位):

    [_________] [__________]  <-- 10 width (5 each)
      [__________________] <-- 9 width
        [_____________] <-- 7 width   
           [_______] <-- 5 width
             [___] <-- 3 width
              [_] <-- 2 width
    
    编辑:刚刚意识到内心是多么丑陋,我的坏。

    现在我们需要每个单词的大小,然后按顺序插入它们。每个块具有x宽度,每个字对象具有y宽度。如果y宽度> x宽度,我们移动到下一行并检查

    considering we already have widths
    while(image.hasNextChunk()){
        currentChunk = image.nextChunk();
        if(currentWord.width < currentChunk.width) //insert here and then change currentWord to nextWord
        ...
    }
    

    我认为这就是你想要的,但我并不完全确定。如果这有帮助,请告诉我! :)