【问题标题】:Getting integer box widths instead of decimal values: Math.ceil() doesn't round up获取整数框宽度而不是十进制值:Math.ceil() 不会四舍五入
【发布时间】:2017-12-07 16:53:58
【问题描述】:

我有一个 Bootstrap 导航栏。使用 Chrome DevTools 检查时,我注意到这个(以及其他浏览器,我想)返回十进制框宽度而不是整数(即 83.06 而不是 83)。

对于与其他一些元素的像素完美对齐,我需要“转换为整数”这个数字,并避免按钮在 2 个以上的单词中折叠,我需要“四舍五入”它:简而言之,83.06 应该变成84(而不是83)。

我知道的唯一方法是使用 JavaScript,所以我做了这个脚本:

$(window).on('resize', function(){ // recalculate when resizing window
  if (window.innerWidth > 768) { // only in 'desktop' version(s), smaller devices don't need recalculation
    $('.navbar-nav').find('> li:not(.hidden-sm)').each(function(){
      var width = $(this).children('a').outerWidth(); // for each valid 'li', take its 'a' descendant width
      console.log(width); // watch what happens
      $(this).width(Math.ceil(width)); // change item width with a 'rounded up' value
    })
  }
}).resize();

这里是代码 sn-p (jsFiddle):

$(window).on('resize', function(){ // recalculate when resizing window
  if (window.innerWidth > 768) { // only in 'desktop' version(s)
    $('.navbar-nav').find('> li:not(.hidden-sm)').each(function(){
      var width = $(this).children('a').outerWidth(); // for each valid 'li', take its 'a' descendant width
      console.log(width); // watch what happens
      $(this).width(Math.ceil(width)); // change item width with a 'rounded up' value
    })
  }
}).resize();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link One<span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link Two, Long</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="hidden-sm"><a href="#">Link Three: too long to fit, hide on small devices</a></li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

很直接,对吧?但它没有按预期工作:尽管有 Math.ceil() 函数,但项目的原始宽度(86.05124.17107.7 根据 Chrome DevTools)并不总是四舍五入,我最终得到 86124108(只有后者是对的;前两项“折叠”,因为没有足够的空间)。 Math.ceil() 不应该总是四舍五入吗?很奇怪……

“好的”,我想,“让我们找到解决方法”:所以我将Math.ceil()parseInt() 交换并添加至少+1 像素,就像其他sn-p (jsFiddle) 一样:

$(window).on('resize', function(){ // recalculate when resizing window
  if (window.innerWidth > 768) { // only in 'desktop' version(s)
    $('.navbar-nav').find('> li:not(.hidden-sm)').each(function(){
      var width = $(this).children('a').outerWidth(); // for each valid 'li', take its 'a' descendant width
      console.log(width); // watch what happens
      $(this).width(parseInt(width)+1); // change item width with a 'rounded up' value
    })
  }
}).resize();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link One<span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link Two, Long</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
          </ul>
        </li>
        <li class="hidden-sm"><a href="#">Link Three: too long to fit, hide on small devices</a></li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

很好,按钮不会折叠,但是...尝试调整窗口大小:按钮永远增长,可能是因为我在每次迭代中添加了 1 个像素:这比以前更糟...

现在我被困住了,无法想象其他方法:任何解决方案都可以让整数四舍五入而不以所有这些疯狂的结果结束,好吗?谢谢

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    您的问题是 jQuery 的 .width() 已经在内部将宽度值四舍五入为最接近的整数(因此:86.05 =&gt; 86124.17 =&gt; 124107.7 =&gt; 108)。

    因此,您使用 .width() 检索并对其执行舍入计算的值已经是整数,因此它们没有任何影响:)

    这可以通过使用 JavaScript 的原生 .getBoundingClientRect() 来解决:
    这将返回实际的浮点宽度(从 this answer 获取)。

    var width = $(this).children('a')[0].getBoundingClientRect().width;
    

    您可以保留它,但现在所有lis 中的widths 总是被重置,无论它们是否已经重置。
    为了防止这种情况,我使用了一个 if 子句来检查宽度是否还不是一个整数,并且只有那么 获取实际调整大小的元素。

    这就是你所需要的(我从this answer得到的):

    if (width%1 !== 0) {$(this).width(Math.ceil(width));}
    

    但为了安全起见,我也会删除.children('a'),并自行测量lis:

    var width = $(this)[0].getBoundingClientRect().width;
    

    显然a 会自动填充整个li,但li 也会自动缩放到a,因为您正在对.width() 执行.width() 操作li ,同时检查同一元素的width 似乎更安全、更合乎逻辑。
    或者,您可以设置awidth() 而不是li


    请参阅 code sn-p 了解演示(将 sn-p 放在“整页”中进行测试):

    $(window).on('resize', function(){ // recalculate when resizing window
      if (window.innerWidth > 768) { // only in 'desktop' version(s)
        $('.navbar-nav').find('> li:not(.hidden-sm)').each(function(){
          var width = $(this)[0].getBoundingClientRect().width; // for each valid 'li', take its 'a' descendant width
          if (width%1 !== 0) {$(this).width(Math.ceil(width));} // if width isn't already an integer, round up
          console.log(width, 'resize: '+(width%1 !== 0));
        });
      }
    }).resize();
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    
    <nav class="navbar navbar-default">
      <div class="container-fluid">
        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">Link One<span class="sr-only">(current)</span></a></li>
            <li><a href="#">Link Two, Long</a></li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
              <ul class="dropdown-menu">
                <li><a href="#">Action</a></li>
                <li><a href="#">Another action</a></li>
                <li><a href="#">Something else here</a></li>
              </ul>
            </li>
            <li class="hidden-sm"><a href="#">Link Three: too long to fit, hide on small devices</a></li>
          </ul>
        </div><!-- /.navbar-collapse -->
      </div><!-- /.container-fluid -->
    </nav>
    jsfiddle:https://jsfiddle.net/c7927ud1/6/

    【讨论】:

    • @Ivan 我对我的回答做了一个小的更新:我从var width = ...; 行中删除了.children('a')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 2015-07-30
    相关资源
    最近更新 更多