【问题标题】:jQuery/JavaScript: convert pixels to em in a easy wayjQuery/JavaScript:以简单的方式将像素转换为 em
【发布时间】:2012-04-24 21:05:45
【问题描述】:

我正在寻找一种简单的方法来将一行代码添加到我的插件中,将几个像素值转换为 em 值,因为我的项目的布局需要在 ems 中。有没有一种简单的方法可以做到这一点,因为我不想在网站上添加第三方插件。

这里就不贴代码了,跟插件本身没有关系。

谢谢。

示例:13px -> ??em

【问题讨论】:

  • 这可能会帮助你pxtoem.com检查“学习”标签

标签: javascript jquery pixel em


【解决方案1】:

我认为你的问题很重要。由于显示分辨率的类别正在迅速增加,因此使用 em 定位来支持广泛的屏幕分辨率是一种非常吸引人的方法。但是,无论您多么努力地将所有内容都保留在 em 中——有时您可能会从 JQuery 拖放或其他库中获得一个像素值,并且您希望在将其发送回服务器以保持持久性之前将该值转换为 em。这样,下次用户查看页面时,项目将处于正确的位置——无论他们使用的设备的屏幕分辨率如何。

当您可以查看代码时,JQuery 插件并不是很可怕,特别是当您想要它们像this plugin to convert pixel values to em 这样简短而甜美时。事实上它太短了,我会把整个东西贴在这里。有关版权声明,请参阅链接。

$.fn.toEm = function(settings){
    settings = jQuery.extend({
        scope: 'body'
    }, settings);
    var that = parseInt(this[0],10),
        scopeTest = jQuery('<div style="display: none; font-size: 1em; margin: 0; padding:0; height: auto; line-height: 1; border:0;">&nbsp;</div>').appendTo(settings.scope),
        scopeVal = scopeTest.height();
    scopeTest.remove();
    return (that / scopeVal).toFixed(8) + 'em';
};


$.fn.toPx = function(settings){
    settings = jQuery.extend({
        scope: 'body'
    }, settings);
    var that = parseFloat(this[0]),
        scopeTest = jQuery('<div style="display: none; font-size: 1em; margin: 0; padding:0; height: auto; line-height: 1; border:0;">&nbsp;</div>').appendTo(settings.scope),
        scopeVal = scopeTest.height();
    scopeTest.remove();
    return Math.round(that * scopeVal) + 'px';
};

用法示例:$(myPixelValue).toEm();$(myEmValue).toPx();

我刚刚在我的应用程序中对此进行了测试,效果很好。所以我想我分享。

【讨论】:

  • 我从来没有见过这样使用 jQuery。我假设这支持字符串值("3px""3em"),但在您访问插件的 .toPx().toEm() 之前,这不会要求 jQuery 查询文档中的这些选择器吗?跨度>
  • 我真的不明白将这些设为 jquery / $ 函数的意义——简单的函数 toPx(ems) 或函数 toEms(px) 在我看来会更清楚。
【解决方案2】:

尽管它基于父元素的font-size 和元素本身的px,但似乎可以满足您的要求:

function px2em(elem) {
    var W = window,
        D = document;
    if (!elem || elem.parentNode.tagName.toLowerCase() == 'body') {
        return false;
    }
    else {
        var parentFontSize = parseInt(W.getComputedStyle(elem.parentNode, null).fontSize, 10),
            elemFontSize = parseInt(W.getComputedStyle(elem, null).fontSize, 10);

        var pxInEms = Math.floor((elemFontSize / parentFontSize) * 100) / 100;
        elem.style.fontSize = pxInEms + 'em';
    }
}

JS Fiddle proof of concept.

注意事项:

  • 如果您尝试转换为em 的元素是body,则该函数返回false,但这是因为我无法确定将值设置为@987654333 是否合理@ 或者干脆别管它。

  • 它使用window.getComputedStyle(),所以如果不做一些调整,它就不能在IE上工作。

参考资料:

【讨论】:

    【解决方案3】:

    像素和ems是根本不同类型的单位。您不能简单地在它们之间进行转换。

    例如,用户在一个网站上的默认字体大小为 16 像素,其中顶级标题的样式为 200% 字体大小,1em 可能等于 32 像素。将标题移到文档的其他位置,可以是 64 像素或 16 像素。将相同的文档提供给不同的用户,它可能是 30/60/15px。开始谈论不同的元素,它可以再次改变。

    最接近您想要的是将像素转换为 ems+document+context+settings。但是,如果有人要求您使用 em 布置您的项目,他们可能不会很高兴您尝试以像素为单位然后“转换”。

    【讨论】:

    • 在某些情况下您只能访问像素值。例如,在页面上拖动 div 时,您可能希望在保留 div 的位置之前获取 em 值。我认为这个问题是完全有效的,如果您在浏览器中执行此操作,则可以将像素转换为 em。毕竟浏览器本身在渲染之前会将 em 值转换为像素。
    【解决方案4】:

    老问题,但仅供参考,这是我拼凑的东西,范围和后缀是可选的。将 rem 或 em 值作为字符串传递给它,例如。 '4em' [您可以使用空格和大写/小写],它将返回 px 值。除非您给它一个范围,这将是查找本地 EM 值的目标元素,否则它将默认为 body,有效地为您提供 rem 值。最后,可选的后缀参数 [ boolean ] 会将 'px' 添加到返回值,例如 48 变为 48px。

    例如:emRemToPx( '3em', '#content' )

    在字体大小为 16px / 100% 的文档上返回 48

    /**
    * emRemToPx.js | @whatsnewsisyphus 
    * To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
    * see CC0 Public Domain Dedication <http://creativecommons.org/publicdomain/zero/1.0/>.
    */
      var emRemToPx = function( value, scope, suffix ) {
        if (!scope || value.toLowerCase().indexOf("rem") >= 0) {
          scope = 'body';
        }
        if (suffix === true) {
          suffix = 'px';
        } else {
          suffix = null;
        }
        var multiplier = parseFloat(value);
        var scopeTest = $('<div style="display: none; font-size: 1em; margin: 0; padding:0; height: auto; line-height: 1; border:0;">&nbsp;</div>').appendTo(scope);
        var scopeVal = scopeTest.height();
        scopeTest.remove();
        return Math.round(multiplier * scopeVal) + suffix;
      };
    

    【讨论】:

      【解决方案5】:

      通常当您想将px 转换为em 时,转换发生在元素本身上。 getComputedStylepx 中返回值,这会破坏他们的响应能力。下面的代码可以用来帮助解决这个问题:

      /**
       * Get the equivalent EM value on a given element with a given pixel value.
       *
       * Normally the number of pixel specified should come from the element itself (e.g. element.style.height) since EM is
       * relative.
       *
       * @param {Object} element - The HTML element.
       * @param {Number} pixelValue - The number of pixel to convert in EM on this specific element.
       *
       * @returns {Boolean|Number} The EM value, or false if unable to convert.
       */
      window.getEmValueFromElement = function (element, pixelValue) {
          if (element.parentNode) {
              var parentFontSize = parseFloat(window.getComputedStyle(element.parentNode).fontSize);
              var elementFontSize = parseFloat(window.getComputedStyle(element).fontSize);
              var pixelValueOfOneEm = (elementFontSize / parentFontSize) * elementFontSize;
              return (pixelValue / pixelValueOfOneEm);
          }
          return false;
      };
      

      使用起来很简单:

      var element = document.getElementById('someDiv');
      var computedHeightInEm = window.getEmValueFromElement(element, element.offsetHeight);
      

      【讨论】:

        【解决方案6】:

        我已将此功能打包到一个库中,并完成了参数类型检查:px-to-em

        鉴于此 HTML:

        <p id="message" style="font-size: 16px;">Hello World!</p>
        

        您可以期待这些输出:

        pxToEm(16, message) === 1
        pxToEm(24, message) === 1.5
        pxToEm(32, message) === 2
        

        由于 OP 要求在没有库的情况下执行此操作,我已将 px-to-em 的源代码复制到现场演示中:

        function pxToEm (px, element) {
          element = element === null || element === undefined ? document.documentElement : element;
          var temporaryElement = document.createElement('div');
          temporaryElement.style.setProperty('position', 'absolute', 'important');
          temporaryElement.style.setProperty('visibility', 'hidden', 'important');
          temporaryElement.style.setProperty('font-size', '1em', 'important');
          element.appendChild(temporaryElement);
          var baseFontSize = parseFloat(getComputedStyle(temporaryElement).fontSize);
          temporaryElement.parentNode.removeChild(temporaryElement);
          return px / baseFontSize;
        }
        
        console.log(pxToEm(16, message), 'Should be 1');
        console.log(pxToEm(24, message), 'Should be 1.5');
        console.log(pxToEm(32, message), 'Should be 2');
        &lt;p id="message" style="font-size: 16px;"&gt;Hello World!&lt;/p&gt;

        我从this answer了解到,使用getComputedStyle可以可靠地得到带小数点的除数px值,提高了计算的准确性。我发现 Aras 的答案可能会偏离 0.5px 以上,这对我们造成了舍入误差。

        【讨论】:

          【解决方案7】:

          试试这个:

          parseInt(myPixelValue) / parseFloat($("body").css("font-size"));
          

          【讨论】:

          • 欢迎来到 SO 并感谢您的贡献。我真的建议您注释您的答案,特别是考虑到还有 8 个其他答案的事实(想想一个人试图选择一个相关的答案,他们为什么要尝试您的答案?与其他答案相比它有什么帮助?)
          【解决方案8】:

          Ems 无论如何都不等于像素。它们是相对测量值。

          <span style="font-size: 1em;">This is 1em font size, which means the text is the same size as the parent</span>
          
          <span style="font-size: 1.5em;">This is 1.5em font size, which means the text is 150% the size as the parent</span>
          

          基本大小由用户代理(浏览器)确定。

          【讨论】:

          • 基本大小由自己的字体大小或父字体大小决定。如果有人定义了字体大小,那么用户代理。
          • @josantgv 是的,同意。我想说的是,一切基础的大小都在用户代理级别。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-01
          • 1970-01-01
          • 2011-04-02
          • 1970-01-01
          • 1970-01-01
          • 2023-03-14
          相关资源
          最近更新 更多