堂主 - WEB前端开发

专注于互联网 | WEB前端开发 | 以用户为中心的体验 | 家是圆心 | Code is art !

圆角头像的重构优化

Tags :     2 comments

有些恼人的圆角

一些网站(尤其是娱乐性为主的网站)从用户视觉体验角度出发,会将用户头像设置为圆角显示,以增加亲和度。如开心网的用户头像:

开心网用户圆角头像

在此基础上,追求更简约的设计会直接将头像图片本身设置为圆角来展示,如腾讯朋友

腾讯朋友用户圆角头像

这个效果看似简单,但可能会令一些前端er感到头疼。毕竟在尚不支持CSS3圆角属性的IE大行其道的当下,高效的解决页面中的批量圆角图片不是那么容易。看到最后的童鞋也会发现,本文也无最优解,因为不同的环境,需求不同,技术实现也会不同。

技术实现

后端生成

似乎对于前端来说,最希望的就是后端工程师在程序开发上能支持用户上传头像时候,可以自动生成一组用于前台页面不同情境下使用的头像集合,既包含了默认直角的同时也会生成圆角版本的调用头像。

优点:节省前台页面对圆角图片处理的代码量,为公司省带宽,为用户省加载时间。

不足:后端开发成本提升,服务器负荷在生成头像阶段有极为微小的加剧。

前端实现

目前看来。似乎绝大部分的网站会采用由前端来实现这个效果。毕竟,前端负责的就是用户浏览器里的那些东西。

我们这里不会谈论那个07年广泛使用的“4个<b>绝对定位”的方式,毕竟对于但页面中数量众多的用户头像来说,这个方法虽可行但效率太差,同时也是表格布局思维的遗老——以视觉为基础进行布局的意识要不得。

方法一:针对非IE的更现代款浏览器,采用CSS3

相信大家都会最喜欢这个方式,简单高效,代码无冗余可以保持优雅,只是目前鉴于黑势力的IE系列,若想普及还有待时日。DEMO请猛击这里

HTML:

<div id="demo-2">
  <a href="http://www.osmn00.com">
      <img src="images/hi.jpeg" width="60" height="60" />
  </a>
</div>

CSS:

img {
	border:0;
	display:block;
}
#demo-2 img {
	border-radius: 4px;
}

方法二:针对不那么现代的IE系列,采用额外的一个绝对定位层

这个方法首先需要一张png图片为覆盖图,该覆盖图中间为透明,只在四角有不透明部分。设置图片外容器为相对定位,此覆盖层为绝对定位。当此覆盖图覆盖在头像上时,头像就因四角被覆盖,呈现出圆角的外观。DEMO请猛击这里。 

HTML:

<div id="demo-3">
  <a href="http://www.osmn00.com">
    <span></span>
    <img src="images/hi.jpeg" width="60" height="60" />
  </a>
</div>

基本的CSS:

img {
	border:0;
	display:block;
}
#demo-3 a{
	width: 60px;
	height: 60px;
	display: block;
	overflow: hidden;
	position: relative;
}
#demo-3 a span {
	width: 60px;
	height: 60px;
	display: block;
	background: url(images/portrait_round.png);
	position: absolute;
	left: 0;
	top: 0;
}

因为要使用带过渡透明的PNG图片,所以此方法会遇到IE6不支持PNG的问题。解决的办法有很多,详细的说明请移步这篇文章:《IE6下png背景不透明问题的综合拓展》。本demo中采用IE6背景图更换为gif格式,虽然有一点点锯齿但总比加载一个巨大的JS文件强。再或者可以狠狠心,针对IE6就不提供圆角的样式,而是默认的直角头像,如腾讯朋友,在IEtester模拟的IE6环境下就是直角的。

本DEMO中针对IE6改进后的部分CSS:

#demo-3 a span {
	width: 60px;
	height: 60px;
	display: block;
	cursor:pointer;
	background: url(images/portrait_round.png)!important;
	background: url(images/portrait_round.gif);
	position: absolute;
	left: 0;
	top: 0;
}

