2012-05-05 32 views
41

Hay situaciones en las que puede ser útil obtener el ancho de píxel exacto de una medida em. Por ejemplo, supongamos que tiene un elemento con una propiedad CSS (como borde o relleno) que se mide en ems, y necesita obtener el ancho exacto de píxeles del borde o relleno. Hay una pregunta existente, que toca este tema:Convertir em a px en Javascript (y obtener el tamaño de fuente predeterminado)

How can i get default font size in pixels by using JavaScript or JQuery?

Esta pregunta se preguntará por conseguir el tamaño de fuente predeterminado - lo cual es necesario con el fin de convertir un valor relativo em a un valor exacto px.

This answer tiene una muy buena explicación de cómo hacer para conseguir el tamaño de fuente predeterminado de un elemento:

Desde anchura medida ems siempre se puede calcular el píxel exacto de una fuente tamaño mediante la creación de un div que es 1000 ems de longitud y dividiendo su propiedad de ancho de cliente por 1000. Parece que ems se truncan a la milésima más cercana, por lo que necesita 1000 ems para evitar un error de truncamiento del resultado de píxel.

Así, utilizando esta respuesta como una guía, escribí la siguiente función para obtener el tamaño de fuente predeterminado:

function getDefaultFontSize(parentElement) 
{ 
    parentElement = parentElement || document.body; 
    var div = document.createElement('div'); 
    div.style.width = "1000em"; 
    parentElement.appendChild(div); 
    var pixels = div.offsetWidth/1000; 
    parentElement.removeChild(div); 
    return pixels; 
} 

vez que tenga el tamaño de fuente predeterminado, puede convertir cualquier ancho em-px anchura por simplemente multiplicando el ems por tamaño de fuente predeterminado del elemento y redondeando el resultado:

Math.round(ems * getDefaultFontSize(element.parentNode))

Problema: Idealmente, se supone que el getDefaultFontSize es una función simple sin efectos secundarios que devuelve el tamaño de fuente predeterminado. Pero DOES tienen un desafortunado efecto secundario: ¡modifica el DOM! Anexa un niño y luego lo saca. Agregar al niño es necesario para obtener una propiedad offsetWidth válida. Si no agrega el hijo div al DOM, la propiedad offsetWidth permanece en 0 porque el elemento nunca se representa. Aunque eliminemos inmediatamente el elemento secundario, esta función aún puede crear efectos colaterales no deseados, como disparar un evento (como el evento onpropertychange de Internet Explorer o el DOMSubtreeModified de W3C) que estaba escuchando en el elemento padre.

Pregunta: ¿Hay alguna manera de escribir un libre getDefaultFontSize() verdadera función de efectos secundarios que no va a disparar accidentalmente controladores de eventos o causar otros efectos secundarios no deseados?

+0

En realidad, así es como funciona el DOM. Sin embargo, puede establecer la clase del elemento creado en algo como 'font-size-check' y luego en cualquier evento disparado, verifique si el elemento tiene esa clase para determinar si desea ignorarlo o no. –

+0

Recorre el DOM hasta que encuentres un nodo con un ancho especificado en ems, y úsalo para una medida algo menos precisa. El único efecto secundario es el tiempo de procesamiento. Además, no se garantiza que funcione. – mgiuffrida

Respuesta

15

Editar: No, no lo hay.

Para obtener el tamaño de la fuente rendido de un elemento dado, sin afectar el DOM:

parseFloat(getComputedStyle(parentElement).fontSize); 

Esto se basa la respuesta a this question.


Editar:

En IE, que tendría que utilizar parentElement.currentStyle["fontSize"], pero esto no está garantizado para convertir el tamaño de px. Así que eso está fuera.

Además, este fragmento no obtendrá el tamaño de fuente predeterminado del elemento, sino más bien su tamaño real de fuente, que es importante si realmente tiene una clase y un estilo asociado. En otras palabras, si el tamaño de fuente del elemento es 2em, obtendrá el número de píxeles en 2 ccs. A menos que el tamaño de fuente se especifique en línea, no podrá obtener la proporción de conversión correcta.

+1

No cambiará el DOM, pero obligará al navegador a realizar una operación de recalc/diseño, por lo que no será una operación "libre". Además, use parseFloat() no Number()! –

+0

@ThomasMcCabe: ¿por qué no utilizar 'Number()'? – mgiuffrida

+1

bueno, si usas 'parseFloat' no necesitarás la sobrecarga de una expresión regular como lo harías con' parseFloat (getComputedStyle (parentElement, "") .fontSize) '. Si intentara hacer lo mismo con 'Number' obtendría' NaN'. Básicamente, estoy diciendo que estás agregando la sobrecarga de '.match' sin ninguna razón. Además, 'Number 'en este caso es marginalmente más lento que' parseFloat'. –

3

Si necesita algo rápido y sucio (y basado en la base de la fuente-tamaño del cuerpo, no un elemento), me gustaría ir con:

Number(getComputedStyle(document.body,null).fontSize.replace(/[^\d]/g, '')) 

Number( // Casts numeric strings to number 
    getComputedStyle( // takes element and returns CSSStyleDeclaration object 
    document.body,null) // use document.body to get first "styled" element 
     .fontSize // get fontSize property 
      .replace(/[^\d]/g, '') // simple regex that will strip out non-numbers 
) // returns number 
+0

Agregaría \. a la expresión regular para tener en cuenta los decimales (a continuación, parseFloat() o lo que no depende de lo que tienes que hacer), pero esto parece funcionar. – Tom

5

tengo una mejor respuesta. Mi código almacenará el valor de 1em en la unidad-px en la variable em.

  1. Coloque este div cualquier parte del código HTML

    <div id="div" style="height:0;width:0;outline:none;border:none;padding:none;margin:none;"></div> 
    
  2. lugar esta función en su archivo JavaScript

    var em; 
    function getValue(id){ 
        var div = document.getElementById(id); 
        div.style.height = 1em; 
        em = div.offsetHeight; 
    } 
    

Ahora, cada vez que va a llamar a esta función 'getValue' con id de esa prueba div en el parámetro, tendrá un nombre de variable em que contendrá el valor de 1 em en px.

Cuestiones relacionadas