JS时间轴效果(类似于qq空间时间轴效果)
2013-11-04 23:51 龙恩0707 阅读(7667) 评论(15) 编辑 收藏 举报在上一家公司写了一个时间轴效果,今天整理了下,感觉有必要写一篇博客出来 给大家分享分享 当然代码还有很多不足的地方,希望大家多指点指点下,此效果类似于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代码 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | <style> .tao-allMonth-w 990 { 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 h 3 { 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. 点击控制轴任一年份时候 滚动到条目列表中相对应的年份来.
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | 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. 最后 点击控制轴当前年份中的月份时候 滚动到当前的月份的地方。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | // 点击控制轴当前年份中的月份时候 滚动到当前的月份的地方。 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代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | 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({});
});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端