原貼地址:http://www.baidufe.com/item/60cd11d3bfdee5c51369.html
做前端的,對web界面基本都摳的很仔細,尤其精確到1px!
類似邊距、寬度、高度等的,調整1px並不難,但是如果遇到不同字體的情況,要處理line-height,保證每種字體下,UI效果都非常美觀,這就不是一件簡單的事情了!
也許大家首先能想到的是,字體嘛,默認給頁面body節點設置一個font-family列表即可:
body { font-size: 12px; font-family:"Microsoft Yahei", "微軟雅黑", Tahoma, Arial, Helvetica, STHeiti; }
但其實問題並沒有這么簡單,font-family列表是必然要設置的,但這個列表的具體解析,只有瀏覽器自己才知道,如果coder們不在這個基礎上做點兒什么,是完全不知道某個用戶瀏覽到的這個頁面究竟應用到了那種字體、此時的頁面排版是否美觀、頁面有沒有出現文字很擁擠的情況、給某個節點設置的背景icon是否對其了?
等等,各種問題,各種猜測。。。
實際開發中,這也確實是一個問題,作為專業coder,是需要兼容各個細節的,包括這里的字體控制。
任務:
利用Javascript編寫一個組件,用於檢測某用戶瀏覽頁面時,瀏覽器應用到了那種字體(以微軟雅黑為例)。
問題:
1、用戶機器未安裝雅黑字體時,需要用別的字體替代,並且要對其他樣式進行修正
2、用戶機器安裝了雅黑字體時:
a、用戶機器未開啟ClearType時,雅黑字體顯示出來會有鋸齒,此時依然要將頁面字體設置為默認,並同樣對其他樣式進行修正
b、用戶機器開啟了ClearType時,按照正常的模式進行渲染,不需要對其他樣式進行修正
方法:
1、頁面開始渲染時,檢測用戶機器上是否安裝了雅黑字體
2、檢測用戶機器是否開啟了ClearType
3、如果一切如願,給html節點增加class="ms-with-yahei",否則增加class="ms-without-yahei"
4、樣式修正:對html.ms-without-yahei下的樣式進行復寫
實現:
只要這一切都分析好了,要實現,就很簡單了,核心的部分代碼就是:
1、檢測用戶機器是否安裝了某種字體:
a、IE瀏覽器中,通過創建<object classid="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b"></object>,直接訪問系統的字體庫,讀取字體列表,判斷某種字體是否存在
if(qing.browser.ie){ _dlgHelper = qing.dom.create('object',{ id : "sp-font-detect-obj", classid : "clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b" }); qing.dom.setStyles(_dlgHelper,{ "position": "absolute", "top": "-10000px", "left": "-10000px", "width" : "1px", "height" : "1px" }); document.body.appendChild(_dlgHelper); _isInitialedInIE = true; }
//IE中,用object的classid來判斷字體 if(qing.browser.ie) { if(!_isInitialedInIE) { init(); } var sysFonts = _dlgHelper.fonts; if(sysFonts.count) { for(var i = 1,len = sysFonts.count;i <= len;i++){ if(isInArray(sysFonts(i),familys)) { return callback(true); } } } return callback(false); }
b、非IE的瀏覽器中,創建一個span標簽,再插入一段字符,設置很大的字號和默認字體(預計所有機器都有的“Times New Roman”),獲取到span的offsetWidth;再給span追加一個待檢測的字體,再獲取其offsetWidth;兩個width進行比較,如果相同,則表明用戶機器沒有這種字體,否則表明用戶機器確實安裝了這種字體!
/** * 檢查字體寬度 * @param {Object} family */ var checkOffsetWidth = function(family){ var node = document.createElement("p"); qing.dom.setStyles(node, { "font-family": family + ", Times New Roman", "font-size": '300pt', "display": "inline", "position": "absolute", "top": "-10000px", "left": "-10000px" }); qing.dom.addClass(node, "sp-font-detect"); node.innerHTML = "mmmmmmmmml"; document.body.appendChild(node); var width = node.offsetWidth; document.body.removeChild(node); return width; };
/** * 獲取文字實際寬度 */ var getDefaultWidth = function(){ if (!_defaultWidth) _defaultWidth = checkOffsetWidth("Times New Roman"); return _defaultWidth; };
//非IE瀏覽器中,用比較寬度的方法來判斷 else{ var familyWidth = 0; var defaultWidth = getDefaultWidth(); for(var j = 0,flen = familys.length;j < flen;j++){ familyWidth = checkOffsetWidth(familys[j]); if(familyWidth !== defaultWidth){ return callback(true); } } return callback(false); }
2、檢測用戶機器是否開啟了ClearType
a、IE下,直接通過screen.fontSmoothingEnabled獲取
b、非IE下,創建canvas,畫一條粗線,然后獲取並分析該DataURI數據
/** * 是否開啟了clearType *@function isClearTypeOn *@return {Boolean} 如果支持,顯示true;否則返回false */ var isClearTypeOn = function() { if(typeof screen.fontSmoothingEnabled!="undefined") return screen.fontSmoothingEnabled; else try { var f=document.createElement("canvas"); f.width="35"; f.height="35"; f.style.display="none"; document.body.appendChild(f); var o=f.getContext("2d"); o.textBaseline="top"; o.font="32px Arial"; o.fillStyle="black"; o.strokeStyle="black"; o.fillText("E",0,0); for(var r=8;r<=32;r++) for(var u=1;u<=32;u++) { var q=o.getImageData(u,r,1,1).data[3]; if(q != 255 && q != 0) { document.body.removeChild(f); return true } } document.body.removeChild(f); return false } catch(y) { return null } };
3、在css中定義“其他字體情況下,樣式的修復方案”
body, button, input, select, textarea , pre { font-size: 12px; font-family:"Microsoft Yahei", "微軟雅黑", Tahoma, Arial, Helvetica, STHeiti; _font-family:Tahoma,Arial,Helvetica,STHeiti; } html.mod-without-msyahei body { font-family: Tahoma,Arial,Helvetica,STHeiti; }
/****************系統默認支持雅黑的處理**********************/ .mod-without-msyahei .mod-blogitem .a-expand-reason{ background-position-y:-15px; } .mod-without-msyahei .mod-blogitem .a-collapse-reason{ background-position-y:3px; } .mod-without-msyahei .mod-blogitem .box-tag .q-tag{ _padding:5px 3px 1px; } .mod-without-msyahei .mod-blogitem .item-head .q-private { line-height:23px; _padding-top:3px; }
4、在頁面上,調用detect方法進行字體檢測,並進行樣式糾偏
/** * 字體監測 * @return {[type]} */ var _fontDetect = function(){ qext.FontDetect.detect(['微軟雅黑','Microsoft Yahei'],function(isExist){ //獲得html節點 var htmlElm = qing.dom.query('html')[0]; //開啟clearType並存在雅黑字體 if(isExist){ qing.dom.addClass(htmlElm,'mod-with-msyahei'); }else{ qing.dom.addClass(htmlElm,'mod-without-msyahei'); } }); };
這樣,就能保證整個頁面在不同的字體情況下,UI展現都盡量保持一致性!