纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录...

前言

FineUI控件库发展至今已经有 5 个年头,目前论坛注册的QQ会员 5000 多人,捐赠用户 500 多人(捐赠用户转化率达到10%以上,在国内开源领域相信这是一个梦幻数字!也足以证明FineUI旺盛的生命力!)。这一切的得来不是无缘无故的,而是来自于FineUI的发布理念 – Release Early! Release Often!

时至今天,FineUI总共发布了 100 多个版本!

这 100 多个版本更新列表只是文本文件就有 120K 大小,放在页面上更是长的要命,如何恰当的向用户展示 FineUI 勤劳的身影就成了一个问题。之前的展示页面只是简单的将所有的更新记录放在一个 PRE 标签中,显得有点死气沉沉,如下图所示。

image

 

站在巨人的肩膀上

由于前段时间时间轴形式的展示方式比较火,就考虑采用这种方式。但是查阅了网上的jQuery timeline plugin,大部分都比较臃肿,还需要创建Google Spreadsheet Template,并且通过JavaScript调整时间轴中每个记录的位置,也不适合软件更新记录这样大数据集的展现。

其实我需要的只是一个简单、漂亮的数据展示方式,很快我找到了这个例子:http://tympanus.net/Blueprints/VerticalTimeline/

image

这个界面风格给人眼前一亮的感觉。在快速浏览之后,我发现这里面用到了内嵌字体和CSS3的诸多知识来生成哪些漂亮的图片,所以在IE7、IE8下浏览会乱作一团,如下图所示:

image

 

没关系,我们就用简单的图片来代替,其实我最想要的就是左侧的那个垂直直线和那个圆粑粑,网页截图,然后用PhotoShop做简单的处理,得到如下三张图片。

1. 垂直线(10*7)

version_line

2. 浅色的圆粑粑(56*56)

version_dot_alt

3. 深色的圆粑粑(56*56)

version_dot

两个不同颜色的圆粑粑是为了让列表看起来更灵动一点。

 

俺的PhotoShop功底不咋地,你会发现那两个圆粑粑不是透明背景,而是白色背景的,没关系,只要我们使用精确的CSS定位,看不出破绽的,^_^

 

最终我们希望实现的效果如下图所示。

image

其中圆粑粑中的数字表示软件的第几个版本,是不是看着比原来的好多了。

 

下面我们就动手实现,纯手工哦,用到的开发工具只有Notepad++(My favorite!)。

 

最简单的HTML结构

HTML结构一定要保持简单,其实就是一个列表嘛,那就用 UL 标签实现。

1: <ul class="timeline">
 2:  <li>
 3:  <div class="time">时间</div>
 4:  <div class="version">版本号</div>
 5:  <div class="number">第几个版本</div>
 6:  <div class="content">
 7:  <pre>
 8:  更新记录
 9:  </pre>
 10:  </div>
 11:  </li>
 12: <ul>

初步的设想是content左边留白,time/version/number全部浮动起来,这样方便定位。

特别是number的定位要准确,否则圆粑粑和背景垂直线就重合不到一起了。这就要看CSS的了。

 

最简单的CSS

我们主要来看看如何对number的定位,完整的代码在文章最后会给出。

 1: ul.timeline {
 2:  list-style-type: none;
 3:  background: url("../res/img/version_line.png") repeat-y scroll 120px 0 transparent;
 4:  margin: 50px 0;
 5:  padding: 0;
 6: }
 7: ul.timeline li {
 8:  position: relative;
 9:  margin-bottom: 20px;
 10: }
 11:  
 12: ul.timeline li .number {
 13:  position: absolute;
 14:  background: url("../res/img/version_dot.png") no-repeat scroll 0 0 transparent;
 15:  width: 56px;
 16:  height: 56px;
 17:  left: 97px;
 18:  line-height: 56px;
 19:  text-align: center;
 20:  color: #fff;
 21:  font-size: 18px;
 22: }

首先,将垂直蓝色的背景线放在最外层的 UL 标签上,距离左侧 120px;

