在JS和CSS

时间:2017-04-18 14:58:35

标签: javascript jquery html css

我试图找出如何计算和设置容器div的宽度,以便内部的文本正好是< = 2行。问题如下:给我一个文本,它是字体属性和“建议”宽度'X'px。我必须将文本放入宽度尽可能接近给定'X'px的div中,但要确保文本最多包含2行。

示例:

text: 'total after-cashback revenue from rewarded users'
font: font-family: 'Roboto-Regular';font-size: 14px;line-height: 19px;
X: 130px

solution: 180px
because: 
    total after-cashback revenue // this is 180px
    from rewarded users
NOTE: if I put the text into 1 line and divide the width into 2 I get width 154px which results into:
    total after-cashback
    revenue from rewarded
    users

示例2:

text: 'total shit'
font: font-family: 'Roboto-Regular';font-size: 14px;line-height: 19px;
X: 130px

solution: 130px
because:
    total shit // ~60px < 130px soo 130px will be enough and it is 1 line

祝你好运

3 个答案:

答案 0 :(得分:1)

我会采用这种方法:

  • 获取以限制大小为基础创建对象的px的默认空间。
  • 然后将两个线高的值作为最大值,并评估实际高度是否大于该值。
  • 如果它更多,则将其减小到最大高度并进行计算,以确保基础容器的相同面积与宽度成比例增加相辅相成。

检查此代码段:

$(document).ready(function(){
  $('div').each(function(){
    var $el   = $(this),
        maxH  = parseInt($el.css('line-height'))*2,
        actH  = $el.height(),
        actW  = $el.width();

    if(actH > maxH) {
      $el.height(maxH);
      var diff = actH/maxH;
      var newW = actW*diff
      $el.width(newW)
    }
  })
})
div {
  margin:10px;
  line-height:20px;
  width:300px;  
  color:#e1e1e1; 
  background:tomato;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Vitae repellat nihil laudantium ipsa error, impedit quos consectetur adipisicing elit. Vitae repellat nihil laudantium ipsa error, impedit quos , impedit quos consectetur adipisicing elit. Vitae repellat nihil laudantium ipsa error, impedit quos</div>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Vitae repellat nihil laudantium</div>
<div>Lorem ipsum</div>

具有不同字体大小的行示例//行高:

$(document).ready(function() {
  $('div').each(function() {
    var $el = $(this),
      maxH = parseInt($el.css('line-height')) * 2,
      actH = $el.height(),
      actW = $el.width();

    if (actH > maxH) {
      $el.height(maxH);
      var diff = actH / maxH;
      var newW = actW * diff
      $el.width(newW)
    }
  })
})
div {
  margin: 10px;
  font-size: 14px;
  line-height: 20px;
  width: 100px;
  color: #e1e1e1;
  background: tomato;
}

div.two {
  font-size: 18px;
  line-height: 25px;
}

div.third {
  font-size: 30px;
  line-height: 32px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>total after-cashback revenue from rewarded users</div>
<div class="two">total after-cashback revenue from rewarded users</div>
<div class="third">total after-cashback revenue from rewarded users</div>

答案 1 :(得分:0)

Sooo ...由于单词休息,这比你想的要复杂得多。也就是说,如果文本的中点位于该单词的中间,那么该单词不会跨越两行(这将是愚蠢的),因此它将包装到下一行:

somereallylongtextthatwillalwaysbetoolong somereallylongtextthatwillalwaysbetoolong dave
                                   midpoint ^
                                  max width v
somereallylongtextthatwillalwaysbetoolong   |
somereallylongtextthatwillalwaysbetoolong   |
dave

现在那个行太长了,导致最后一个词也被包裹下来。这最终可能会超过2行,但是随着更多行的增加,拾取过量的可能性(由于将长字包裹到可以将短字包装到可用空间中的行)增加。

我来到(在Unity中)的解决方案是采用迭代方法:查询文本想要的宽度,如果它在一行上。然后重复减去一些宽度并检查新的高度,直到它达到所需的比例(我对宽度:高度比(以像素为单位)感兴趣,但同样适用于总线:你可以检查是否所需的高度是正确的值。)

所以我建议做的就是你现在所拥有的,而不是“将宽度除以2,完成”是除以2,检查文本的高度是否为预期值,如果不是,则添加宽度为50像素(任意值)并再次检查。当文本的高度下降到所需的值时,就是循环终止时。

基本上,除以2将总是太短,除非它设法在空间上抓住,但这也是为什么它是一个很好的起点:我们知道我们可能 接近所需的值。然后,我们要做的就是继续增加一点宽度(最小宽度为1个字符,因为例如1个像素不太可能导致变化),直到尺寸扩大到足以让悬挂的单词弹回一行。 / p>

                                  max width+2 v
somereallylongtextthatwillalwaysbetoolong     |
somereallylongtextthatwillalwaysbetoolong dave|

无论“dave”出现在此字符串中的哪个位置,都会发生同样的情况。如果它是第一个单词,那么它将位于顶部的自己的行上。第二,然后在中间自己的线。在所有这三种情况下,只有2个宽度值的字符总是足以使它与两个“somereallylongtextthatwillalwaysbetoolong”部分中的一个相同。

答案 2 :(得分:0)

查看我的答案:http://jsfiddle.net/mp3por/eq4e8dy7/10/

function getTextWidth(text, font) {
  var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  var context = canvas.getContext("2d");
  context.font = font;

  var chunks = text.split(' ');
  var suggestedWidth = 130;
  var maxWidth = suggestedWidth;
  var chunkWidthMap = [];
  var i = 0;
  for (i = 0; i < chunks.length; i++) {
    chunkWidthMap.push(context.measureText(chunks[i]).width);
  }
  // console.log(chunkWidthMap);

  var spaceWidth = context.measureText(' ').width;
  var line1Width = 0,
    line2Width = 0;
  var line1Chunks = [],
    line2Chunks = [];
  for (i = 0; i < chunkWidthMap.length; i++) {
    //console.log(`${i}: line1Width: ${line1Width}, line2Width: ${line2Width}, chunkWidth: ${chunkWidthMap[i]}`);
    //console.log(line1Chunks);
    //console.log(line2Chunks);
    if (line1Width + chunkWidthMap[i] < maxWidth && line2Width <= 0) {
      //console.log('Adding to 1st line');
      line1Width += chunkWidthMap[i] + spaceWidth;
      line1Chunks.push(i);
      continue;
    } else if (line2Width + chunkWidthMap[i] < maxWidth) {
      //console.log('Adding to 2nd line');
      line2Width += chunkWidthMap[i];
      line2Chunks.push(i);
      continue;
    } else {
      //console.log('not enough space in both => restructure');
      while (line2Width + chunkWidthMap[i] > maxWidth) {
        var line2FirstWordIndex = line2Chunks.shift();
        line2Width -= chunkWidthMap[line2FirstWordIndex] - spaceWidth;
        line1Width += chunkWidthMap[line2FirstWordIndex] + spaceWidth;
        line1Chunks.push(line2FirstWordIndex);
        maxWidth = line1Width;
      }
    }
  }

  console.log('maxWidth: ' + maxWidth);

  return maxWidth;
};

$('#sex').width(getTextWidth("total after-cashback revenue from rewarded users", "14px  'Roboto'"));
console.log(getTextWidth("total after-cashback revenue from rewarded users", "14px  'Roboto'"));