JS时间轴效果(类似于qq空间时间轴效果)
在上一家公司写了一个时间轴效果,今天整理了下,感觉有必要写一篇博客出来 给大家分享分享 当然代码还有很多不足的地方,希望大家多指点指点下,此效果类似于QQ空间或者人人网空间时间轴效果,当时也是为了需求 研究了下qq空间逻辑(当然JS代码压缩了肯定看不到的),只是当时研究了下他们HTML结构和css结构,所以仿照他们那种逻辑自己也写了一个出来。先来看看是个什么样的吧!如下图所示:

需求分析:左侧是一个时间列表 右侧是一个时间控制抽,当时的需求是这样的:默认页面一打开 只加载当前年份所有列表加载出来 当前年份的控制轴展开出来,默认的焦点在最近的月份,如上图在当前的10月份或者下图的12月份,当滚动条滚动的时候再继续判断 如果左侧滚动到几月份的时候 那么右侧控制抽当前的焦点也在几月份,当滚动到上一个年份的时候 那么当前的年份控制轴收缩起来 上一个年份控制轴展开出来,如下图所示:

当我们点击某一年份的时候 滚动到当前的年份,当我点击某一年中某一月份的时候 滚动到当前年份中对应的月份上来。
当然下面的代码我是用到的是淘宝的KISSY框架 当然如果改成Jquery框架也是一样的,没有很大的差别 只是用了一下"延迟加载"和一些选择器而已,首先我们如果要做成这样的话 要知道有2个请求 一个是左侧列表请求返回的数据 一个是右侧的年份和月份返回的数据 下面我们可以先来看看 开发给我当时返回的数据格式是个什么样的,
左侧列表的JSON数据如下图:

默认情况下是最近年份 当我滚动到2012年时候 再继续发个2012年的请求 把2012年的相对应的数据渲染出来,同理2011年也一样.
再来看看年份和月份的JSON数据吧 如下图:

