2012-05-05 40 views
41

在某些情況下,獲取em度量的確切像素寬度可能很有用。例如,假設您有一個帶有CSS屬性的元素(如邊框或填充),這是以ems度量的,並且您需要獲得邊框或填充的精確像素寬度。有一個現有的問題,其中涉及這個話題:在JavaScript中將em轉換爲px(並獲取默認字體大小)

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

這個問題是問得到默認字體大小 - 這是必要的,以相對em值轉換爲一個確切的px值。

This answer對如何去獲得一個元素的默認字體大小相當不錯的解釋:通過創建一個div是

由於EMS測量寬度可以隨時計算出精確的像素字體 大小1000 ems長,並將其 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寬度通過僅由元素的默認字體大小相乘EMS並將結果舍入:

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

問題:getDefaultFontSize理想情況下應該是一個簡單的副作用自由函數,它返回默認的字體大小。但它DOERS有一個不幸的副作用:它修改DOM!它追加一個孩子,然後移除孩子。爲了得到有效的offsetWidth屬性,附加孩子是必要的。如果您不將子div附加到DOM,則offsetWidth屬性將保持爲0,因爲該元素永遠不會呈現。儘管我們立即刪除了子元素,但此函數仍可能會產生意想不到的副作用,例如觸發正在父元素上偵聽的事件(如Internet Explorer的onpropertychange或W3C的DOMSubtreeModified事件)。

問:有沒有什麼辦法來寫一個真正的無副作用getDefaultFontSize()功能不會意外火災事件處理或造成其他意外的副作用?

+0

不是真的,這就是DOM的工作原理。但是,您可以將創建的元素的類設置爲諸如「font-size-check」之類的東西,然後在任何事件觸發時檢查該元素是否具有該類以確定是否忽略它。 –

+0

遍歷DOM,直到找到一個寬度指定爲ems的節點,並將其用於不太精確的測量?唯一的副作用是處理時間。也不能保證工作。 – mgiuffrida

回答

15

編輯:不,沒有。

爲了獲得給定元素的呈現字體大小,而不會影響DOM:

parseFloat(getComputedStyle(parentElement).fontSize); 

這是基於關閉答案this question


編輯:

在IE中,你將不得不使用parentElement.currentStyle["fontSize"],但是這不能保證大小轉換爲px。所以就這樣了。

而且,這個片段將不會讓你的元素的默認字體大小,而是它的實際字體大小,這是非常重要的,如果它實際上已經得到了類以及與其關聯的樣式。換句話說,如果元素的字體大小爲2em,則會得到2 em中的像素數。除非字體大小是內聯指定的,否則您將無法獲得正確的轉換比率。

+1

它不會更改DOM,但會強制瀏覽器執行重新計算/佈局操作,因此不是「免費」操作。另外,使用parseFloat()不是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值存儲在變量em的unit-px中。

  1. div在你的HTML代碼

    <div id="div" style="height:0;width:0;outline:none;border:none;padding:none;margin:none;"></div> 
    
  2. 在任何場合下此功能在你的JavaScript文件

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

現在地點,只要你會調用這個函數'getValue'與參數中該測試div的ID,您將有一個變量名稱em它將包含px中1em的值。

相關問題