其次,设置 LI 为相对定位,为 LI 中元素的绝对定位做铺垫;

最后,将number浮动起来,主要是number的left属性一定要精确!

 

如何计算 number 的 left 属性那,大家看看如下的公式是否合你口味:

number.left = line.left + line.width/2 – number.width/2

                      = 120 + 10/2 – 56/2

                      =  97

 

最简单的JQUERY

剩下就是jQuery的任务了,我们需要使用jQuery完成如下两点任务:

1. 动态计算 number 的数字;

2. 为间隔行的 LI 节点添加 alt 类。

 1: $(function() {
 2: 
 3:  var liNodes = $('ul.timeline li'), count = liNodes.length, i, liNode;
 4:  for(i=0; i<count; i++) {
 5:  liNode = $(liNodes.get(i));
 6:  if(i % 2 !== 0) {
 7:  liNode.addClass('alt');
 8:  }
 9:  liNode.find('.number').text(count - i);
 10:  }
 11:  
 12: });

最简单的数据迁移(正则表达式替换)

还有一项重要的任务,如何把 100 多条数据迁移到新的 HTML 结构中去,没人愿意手工去做,没关系我们有好帮手 Notepad++。

image

查找目标:\+(\d{4}-\d{2}-\d{2})\s+(v\d+.*)$

替换为:</pre></div></li>\r\n<li><div class="time">$1</div><div class="version">$2</div><div class="number"></div><div class="content"><pre>

 

查找目标用来匹配类似“+2013-07-29 v3.3.1”的字符串,一次搞定,是不是很舒服。

 

完成效果

image

列表实在是太长,这里只是 5% 不到的截图!

 

优化!将页面大小由150K减少为20K

本来文章就此结束了,可是吃完饭我就不满意了,还有改进的余地!

1. 一次展示 100 多个记录,用户也看不完,反而影响显示效果,长长长长长长长长长的滚动条;

2. 用户关心的可能只是最近的几次更新记录,如果需要看更多的,提供一种方法即可!

 

基于以上考虑,我们可以将 100 多个记录分成 20 个记录一个文本文件保存起来,需要的时候通过 AJAX 获取就行了。

页面首次加载只需要前 10 条左右的记录即可,在列表的最后添加一个大大的按钮,如下图所示。

image

 

最终的目录结构如下所示。

image

 

来体验一下最终的效果吧:

http://fineui.com/version

 

 