下面我一步步来分析下 我当时的做法:
1. 首先我需要HTML结构 如下图所示:
<div class="tao-allMonth-w990">
<div class="tao-video-left J_Video_Left" id="J_Video_Left"></div>
<div class="tao-year-right">
<div class="mod-timelinenav">
<ul id="timelinenavpanel" class="timelinenav-panel isScroll"></ul>
</div>
</div>
</div>
其中 id="J_Video_Left" 和 id="timelinenavpanel" 在初始化的时候 是可以配置的 也就是说 他们叫什么名字并不重要,依赖于这个HTML结构。
2. 依赖于css代码 如下:
<style>
.tao-allMonth-w990 {width: 990px;margin: 100px auto 0;overflow: hidden; }
.tao-video-left {float:left;width: 620px;overflow: hidden;}
.tao-video-block {width: 620px;overflow: hidden;}
.tao-header-title {width: 100%;height: 26px;overflow: hidden;}
.tao-header-title {color: #FF6600;font-family: "Microsoft yahei";font-size: 18px;font-weight: 700;padding-left: 42px;}
.tao-dottle-top {width: 10px;height: 40px;margin-left: 68px;background: none repeat scroll 0 0 #FFCC99;overflow: hidden; }
.tao-video-content {position: relative;width: 620px;overflow: hidden;}
.tao-video-content .addBlock {
background: none repeat scroll 0 0 #FFCC99;
height: 16px;
left: 68px;
position: absolute;
width: 10px;
}
.left-date {
color: #FF6600;
float: left;
font-family: "Microsoft yahei";
font-size: 14px;
height: 20px;
line-height: 20px;
margin-top: 18px;
overflow: hidden;
width: 60px;
}
.left-date span {
float: left;
}
.tao-video-content .tao-line {
background: url("http://img02.taobaocdn.com/tps/i2/T1je8uXEBgXXagEfc2-10-205.png") no-repeat scroll 0 0 rgba(0, 0, 0, 0);
display: inline;
float: left;
height: 205px;
margin: 24px 0 0 8px;
overflow: hidden;
width: 10px;
}
.tao-inner-content {
background: url("http://img03.taobaocdn.com/tps/i3/T16VXtXBNiXXXPeW.X-519-190.png") no-repeat scroll 0 0 rgba(0, 0, 0, 0);
display: inline;
float: left;
height: 190px;
margin: 0 0 0 20px;
overflow: hidden;
width: 519px;
}
.tao-inner-block {
height: 130px;
margin: 30px 0 0 40px;
overflow: hidden;
width: 450px;
}
.tao-inner-block .inner-left {
float: left;
height: 130px;
overflow: hidden;
width: 230px;
}
.inner-left .alink {
display: block;
height: 130px;
overflow: hidden;
position: relative;
width: 230px;
}
.inner-left .alink img {
display: block;
height: 130px;
width: 230px;
}
.tao-inner-block .icon-player {
background: url("http://img02.taobaocdn.com/tps/i2/T1J5FFXy8cXXaiphQj-60-145.png") no-repeat scroll 0 -40px rgba(0, 0, 0, 0);
height: 50px;
left: 10px;
overflow: hidden;
position: absolute;
top: 68px;
width: 50px;
z-index: 10;
}
.inner-right {
float: right;
height: 130px;
width: 202px;
}
.inner-date {
color: #666666;
font-family: "Tahoma";
}
.inner-title {
height: 22px;
line-height: 22px;
margin-top: 5px;
overflow: hidden;
width: 202px;
}
.inner-title a {
color: #333333;
font-family: "Microsoft yahei";
font-size: 18px;
font-weight: 700;
}
.inner-title a:hover {
color: #FF1155;
text-decoration: none;
}
.inner-content {
color: #999999;
line-height: 18px;
margin-top: 12px;
}
.tao-year-right {
float: right;
overflow: hidden;
width: 311px;
}
.tao-year-right .mod-fixed {
overflow: hidden;
position: fixed;
top: 0;
width: 60px;
z-index: 10;
}
.mod-timelinenav {
margin-top: 20px;
}
.mod-timelinenav .yearlink {
display: inline-block;
}
.mod-timelinenav a {
display: inline-block;
}
.mod-timelinenav a:hover {
text-decoration: none;
}
.mod-timelinenav .yearlink, .mod-timelinenav .monthlink {
border-left: 10px solid #74C2FA;
color: #7FCCFF;
font-family: "Tahoma";
line-height: 20px;
padding-left: 8px;
}
.mod-timelinenav .norecord {
display: none;
}
.mod-timelinenav .active .yearlink, .mod-timelinenav .active .monthlink {
border-left: 10px solid #0099FF;
color: #0099FF;
font-family: "Tahoma";
line-height: 20px;
padding-left: 8px;
}
.mod-timelinenav .active .monthlink {
color: #7FCCFF;
}
.mod-timelinenav .highlight .monthlink {
color: #0099FF;
font-family: "Tahoma";
}
.mod-timelinenav .active .timelinenav-mpanel {
display: block;
}
.mod-timelinenav .timelinenav-mpanel {
display: none;
}
.timelinenav-panel {
overflow: hidden;
width: 60px;
}
.timelinenav-panel li {
margin: 1px 0;
}
.timelinenav-panel li.active, .timelinenav-panel li.active .timelinenav-mpanel li {
margin: 0;
}
.hot-footage {
bottom: 0;
overflow: hidden;
position: fixed;
width: 311px;
z-index: 8;
}
.hot-footage .dottle {
border-top: 1px solid #CCCCCC;
}
.hot-title {
margin-top: 12px;
}
.hot-icon {
background: none repeat scroll 0 0 #FF6600;
float: left;
height: 28px;
margin-top: 10px;
overflow: hidden;
width: 4px;
}
.hot-title h3 {
color: #333333;
font-family: "Microsoft yahei";
font-size: 30px;
font-weight: 500;
padding-left: 10px;
}
.hot-list {
margin-top: 5px;
overflow: hidden;
width: 311px;
}
.hot-list li {
display: inline;
float: left;
height: 150px;
margin: 5px 10px 0 0;
overflow: hidden;
width: 150px;
}
.hot-list li.last {
margin-right: 0;
}
.hot-list li a {
display: block;
height: 100px;
overflow: hidden;
position: relative;
width: 150px;
}
.hot-list .icon-player {
background: url("http://img02.taobaocdn.com/tps/i2/T1J5FFXy8cXXaiphQj-60-145.png") no-repeat scroll 0 -40px rgba(0, 0, 0, 0);
height: 50px;
left: 10px;
overflow: hidden;
position: absolute;
top: 40px;
width: 50px;
z-index: 10;
}
.hot-date {
color: #666666;
font-family: "Tahoma";
height: 18px;
line-height: 18px;
margin-top: 5px;
}
.hot-desc a:hover {
text-decoration: none;
}
</style>
3. 当然更依赖于kissy哦 要引入kissy:<script src="http://a.tbcdn.cn/??s/kissy/1.2.0/kissy-min.js"></script>
现在框架已经搭建好了,接下来我来分析下 当时我写的JS代码。首先我想渲染左侧年份列表出来 及右侧控制轴渲染出来 如下图:


所以上面的代码是渲染年份列表的 如下:
/*
* 发jsonp请求
* 1.渲染列表中的所有年份HTML出来
* 2.把控制轴上的所有年份及月份及条目列表中的年份渲染出来
*/
S.jsonp(_config.year_url + "×tamp="+S.now(),function(data){
_renderYear(data);
});
function _renderYear(data) {
if(data.isSuccess) {
var yearlists = data.list,
yearHTML = '',
liHTML = '';
/*
* 渲染列表中的所有年份HTML出来
*/
for(var i = 0, ilen = yearlists.length; i < ilen; i+=1) {
yearHTML += '<div class="J_Year_Month">'+
'<div class="tao-header-title J_Header_Title">'+
'<span data-year="'+yearlists[i].year+'" class="J_Year">'+yearlists[i].year+'<i>年</i></span>'+
'</div>' +
'<div class="tao-dottle-top"></div>' +
'<div class="J_Video_Block"></div>' +
'</div>';
}
var recentlyYear = yearlists[0].year;
D.html(D.get(_config.videoContainer),yearHTML);
/*
* 把控制轴上的所有年份渲染出来
*/
for(i = 0,itemLen = yearlists.length; i < itemLen; i++){
liHTML += '<li data-year="'+yearlists[i].year+'" class="itemList">' +
'<a class="yearlink" href="#">'+yearlists[i].year+'年</a>' +
'<ul class="timelinenav-mpanel"></ul>' +
'</li>';
}
D.html(D.get(_config.listContainer),liHTML,false,function(){
D.addClass(D.get(_config.listContainer + " li"),_config.activeCls);
D.attr(D.get(_config.listContainer + " li"),{"index":"1"});
}); /*
* 分别渲染各个年份中的月份
*/
var monthContainers = D.query(".timelinenav-mpanel");
for(var m = 0, mlen = monthContainers.length; m < mlen; m+=1) {
var ulHTML = "";
for(var k = 0,subItems = yearlists[m].month.length; k < subItems; k+=1){
ulHTML += '<li data-year="'+yearlists[m].year+'" data-month="'+yearlists[m].month[k]+'" class="itemHover">' +
'<a class="monthlink" href="#">'+yearlists[m].month[k]+'月</a>' +
'</li>';
}
D.html(monthContainers[m],ulHTML,false,function(){ var headerTitle = D.query(".J_Year"),
itemLists = D.query(".itemList"),
videoBlocks = D.query(".J_Video_Block");
// 默认时候 当前年份 最近月份高亮
D.addClass(D.get(".itemHover"),_config.highlightCls);
});
}
4. 接着发请求 把左侧列表中最近年份 下的所有月份渲染出来 如下代码可以实现:
var self = this,
_config = self.config;
var allYears = D.query(".J_Year_Month"); S.each(allYears,function(everyYear,index){
var jYear = D.get(".J_Year",everyYear),
jDataYear = D.attr(jYear,"data-year"),
jTextArea = D.get(".J_Video_Block",everyYear);
S.jsonp(_config.list_url+"&group="+jDataYear+"×tamp="+S.now(),function(data){
if(data.isSuccess){
var dataLists = data.list,
dataContainer = "";
for(var x=0,xlen=dataLists.length; x<xlen; x+=1){
var tempGroupId = dataLists[x].group_id;
dataContainer +='<div class="tao-video-content">'+
'<div class="addBlock"></div>' +
'<div class="left-date" videoMonth="'+tempGroupId.substring(4,6)+'">'+
'<span><i class="J_Month" M_year="'+tempGroupId.substring(0,4)+'">'+tempGroupId.substring(4,6)+'</i>月</span>'+
'<span><i class="J_Day">'+tempGroupId.substring(6,8)+'</i>日</span>'+
'</div>'+
'<div class="tao-line"></div>'+
'<div class="tao-inner-content">'+
'<div class="tao-inner-block">'+
'<div class="inner-left">'+
'<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'" class="alink">'+
'<img src="'+dataLists[x].video_pic.replace("/0","/1")+'" alt="">'+
'<span class="icon-player"></span>'+
'</a>'+
'</div>'+
'<div class="inner-right">'+
'<p class="inner-date">'+tempGroupId.substring(0,4)+'-'+tempGroupId.substring(4,6)+'-'+tempGroupId.substring(6,8)+'</p>'+
'<p class="inner-title">' +
'<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'">'+dataLists[x].subject+'</a>'+
'</p>'+
'<div class="inner-content">'+dataLists[x].content+'</div>'+
'</div>'+
'</div>'+
'</div>'+
'</div>';
}
if(flag == 'hover') {
(new DataLazyload(everyYear, {diff: 200})).addCallback(everyYear, function(){
self._isDelayLoad(jTextArea,dataContainer,index);
});
}
我上面的代码也有个小缺点 就是说页面一打开的时候 联系发了四个请求 把所有年份都渲染出来 但是数据并没有到页面上来 还是以前的逻辑 当滚动条滚动到离还有200像素的时候 再把数据渲染到页面上来。
5. 接着再做了以下事情:
1. 列表中的年份和控制轴中的年份相等时候 控制轴的年份展开。
2. 当滚动到列表中年份中的月份时候 对应的控制轴月份也要相应的变化(如高亮等),随着鼠标滚动。
3. 点击控制轴任一年份时候 滚动到条目列表中相对应的年份来.
代码如下:
var self = this,
_config = self.config,
_cache = self.cache; D.html(jTextArea,dataContainer,false,function(){
var itemLists = D.query(_config.listContainer + " .itemList"),
itemHover = D.query(".itemHover",itemLists[index]),
jmonths = D.query(".J_Month",jTextArea[index]),
headerTitle = D.query(".J_Year");
// 默认时候 当前年份 最近月份高亮
D.addClass(D.get(".itemHover"),_config.highlightCls); var storage = function(itemFChar){
for(var i = 0, ilen = itemHover.length; i < ilen; i+=1){
var itemMonth = D.attr(itemHover[i],"data-month");
if(itemMonth == itemFChar){
KISSY.all(itemHover[i]).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
}
}
};
E.on(window,'scroll',function(){
if(D.hasClass(D.get(_config.listContainer),'isScroll')){
var wTop = D.offset(window).top;
/*** 列表中的年份和控制轴中的年份相等时候 控制轴的年份展开 ***/
for(var m=0,mlen=headerTitle.length; m<mlen; m+=1){
var headerTop = D.offset(headerTitle[m]).top,
headAttr = D.attr(headerTitle[m],"data-year"),
itemAttr = D.attr(itemLists[m],"data-year");
if(headerTop <= wTop){
if(headAttr == itemAttr){
KISSY.all(itemLists[m]).addClass(_config.activeCls).siblings().removeClass(_config.activeCls);
}
}
}
/*** 当滚动到列表中年份中的月份时候 对应的控制轴月份也要相应的变化(如高亮等) **/
for(var nn = 0, nlen = jmonths.length; nn < nlen; nn+=1){
var jmonthTop = D.offset(jmonths[nn]).top;
if(jmonthTop <= wTop){ var itemVal = D.html(jmonths[nn]),
// 转换02 -> 2
itemFChar = itemVal.substring(0,1);
if(itemFChar == 0){
itemFChar = itemVal.substring(1,2);
}else{
itemFChar = itemVal.substring(0,2);
}
storage(itemFChar);
}
}
}
});
// 点击控制轴任一年份时候 滚动到条目列表中相对应的年份来
var itemLists = D.query(_config.listContainer + " .itemList");
S.each(itemLists,function(item,index){
var innerIndex;
E.on(item,'click',function(e){
e.preventDefault();
e.halt();
innerIndex = index;
var scrollTimer,
DELAY = 0.3;
!D.hasClass(KISSY.all(this),_config.activeCls) && KISSY.all(this).addClass(_config.activeCls).siblings().removeClass(_config.activeCls); if(!D.hasClass(KISSY.all(this),"isClick")){
D.addClass(KISSY.all(this),"isClick");
}
var curThis = KISSY.all(this);
// 删除类
D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
var headerTop = D.offset(headerTitle[index]).top;
scrollTimer && scrollTimer.cancel();
scrollTimer = S.later(function(){
KISSY.all("html,body").animate({"scrollTop":headerTop},DELAY,'easeBothStrong',function(){
D.removeClass(D.query(".itemHover"),_config.highlightCls);
!D.hasClass(D.get(".itemHover",curThis),_config.highlightCls) && D.addClass(D.get(".itemHover",curThis),_config.highlightCls);
!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
});
},DELAY);
_config.yearCallback && S.isFunction(_config.yearCallback) && _config.yearCallback();
self._clickMenu(itemLists,innerIndex);
});
if(innerIndex == undefined){
innerIndex = 0;
self._clickMenu(itemLists,innerIndex);
}
});
6. 最后 点击控制轴当前年份中的月份时候 滚动到当前的月份的地方。代码如下:
// 点击控制轴当前年份中的月份时候 滚动到当前的月份的地方。
var itemHovers = D.query(".itemHover",KISSY.all(itemLists[innerIndex]));
S.each(itemHovers,function(itemHover,curIndex){
E.on(itemHover,'click',function(e){ e.halt();
var itemMonth = D.attr(KISSY.all(itemHover),"data-month");
var tempArr = [],
scrollTimer,
DELAY = 0.1;
console.log(itemMonth);
var curMonths = D.query(".left-date",D.query(".J_Year_Month")[innerIndex]);
// 删除类
D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
KISSY.all('.itemHover').removeClass(_config.highlightCls);
KISSY.all(this).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
for(var i=0; i<curMonths.length; i+=1){
var itemVal = D.attr(curMonths[i],"videoMonth");
// 转换02 -> 2
var itemFChar = itemVal.substring(0,1);
if(itemFChar == 0){
itemFChar = itemVal.substring(1,2);
}else{
itemFChar = itemVal.substring(0,2);
}
tempArr.push(itemFChar);
}
for(var j=0; j<tempArr.length; j+=1){
var tempV = tempArr[j];
if(itemMonth == tempArr[j]){
var mtop = D.offset(curMonths[j]).top;
scrollTimer && scrollTimer.cancel();
scrollTimer = S.later(function(){
KISSY.all("html,body").animate({"scrollTop":mtop},DELAY,'easeBothStrong',function(){
!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
});
},DELAY);
break; // 此break是当数组里面的月份有多个相同的时候 只取第一个月份
}
}
_config.monthCallback && S.isFunction(_config.monthCallback) && _config.monthCallback();
综合以上 所有JS代码如下:
KISSY.add('timeline/nav',function(S,DataLazyload){
	var D = S.DOM,
		E = S.Event;
	function TimeLineNav() {
		this.config = {
			year_url       :'http://bbs.hitao.com/apps.php?q=tvshow&m=video_years',    //所有年份URL
			list_url       :'http://bbs.hitao.com/apps.php?q=tvshow&m=video_group',    // 时间轴list列表 URL
			delay          : 100,                                                      // 延迟time
			highlightCls   :'highlight',                                               // 高亮类
			fixedCls       :'mod-fixed',                                               // fixed类
			activeCls      :'active',                                                  // 当前active class
			videoContainer :'#J_Video_Left',                                           // 左侧视频容器
			listContainer  :'#timelinenavpanel',                                       // 控制轴容器
			yearCallback   : null,                                                     // 点击某一项年份时的回调函数
			monthCallBack  : null                                                      // 点击某一项月份时候回调
		};
		this.cache = {
		};
	}
	TimeLineNav.prototype = {
		init: function(options) {
			this.config = S.augment(this.config,options || {});
            var self = this,
                _config = self.config;
			/*
			 * 发jsonp请求
			 * 1.渲染列表中的所有年份HTML出来
			 * 2.把控制轴上的所有年份及月份及条目列表中的年份渲染出来
			 */
			 S.jsonp(_config.year_url + "×tamp="+S.now(),function(data){
				_renderYear(data);
			 });
			 function _renderYear(data) {
				if(data.isSuccess) {
					var yearlists = data.list,
						yearHTML = '',
						liHTML = '';
					/*
					 * 渲染列表中的所有年份HTML出来
					 */
				     for(var i = 0, ilen = yearlists.length; i < ilen; i+=1) {
						yearHTML += '<div class="J_Year_Month">'+
										'<div class="tao-header-title J_Header_Title">'+
											'<span data-year="'+yearlists[i].year+'" class="J_Year">'+yearlists[i].year+'<i>年</i></span>'+
										'</div>' +
										'<div class="tao-dottle-top"></div>' +
										'<div class="J_Video_Block"></div>' +
									'</div>';
					 }
					 var recentlyYear = yearlists[0].year;
					 D.html(D.get(_config.videoContainer),yearHTML);
				     /*
					  * 把控制轴上的所有年份渲染出来
					  */
					 for(i = 0,itemLen = yearlists.length; i < itemLen; i++){
						liHTML += '<li data-year="'+yearlists[i].year+'" class="itemList">' +
									 '<a class="yearlink" href="#">'+yearlists[i].year+'年</a>' +
									 '<ul class="timelinenav-mpanel"></ul>' +
								   '</li>';
					 }
					 D.html(D.get(_config.listContainer),liHTML,false,function(){
						D.addClass(D.get(_config.listContainer + " li"),_config.activeCls);
						D.attr(D.get(_config.listContainer + " li"),{"index":"1"});
					 });
					 /*
					  * 分别渲染各个年份中的月份
					  */
					 var monthContainers = D.query(".timelinenav-mpanel");
					 for(var m = 0, mlen = monthContainers.length; m < mlen; m+=1) {
						var ulHTML = "";
						for(var k = 0,subItems = yearlists[m].month.length; k < subItems; k+=1){
							ulHTML += '<li data-year="'+yearlists[m].year+'" data-month="'+yearlists[m].month[k]+'" class="itemHover">' +
										 '<a class="monthlink" href="#">'+yearlists[m].month[k]+'月</a>' +
									   '</li>';
						}
						D.html(monthContainers[m],ulHTML,false,function(){
							var headerTitle = D.query(".J_Year"),
								itemLists = D.query(".itemList"),
								videoBlocks = D.query(".J_Video_Block");
							// 默认时候 当前年份 最近月份高亮
							D.addClass(D.get(".itemHover"),_config.highlightCls);
						});
					 }
					self._query('hover');
				}else {
					return;
				}
			 }
		    /*
			 * 1.滚动条先滚动 当离顶部距离差距不大的时候 使右侧菜单固定在顶部20px;
			 */
			var timelineTop = D.offset(".mod-timelinenav").top,
				scrollTimer;
			E.on(window,'scroll',function(){
				scrollTimer && scrollTimer.cancel();
				scrollTimer = S.later(function(){
					var windowTop = D.offset(window).top;
					if(timelineTop <=windowTop){
						D.addClass(".mod-timelinenav","mod-fixed");
					}else{
						D.removeClass(".mod-timelinenav","mod-fixed");
					}
				},_config.delay);
			});
		},
		_query: function(flag) {
			var self = this,
				_config = self.config;
			var allYears = D.query(".J_Year_Month");
			S.each(allYears,function(everyYear,index){
				var jYear = D.get(".J_Year",everyYear),
					jDataYear = D.attr(jYear,"data-year"),
					jTextArea = D.get(".J_Video_Block",everyYear);
				S.jsonp(_config.list_url+"&group="+jDataYear+"×tamp="+S.now(),function(data){
					if(data.isSuccess){
						var dataLists = data.list,
							dataContainer = "";
						for(var x=0,xlen=dataLists.length; x<xlen; x+=1){
							var tempGroupId = dataLists[x].group_id;
							dataContainer +='<div class="tao-video-content">'+
												'<div class="addBlock"></div>' +
												'<div class="left-date" videoMonth="'+tempGroupId.substring(4,6)+'">'+
													'<span><i class="J_Month" M_year="'+tempGroupId.substring(0,4)+'">'+tempGroupId.substring(4,6)+'</i>月</span>'+
													'<span><i class="J_Day">'+tempGroupId.substring(6,8)+'</i>日</span>'+
												'</div>'+
												'<div class="tao-line"></div>'+
												'<div class="tao-inner-content">'+
													'<div class="tao-inner-block">'+
														'<div class="inner-left">'+
															'<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'" class="alink">'+
																'<img src="'+dataLists[x].video_pic.replace("/0","/1")+'" alt="">'+
																'<span class="icon-player"></span>'+
															'</a>'+
														'</div>'+
														'<div class="inner-right">'+
															'<p class="inner-date">'+tempGroupId.substring(0,4)+'-'+tempGroupId.substring(4,6)+'-'+tempGroupId.substring(6,8)+'</p>'+
															'<p class="inner-title">' +
																'<a href="http://bbs.hitao.com/apps.php?q=tvshow&m=detail_new&tid='+dataLists[x].tid+'">'+dataLists[x].subject+'</a>'+
															'</p>'+
															'<div class="inner-content">'+dataLists[x].content+'</div>'+
														'</div>'+
													'</div>'+
												'</div>'+
											 '</div>';
						}
						if(flag == 'hover') {
							(new DataLazyload(everyYear, {diff: 200})).addCallback(everyYear, function(){
								self._isDelayLoad(jTextArea,dataContainer,index);
							});
						}
					}else {
						return;
					}
				});
			});
		},
		_isDelayLoad: function(jTextArea,dataContainer,index) {
			var self = this,
				_config = self.config,
				_cache = self.cache;
			D.html(jTextArea,dataContainer,false,function(){
				var	itemLists = D.query(_config.listContainer + " .itemList"),
					itemHover = D.query(".itemHover",itemLists[index]),
					jmonths = D.query(".J_Month",jTextArea[index]),
					headerTitle = D.query(".J_Year");
				// 默认时候 当前年份 最近月份高亮
				D.addClass(D.get(".itemHover"),_config.highlightCls);
				var storage = function(itemFChar){
					for(var i = 0, ilen = itemHover.length; i < ilen; i+=1){
						 var itemMonth = D.attr(itemHover[i],"data-month");
						 if(itemMonth == itemFChar){
							KISSY.all(itemHover[i]).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
						}
					}
				};
				E.on(window,'scroll',function(){
					if(D.hasClass(D.get(_config.listContainer),'isScroll')){
						var wTop = D.offset(window).top;
						/*** 列表中的年份和控制轴中的年份相等时候 控制轴的年份展开 ***/
						for(var m=0,mlen=headerTitle.length; m<mlen; m+=1){
							var headerTop = D.offset(headerTitle[m]).top,
								headAttr = D.attr(headerTitle[m],"data-year"),
								itemAttr = D.attr(itemLists[m],"data-year");
							if(headerTop <= wTop){
								if(headAttr == itemAttr){
									KISSY.all(itemLists[m]).addClass(_config.activeCls).siblings().removeClass(_config.activeCls);
								}
							}
						}
						/*** 当滚动到列表中年份中的月份时候 对应的控制轴月份也要相应的变化(如高亮等) **/
						for(var nn = 0, nlen = jmonths.length; nn < nlen; nn+=1){
							var jmonthTop = D.offset(jmonths[nn]).top;
							if(jmonthTop <= wTop){
								var itemVal = D.html(jmonths[nn]),
								// 转换02 -> 2
								itemFChar = itemVal.substring(0,1);
								if(itemFChar == 0){
									itemFChar = itemVal.substring(1,2);
								}else{
									itemFChar = itemVal.substring(0,2);
								}
								storage(itemFChar);
							}
						}
					}
				});
				// 点击控制轴任一年份时候 滚动到条目列表中相对应的年份来
			   var	itemLists = D.query(_config.listContainer + " .itemList");
			   S.each(itemLists,function(item,index){
				   var innerIndex;
				   E.on(item,'click',function(e){
					   e.preventDefault();
					   e.halt();
					   innerIndex = index;
					   var scrollTimer,
						   DELAY = 0.3;
					   !D.hasClass(KISSY.all(this),_config.activeCls) && KISSY.all(this).addClass(_config.activeCls).siblings().removeClass(_config.activeCls);
					   if(!D.hasClass(KISSY.all(this),"isClick")){
						   D.addClass(KISSY.all(this),"isClick");
					   }
					   var curThis = KISSY.all(this);
					   // 删除类
					   D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
					   var headerTop = D.offset(headerTitle[index]).top;
					   scrollTimer && scrollTimer.cancel();
					   scrollTimer = S.later(function(){
							KISSY.all("html,body").animate({"scrollTop":headerTop},DELAY,'easeBothStrong',function(){
								D.removeClass(D.query(".itemHover"),_config.highlightCls);
								!D.hasClass(D.get(".itemHover",curThis),_config.highlightCls) && D.addClass(D.get(".itemHover",curThis),_config.highlightCls);
								!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
							});
						},DELAY);
						_config.yearCallback && S.isFunction(_config.yearCallback) && _config.yearCallback();
						self._clickMenu(itemLists,innerIndex);
				   });
				   if(innerIndex == undefined){
					  innerIndex = 0;
					  self._clickMenu(itemLists,innerIndex);
				   }
			   });
			});
		},
		_clickMenu: function(itemLists,innerIndex) {
			var self = this,
				_config = self.config;
			if(innerIndex == undefined){
				return;
			}
			// 点击控制轴当前年份中的月份时候 滚动到当前的月份的地方。
		    var itemHovers = D.query(".itemHover",KISSY.all(itemLists[innerIndex]));
			S.each(itemHovers,function(itemHover,curIndex){
				E.on(itemHover,'click',function(e){
					e.halt();
					var itemMonth = D.attr(KISSY.all(itemHover),"data-month");
					var tempArr = [],
						scrollTimer,
						DELAY = 0.1;
					console.log(itemMonth);
					var	curMonths = D.query(".left-date",D.query(".J_Year_Month")[innerIndex]);
					 // 删除类
					D.hasClass(D.get(_config.listContainer),'isScroll') && D.removeClass(D.get(_config.listContainer),'isScroll');
					KISSY.all('.itemHover').removeClass(_config.highlightCls);
					KISSY.all(this).addClass(_config.highlightCls).siblings().removeClass(_config.highlightCls);
					for(var i=0; i<curMonths.length; i+=1){
						var itemVal = D.attr(curMonths[i],"videoMonth");
						// 转换02 -> 2
						var itemFChar = itemVal.substring(0,1);
						if(itemFChar == 0){
							itemFChar = itemVal.substring(1,2);
						}else{
							itemFChar = itemVal.substring(0,2);
						}
						tempArr.push(itemFChar);
					}
					for(var j=0; j<tempArr.length; j+=1){
						var tempV = tempArr[j];
						if(itemMonth == tempArr[j]){
							var mtop = D.offset(curMonths[j]).top;
							scrollTimer && scrollTimer.cancel();
							scrollTimer = S.later(function(){
								KISSY.all("html,body").animate({"scrollTop":mtop},DELAY,'easeBothStrong',function(){
									!D.hasClass(D.get(_config.listContainer),'isScroll') && D.addClass(D.get(_config.listContainer),'isScroll');
								});
							},DELAY);
							break; // 此break是当数组里面的月份有多个相同的时候 只取第一个月份
						}
					}
					_config.monthCallback && S.isFunction(_config.monthCallback) && _config.monthCallback();
				});
			});
		}
	};
	return TimeLineNav;
},{requires:['datalazyload']});
JS初始化如下 :
  KISSY.use("timeline/nav",function(S,obj){
       new obj().init({});
 });
JS时间轴效果(类似于qq空间时间轴效果)的更多相关文章
- 自己动手写js分享插件 [支持https] (QQ空间,微信,新浪微博。。。)
		
转载:https://blog.csdn.net/libin_1/article/details/52424340 废话不多说,传送门:http://download.csdn.net/detail/ ...
 - 类似于qq空间类型的评论和回复
		
最近学习thinkphp,做了一个博客系统,其中感觉实现一个类似于qq空间的评论和回复功能比较复杂,所以把这次的经历记录下来,与大家共勉,具体的方法就不说了,在这里分享一下思路. 目标就是这种,关键是 ...
 - 仿QQ空间长图效果简易版--母亲节感恩
		
手机网站 母亲节最火的两件事 1.NBA 杜兰特在获MVP催泪致辞献给母亲:她才是真的MVP. 2.QQ空间长图 ------------------------------------------- ...
 - 08. Web大前端时代之:HTML5+CSS3入门系列 ~ QQ空间时间轴
		
Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 大前端系列,主要就是使用CSS3.0来实现,注释我已经打 ...
 - 实现类似于QQ空间相册的点击图片放大,再点后缩小回原来位置
		
前几天看到了有人在android5.0上实现了如下图一样的效果,我自己就去搜了下.参考了国外一篇文章和国内的一篇文章,最终实现了想要的效果.具体参考的网址我已经贴到文章末尾,大家可以去英文的那个网站看 ...
 - Android 实现类似于QQ空间相册的点击图片放大,再点后缩小回原来位置
		
前几天看到了有人在android5.0上实现了如下图一样的效果,我自己就去搜了下.参考了国外一篇文章和国内的一篇文章,最终实现了想要的效果.具体参考的网址我已经贴到文章末尾,大家可以去英文的那个网站看 ...
 - 自己动手写js分享插件 [支持https] (可以分享QQ空间,微信,新浪微博。。。)
		
由于百度分享,jiathis 等分享插件在https下均会报错,就萌生了自己动手写一个分享插件的念头,其实实现起来一点都不难,以下代码都已在https网站运行通过,特附上以下代码:还请各位看官不吝赐教 ...
 - QQ空间/朋友圈类界面的搭建
		
类似于QQ空间的布局主要是在说说信息.点赞.回复三大部分的自适应布局上. 当我们需要搭建类似QQ空间.微信朋友圈的界面的时候,可做如下操作: 创建一个对应的model类: 创建一个对应model类的f ...
 - 制作QQ空间的一些想法
		
新的项目开始了,这一次是做一个网站类似于QQ空间那样的,基本功能比如说写日志,说说之类的都要有(说说是要有楼中楼嵌套的,应该能够上传图片),还要可以修改个人信息.登录注册之类的更不用说了,还要有一定的 ...
 
随机推荐
- Angular4.x 自定义搜索组件
			
Angular4 随笔(三) ——自定义搜索组件 1.简介 本组件主要是实现了搜索功能,主要是通过父子组件传值实现. 基本逻辑: 1.创建一个搜索组件,如:ng g component searc ...
 - 初学HTML-4
			
img标签:<img src=" "> src——source缩写,告诉img标签需要显示的图片名称 属性:width:宽度 height:高度.若未指定宽和高,则 ...
 - apache2.2 +php7.3安装 编译安装
			
1.下载 http://archive.apache.org/dist/httpd/httpd-2.2.0.tar.gz tar -xvf httpd-2.2.0.tar.gz 2.安装 ./conf ...
 - 【代码笔记】iOS-MBProgressHUDDemo
			
一,工程图. 二,代码. RootViewController.h #import <UIKit/UIKit.h> //加入头文件 #import "MBProgressHUD. ...
 - 从零开始学习html(十五)css样式设置小技巧——上
			
一.水平居中设置-行内元素 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> ...
 - [iOS] 输入框高度随输入内容变化
			
一般,类似聊天软件的输入框默认都是显示一行的,在用户输入过程中根据输入文字的内容来改变输入框的高度,以便显示全部文字.像微信,QQ的输入框就是这样的.那么这个效果应该怎么实现呢? 新博客:wosson ...
 - jquery 绑定事件 获取方式 --------------data event 获取
			
//绑定事件 bind event $("body").on("click",function(){ console.log("in") } ...
 - BigDecimal 工具类
			
arg1.compareTo(arg2) arg1 > arg2 返回 int 1 arg1 = arg2 返回 int 0 arg1 < arg2 返回 int -1 public cl ...
 - C#中virtual(虚方法)的理解以及和abstract(抽象方法)的区别
			
Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例 ...
 - python基础学习10----集合
			
集合具有无序性,互异性 一.集合的建立 空集合 s=set() s={}#这样默认为是一个空字典 集合内的元素是可哈希的即不可变的数据类型 s={1,2,3,4} s=set([1,2,3,4]) s ...