原贴地址: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展现都尽量保持一致性!

web界面上的字体兼容方案的更多相关文章

  1. 基于MVC4+EasyUI的Web开发框架经验总结(10)--在Web界面上实现数据的导入和导出

    数据的导入导出,在很多系统里面都比较常见,这个导入导出的操作,在Winform里面比较容易实现,我曾经在之前的一篇文章<Winform开发框架之通用数据导入导出操作>介绍了在Winform ...

  2. (转)基于MVC4+EasyUI的Web开发框架经验总结(10)--在Web界面上实现数据的导入和导出

    http://www.cnblogs.com/wuhuacong/p/3873498.html 数据的导入导出,在很多系统里面都比较常见,这个导入导出的操作,在Winform里面比较容易实现,我曾经在 ...

  3. 基于MVC4+EasyUI的Web开发框架经验总结(2)- 使用EasyUI的树控件构建Web界面

    最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开发框架保持一致,而在Web上,我主要采用EasyUI的前端界面处理技术,走MVC的技术路线,在重 ...

  4. CentOS6.8下搭建zookeeper web界面查看工具node-zk-browser

    zookeeper的web界面查看工具Node-ZK-Browser的界面是用nodejs写的今天试着搭建了下. 1. 安装nodejs [root@localhost product]# pwd / ...

  5. 让IE8支持HTML5及canvas功能!chart.js图表绘制工具库IE8上兼容方案

    第一步,我们加上对html5的支持. <!--[if IE]> <script src="/public/html5.js" type="text/ja ...

  6. ASP.NET 开发必备知识点(1):如何让Asp.net网站运行在自定义的Web服务器上

    一.前言 大家都知道,在之前,我们Asp.net 的网站都只能部署在IIS上,并且IIS也只存在于Windows上,这样Asp.net开发的网站就难以做到跨平台.由于微软的各项技术的开源,所以微软自然 ...

  7. Open Sans字体兼容问题解决办法[font-face]

    参考:http://www.tantengvip.com/2014/11/open-sans/ 1.font-face使用方法 font-face是CSS3中的一个模块,主要是把自定义的Web字体嵌入 ...

  8. 移动Web应用开发入门指南——兼容篇

    兼容篇 兼容篇是我最想写的一部分,在这之前也总结过很多关于移动开发的兼容问题与解决方案.对于移动Web开发来说,兼容是开发重心,通常要花费30%甚至更多的时间去处理一些兼容问题,甚至时间花掉了,问题依 ...

  9. Emoji表情符号兼容方案(适用ios,android,wp等平台)

    http://blog.csdn.net/qdkfriend/article/details/7576524 Emoji表情符号兼容方案 一 什么是Emoji emoji就是表情符号:词义来自日语(え ...

随机推荐

  1. 理解 Promise 过程

    /** new Promise(fn1).then(function(val){ console.log(val); }) 主要是把 then 的函数抽取出来 , 利用闭包存放在 callback中, ...

  2. 关于vsftpd.conf配置

    vsftpd配置文件详解   转自http://yuanbin.blog.51cto.com/363003/108262/   1.默认配置: 1>允许匿名用户和本地用户登陆.      ano ...

  3. Django与数据库操作

    Django与数据库操作 数据库连接的方法 web 框架 django --- 自己内部实现 (ORM) + pymysql(连接) Flask,tornado --- pymysql SQLArch ...

  4. php调用API支付接口(转自刘68)

    首先访问  https://charging.teegon.com/  注册账号, 找到开发配置   记下client_id和client_secret. 点击 天工开放平台 点击天工收银 点击  S ...

  5. Android面试题整理

    1.    请描述下Activity的生命周期. 2.    如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态? 3.    如何将一个Activity设置成窗口的样 ...

  6. Windows Phone 8 Programming Considerations

    OpenGL ES 2.0 Support Marmalade supports the Open GL ES 2.0 Graphics API on Windows Phone 8 using a ...

  7. Chrome设置允许ajax跨域

    最近在做一个前后端分离的项目,在Windows上用.Net WebApi时候的后端,在Mac上用ng2搭建的前端. 要实现前后端对接进行调试,就必须要解决ajax跨域的问题,实现方法如下: //在te ...

  8. HihoCoder1619 “共同富裕”(逆向思维)

    “共同富裕” 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数组A1, A2, ... AN,每次操作可以从中选定一个元素Ai,把除了Ai之外的所有元素都加1. ...

  9. python笔记-4(装饰器、生成器、迭代器)

    一.熟练掌握装饰器的原理 (在装饰器学习的过程中,查了看了很多资料,个人感觉走了很多的弯路,这个笔记,分享我的理解,希望能帮助到一些人.本文对装饰器的描述,侧重点是条理与逻辑思路,想通过从无到有的方式 ...

  10. 洛谷 P2205 [USACO13JAN]画栅栏Painting the Fence

    传送门 题目大意: 开始站在原点,给出一系列操作 x L/R,表示向左或向右走几步. 最多会移动到离原点1,000,000,000单位远的地方. n次操作,n<=100000 问走过k次的地方有 ...