全部源代码

 1: <style>
 2:  ul.timeline {
 3:  list-style-type: none;
 4:  background: url("../res/img/version_line.png") repeat-y scroll 120px 0 transparent;
 5:  margin: 50px 0;
 6:  padding: 0;
 7:  }
 8:  
 9:  ul.timeline li {
 10:  position: relative;
 11:  margin-bottom: 20px;
 12:  }
 13:  ul.timeline li .time {
 14:  position: absolute;
 15:  width: 90px;
 16:  text-align: right;
 17:  left: 0;
 18:  top: 10px;
 19:  color: #999;
 20:  }
 21:  ul.timeline li .version {
 22:  position: absolute;
 23:  width: 290px;
 24:  text-align: right;
 25:  left: -200px;
 26:  top: 30px;
 27:  font-size: 40px;
 28:  line-height: 50px;
 29:  color: #3594cb;
 30:  overflow: hidden;
 31:  }
 32:  ul.timeline li .number {
 33:  position: absolute;
 34:  background: url("../res/img/version_dot.png") no-repeat scroll 0 0 transparent;
 35:  width: 56px;
 36:  height: 56px;
 37:  left: 97px;
 38:  line-height: 56px;
 39:  text-align: center;
 40:  color: #fff;
 41:  font-size: 18px;
 42:  }
 43:  ul.timeline li.alt .number {
 44:  background-image: url("../res/img/version_dot_alt.png");
 45:  }
 46:  ul.timeline li .content {
 47:  margin-left: 180px;
 48: 
 49:  }
 50:  ul.timeline li .content pre {
 51:  background-color: #3594cb;
 52:  padding: 20px;
 53:  color: #fff;
 54:  font-size: 13px;
 55:  line-height: 20px;
 56:  }
 57:  ul.timeline li.alt .content pre {
 58:  background-color: #43B1F1;
 59:  }
 60: </style>
 61: <ul class="timeline">
 62:  <li>
 63:  <div class="time">2013-07-29</div>
 64:  <div class="version">v3.3.1</div>
 65:  <div class="number"></div>
 66:  <div class="content">
 67:  <pre>
 68:  -将工具YUICompressor替换为Microsoft Ajax Minifier(需要指定-evals:immediate)。
 69:  ...
 70:  </pre>
 71:  </div>
 72:  </li>
 73:  ...
 74: </ul>
 75: <script>
 76:  $(function() {
 77: 
 78:  var nextDataNumber = 5;
 79: 
 80:  var ulNode = $('ul.timeline');
 81: 
 82:  function initLiNodes() {
 83:  var liNodes = ulNode.find('li'), count = liNodes.length, i, liNode, leftCount = nextDataNumber * 20;
 84:  for(i=0; i<count; i++) {
 85:  liNode = $(liNodes.get(i));
 86:  if(i % 2 !== 0) {
 87:  liNode.addClass('alt');
 88:  } else {
 89:  liNode.removeClass('alt');
 90:  }
 91:  liNode.find('.number').text(leftCount + count - i);
 92:  }
 93:  }
 94: 
 95: 
 96:  $('#fetchNextData').click(function() {
 97:  var $this = $(this);
 98:  $this.addClass('disabled').text('......');
 99: 
 100:  $.get('./version_data_' + nextDataNumber +'.txt', function(data) {
 101:  ulNode.append(data);
 102:  $this.removeClass('disabled').text('后二十条数据');
 103:  nextDataNumber--;
 104: 
 105:  if(nextDataNumber === 0) {
 106:  $this.hide();
 107:  }
 108: 
 109:  initLiNodes();
 110:  });
 111: 
 112:  });
 113: 
 114:  initLiNodes();
 115: 
 116:  });
 117: </script>

小结

如何向用户有效的展示 100 多条更新记录,是个技术活。需要我们认真思考,学以致用,用最简单的HTML、CSS、JQUERY来实现最好的用户体验。


后记 

网友 混世顽童 提到是否可以在滚动条到达底部时自动加载后20条数据,这个也很容易实现,更新后的JavaScript代码如下所示。

$(function() {
		
	var nextDataNumber = 5;
	var ajaxLoading = false;
	var docNode = $(document);
	
	var ulNode = $('ul.timeline');
	
	function initLiNodes() {
		var liNodes = ulNode.find('li'), count = liNodes.length, i, liNode, leftCount = nextDataNumber * 20;
		for(i=0; i<count; i++) {
			liNode = $(liNodes.get(i));
			if(i % 2 !== 0) {
				liNode.addClass('alt');
			} else {
				liNode.removeClass('alt');
			}
			liNode.find('.number').text(leftCount + count - i);
		}
	}
	
	
	$('#fetchNextData').click(function() {
		var $this = $(this);
		$this.addClass('disabled').text('正在加载后二十条数据...');
		ajaxLoading = true;
		
		$.get('./version_data_' + nextDataNumber +'.txt', function(data) {
			ajaxLoading = false;
			ulNode.append(data);
			$this.removeClass('disabled').text('后二十条数据');
			nextDataNumber--;
			
			if(nextDataNumber === 0) {
				$this.hide();
			}
			
			initLiNodes();
		});
		
	});

	initLiNodes();
	
	docNode.scroll(function() {
		
		if(docNode.height() - $(window).height() - docNode.scrollTop() < 10) {
			if(!ajaxLoading) {
				$('#fetchNextData').click();
			}	
		}
		
	});
	
});


接着阅读姊妹篇《纯手工打造漂亮的瀑布流,五大插件一个都不少Bootstrap+jQuery+Masonry+imagesLoaded+Lightbox!》

你可能感兴趣的:(html,jquery,css,FineUI)