javascript – 精确地截断一个字符串以适应给定的像素宽度

前端之家收集整理的这篇文章主要介绍了javascript – 精确地截断一个字符串以适应给定的像素宽度前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有时你有一些字符串必须适合一定的像素宽度.此功能尝试有效地执行此操作.请在下面发布您的建议或重构:)
function fitStringToSize(str,len) {
    var shortStr = str;
    var f = document.createElement("span");
    f.style.display = 'hidden';
    f.style.padding = '0px';
    document.body.appendChild(f);

    // on first run,check if string fits into the length already.
    f.innerHTML = str;
    diff = f.offsetWidth - len;

    // if string is too long,shorten it by the approximate 
    // difference in characters (to make for fewer iterations). 
    while(diff > 0)
    {
        shortStr = substring(str,(str.length - Math.ceil(diff / 5))) + '…';
        f.innerHTML = shortStr;
        diff = f.offsetWidth - len;
    }

    while(f.lastChild) {
        f.removeChild(f.lastChild);
    }
    document.body.removeChild(f);

    // if the string was too long,put the original string 
    // in the title element of the abbr,and append an ellipsis
    if(shortStr.length < str.length)
    {
        return '<abbr title="' + str + '">' + shortStr + '</abbr>';
    }
    // if the string was short enough in the first place,just return it.
    else
    {
        return str;
    }
}

更新:
@一些下面的解决方案好多了;请使用.

更新2:
现在的代码gist;随意分叉并提交补丁:)

解决方法

你的代码有几个问题.

>为什么/ 5?字符的宽度取决于font-family和font-size.
>你必须在abbr标题中转义str(否则“将使代码无效”).
> diff不被声明,并且结束于全局范围
>子串不应该这样工作.你使用的是什么浏览器?
> hidden不是style.display的有效值.要隐藏它,你应该使用值none,但是浏览器不会计算offsetWidth.改用style.visibility =“隐藏”.
搜索正确的长度是非常低效的.
>必须逃脱& lt; / abbr& gt“

我为您重写了它,并添加了className,因此您可以使用样式来设置font-family和font-size. Fooz先生建议您使用鼠标悬停来显示整个字符串.这是不必要的,因为现代浏览器为你做的(用FF,IE,Opera和Chrome测试)

function fitStringToSize(str,len,className) {
    var result = str; // set the result to the whole string as default
    var span = document.createElement("span");
    span.className=className; //Allow a classname to be set to get the right font-size.
    span.style.visibility = 'hidden';
    span.style.padding = '0px';
    document.body.appendChild(span);


    // check if the string don't fit 
    span.innerHTML = result;
    if (span.offsetWidth > len) {
        var posStart = 0,posMid,posEnd = str.length;
        while (true) {
            // Calculate the middle position
            posMid = posStart + Math.ceil((posEnd - posStart) / 2);
            // Break the loop if this is the last round
            if (posMid==posEnd || posMid==posStart) break;

            span.innerHTML = str.substring(0,posMid) + '&hellip;';

            // Test if the width at the middle position is
            // too wide (set new end) or too narrow (set new start).
            if ( span.offsetWidth > len ) posEnd = posMid; else posStart=posMid;
        }
        //Escape
        var title = str.replace("\"","&#34;");
        //Escape < and >
        var body = str.substring(0,posStart).replace("<","&lt;").replace(">","&gt;");
        result = '<abbr title="' + title + '">' + body + '&hellip;<\/abbr>';
    }
    document.body.removeChild(span);
    return result;
    }

编辑:
在测试一下我发现了几个bug.

我用Math.ceil代替了
打算Math.floor(我责怪这个
那个英文不是我的母语
语言)
>如果输入的字符串有html标签
那么结果将是未定义的
(截断标签是不好的
中间或离开打开的标签)

改进:

>删除所有地方复制到跨度的字符串.您仍然可以使用html实体,但不允许使用标签(<和>将被显示)
>重写while语句(它是一个
更快,但主要原因
是摆脱那个bug
造成额外的回合和摆脱
的break-statement)
>将函数重命名为fitStringToWidth

版本2:

function fitStringToWidth(str,width,className) {
  // str    A string where html-entities are allowed but no tags.
  // width  The maximum allowed width in pixels
  // className  A CSS class name with the desired font-name and font-size. (optional)
  // ----
  // _escTag is a helper to escape 'less than' and 'greater than'
  function _escTag(s){ return s.replace("<","&gt;");}

  //Create a span element that will be used to get the width
  var span = document.createElement("span");
  //Allow a classname to be set to get the right font-size.
  if (className) span.className=className;
  span.style.display='inline';
  span.style.visibility = 'hidden';
  span.style.padding = '0px';
  document.body.appendChild(span);

  var result = _escTag(str); // default to the whole string
  span.innerHTML = result;
  // Check if the string will fit in the allowed width. NOTE: if the width
  // can't be determined (offsetWidth==0) the whole string will be returned.
  if (span.offsetWidth > width) {
    var posStart = 0,posEnd = str.length,posLength;
    // Calculate (posEnd - posStart) integer division by 2 and
    // assign it to posLength. Repeat until posLength is zero.
    while (posLength = (posEnd - posStart) >> 1) {
      posMid = posStart + posLength;
      //Get the string from the beginning up to posMid;
      span.innerHTML = _escTag(str.substring(0,posMid)) + '&hellip;';

      // Check if the current width is too wide (set new end)
      // or too narrow (set new start)
      if ( span.offsetWidth > width ) posEnd = posMid; else posStart=posMid;
    }

    result = '<abbr title="' +
      str.replace("\"","&quot;") + '">' +
      _escTag(str.substring(0,posStart)) +
      '&hellip;<\/abbr>';
  }
  document.body.removeChild(span);
  return result;
}

猜你在找的JavaScript相关文章