针对IE6增加了2条语句,一个是光标在头像上时变为手型(显示为可点击区域),一个是背景设置为GIF格式图片。本demo中采用IE6背景图更换为gif格式,虽然有一点点锯齿但总比加载一个巨大的JS文件强。两者截图对比:

GIF圆角与PNG圆角对比

改进

上述方法看上去还不错,但每次都要在结构中显式地添加一个额外的标签总是没有什么爱。不单单是有损于结构代码的优雅,更是增加了页面的体积、无助于服务器效能提升和带宽的节省,同时增大的网页体积也不利于用户在客户端更快的加载网页。

那就考虑什么办法能在满足结构代码精简优雅的同时又能实现我们想要的头像圆角?是的,用JS在客户端动态的生成额外的圆角层标签。改进后的DEMO请猛击这里

结构代码中没有了无语义的span,同时增加了如下的JS代码:

function createFilletedCorner(){
	var getElementsByClassName = function(searchClass,node,tag){
		var classElements = new Array();
		
		if (node == null)
			node = document;
			
		if (tag == null)
			tag = '*';
			
		var els = node.getElementsByTagName(tag);
		var elsLen = els.length;
		var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
		
		for (i=0,j=0;i<elsLen;i++){
			if (pattern.test(els[i].className)){
				classElements[j] = els[i];
				j++;
			}
		}
		return classElements;
	} 

	var parents = getElementsByClassName('avatar');
	
	for (var i=0;i<parents.length;i++){
		var x = document.createElement('span');
		var avatar = parents[i].getElementsByTagName('img')[0];
		avatar.parentNode.insertBefore(x,avatar);
	}
}

window.onload = function(){createFilletedCorner()} 

新版本的Firefox、Chrome等早已支持“getElementsByClassName” 方法,但黑势力的IE系列尚未支持。作为这个仅针对IE系列的头像圆角效果实现方法,我这里加入了实现按CLASS选择对象的方法。

效率至上

目前,代码里没有了冗余的无语意的span标签,而是采用JS在客户端网页载入完毕后动态的生成这一系列的标签。那么接下来的问题就是,这2种方式哪一种会更有效率?最佳方式就是在大数据的情况下实际测试一凡,同时,大数据量也会将性能差距放大以便更好的观察。

这里将无JS的和有JS的各来一份,内容以组为单位,每组由20个不同的头像组成,共50组1000条头像列表。

无JS的版本有JS的版本

同等测试环境下,20+次的测试,HttpWatch显示JS动态生成的版本比非JS生成的版本在加载时间上快0.3秒左右;观察到系统内存占用JS版比非JS版多出4M。

而现实中绝少会碰到一个页面存在1000个圆角头像的情况,一般一个页面存在100个左右的头像就已经很多了。而在每页100条的情况下,2者在内存占用上差别甚小。

进而取舍的关键点之一便成了在具体情况中,哪一种方法最能节省页面体积。JS版本中需要用到“getElementsByClassName” 方法,在无附加引用类库的情况下,多些的JS语句增加的体积似乎并不比删除的额外标签来得少。但要是在网页中附加了其他的类库如JQ等已经内置实现“getElementsByClassName” 方法,则采用JS的方式的确会节省很多的体积,同时也最大程度上保证了局部代码的优雅。

总结:

头像圆角的实现,似乎不单单是一种技术的方式,而是可以针对不同浏览器采用不同的方式,是渐进增强还是优雅降级,取决于你的用户、或者是你的经理。这里仅仅是给出我自己的一种办法:

  • 针对支持CSS3的现代浏览器,采用CSS3的圆角方式
  • 针对IE系列,采用额外的标签
  • 不同的情景选用是否采用JS来生成额外的标签

如有不同意见或补充,欢迎回复讨论~!

延伸阅读,更多的圆角实现技术:http://www.smileycat.com/miaow/archives/000044.php

 

参与讨论

*

*