2012-05-05 2 views
41

Бывают ситуации, когда может быть полезно получить точную ширину пикселя измерения em. Например, предположим, что у вас есть элемент с свойством CSS (например, границей или дополнением), который измеряется в ems, и вам нужно получить точную ширину пикселя границы или отступов. Там в существующий вопрос, который затрагивает эту тему:Преобразование em в px в Javascript (и получение размера шрифта по умолчанию)

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

Этот вопрос просит о том, чтобы размер по умолчанию шрифта - который необходим для того, чтобы преобразовать относительную em значение для точного px значения.

This answer имеет довольно хорошее объяснение того, как идти о получении размера шрифта по умолчанию элемента:

Поскольку ширина Эмса меры всегда можно вычислить точный пиксельный шрифт размера путем создания DIV, который 1000 ems long и деление его свойства client-Width на 1000. Кажется, что ems усекаются до ближайшей тысячной, так что вам нужно 1000 ems, чтобы избежать ошибочного обрезания результата пикселя .

Таким образом, используя этот ответ в качестве руководства, я написал следующую функцию, чтобы получить размер шрифта по умолчанию:

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; 
} 

После того как вы размер шрифта по умолчанию, вы можете преобразовать любой em ширина px ширина, просто умножив СЭМ по размеру шрифта по умолчанию элемента и округляя результат:

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

Задача:getDefaultFontSize идеально подходит для простой, свободной от побочных эффектов функции, которая возвращает размер шрифта по умолчанию. Но это У есть неудачный побочный эффект: он изменяет DOM! Он добавляет ребенка, а затем удаляет его. Добавление ребенка необходимо, чтобы получить действительное свойство offsetWidth. Если вы не добавите дочерний элемент div в DOM, свойство offsetWidth останется на 0, потому что элемент никогда не отображается. Несмотря на то, что мы сразу удаляем дочерний элемент, эта функция может по-прежнему создавать непреднамеренные побочные эффекты, такие как запуск события (например, событие onpropertychange или приложение W3C DOMSubtreeModified), которое прослушивало родительский элемент.

Вопрос: Есть ли способ, чтобы написать действительно побочный эффект свободного getDefaultFontSize() функции, которая не случайно сгореть обработчик событий или вызвать другие непредвиденные побочные эффекты?

+0

Не совсем, это то, как работает DOM. Однако вы можете установить класс созданного элемента на что-то вроде «font-size-check», а затем в любом случае, запущенном, проверьте, имеет ли этот элемент этот класс, чтобы определить, следует ли его игнорировать. –

+0

Пройдите DOM, пока не найдете узел с шириной, указанной в ems, и используйте это для несколько менее точного измерения? Единственным побочным эффектом является время обработки. Также не гарантируется работа. – mgiuffrida

ответ

15

Редактировать: Нет, не существует.

Чтобы получить обработанный размер шрифта данного элемента, не затрагивая DOM:

parseFloat(getComputedStyle(parentElement).fontSize); 

Это основан ответ на this question.


Edit:

В IE, вы должны использовать parentElement.currentStyle["fontSize"], но это не гарантировано, чтобы преобразовать размер в px. Вот и все.

Кроме того, этот фрагмент не получит размер шрифта по умолчанию для элемента, а его размер действителен, что важно, если у него действительно есть класс и связанный с ним стиль. Другими словами, если размер шрифта элемента равен 2em, вы получите количество пикселей в 2 ems. Если размер шрифта не указан в строке, вы не сможете получить коэффициент конверсии правильно.

+1

Он не изменит DOM, но заставит браузер выполнить операцию recalc/layout, а не «свободную» операцию. Кроме того, используйте parseFloat() not Number()! –

+0

@ThomasMcCabe: почему бы не использовать 'Number()'? – mgiuffrida

+1

Хорошо, если вы используете 'parseFloat', вам не понадобятся накладные расходы регулярного выражения, как вы могли бы просто выполнить' parseFloat (getComputedStyle (parentElement, "") .fontSize) '. Если вы попытаетесь сделать то же самое с 'Number', вы получите' NaN'. Так что в основном, я говорю, что вы добавляете накладные расходы '.match' без всякой причины. Кроме того, 'Number' в этом случае немного медленнее, чем' parseFloat'. –

3

Если вам нужно что-то быстро и грязно (и основанный на базе размера шрифта тела, а не элемент), я бы с:

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

Я бы добавил \. в регулярное выражение для учета десятичных знаков (затем parseFloat() или то, что не зависит от того, что вы должны делать), но это, похоже, работает. – Tom

5

У меня есть лучший ответ. Мой код сохранит 1em значение в unit-px в переменной em.

  1. Поместите этот div в любом месте HTML код

    <div id="div" style="height:0;width:0;outline:none;border:none;padding:none;margin:none;"></div> 
    
  2. Place эта функция в вашем JavaScript файл

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

Теперь, когда вы будете вызывать эту функцию 'getValue' с id этого параметра test div в параметре, у вас будет имя переменной em, который будет содержать значение 1 em в px.