腾讯新闻详情页有一个事件进展效果, 觉得挺有意思. 于是, 就有了本文的效果: 按数据源均分时间点幻灯. 花了三个多小时写的, 当然, 包括样式与调试. 兼容主流, 建议在Chrom,Firefox,Opera,Safari等标准浏览器中查看. IE下没有阴影及圆角.
实现了根据源数据(样例中是一个JSON数据组)总条数, 均分出时间点以平滑向右动画方式显示在时间线上, 当鼠标划过时间点时, 显示对应的日期及标题. 鼠标划过事件, 充分考虑了用户体验, 当用户快速(无意识移动)从时间点上划过时, 并不触发相应事件.
相关的方法说明及使用, 请参见下面的注释或发评论, 同时也欢迎大家找bug并提交.

JS核心代码点此查看样例
var JSONData=[{...},{...},...];//数据源,一切皆因它而生,因它而灭
function iTimePoint(iTimeSlideId, dateId, timeLineId, titleTop, titleId, defaultShow){
/* 传入参数说明:
* iTimeSlideId: 外围ID名. 本样例DOM中#itimeslide;
* dateId: 日期ID名. 本样例DOM中#date;
* timeLineId: 时间点分布ID名. 本样例DOM中#timeline;
* titleTop: 标题容器上方小三角ID名. 本样例DOM中#titletop;
* titleId: 标题容器ID名. 本样例DOM中#title;
* defaultShow: 设定初始显示的时间点, 默认为0, 可不传值
*/
//参数判断,测试用,成功运行后可删除
if (arguments.length < 5 || arguments.length>6) {
alert('参数传入错误,请传入5或6个值! :)');
return false;
}
//通用方法
var iBase = {
//document.getElementById
Id: function(name){
return document.getElementById(name);
},
//时间点动画显示
PointSlide: function(elem, val){
//可通过修改i+=5中的5控制滑动速度
for (var i = 0; i <= 100; i += 5) {
(function(){
//这个pos定义很重要,若直接使用闭包获取到的不是上面的i
var pos = i;
//平滑移动
setTimeout(function(){
elem.style.left = pos * val / 100 + 'px';
}, (pos + 1) * 10);
})();
}
},
//为元素添加样式
AddClass: function(elem, val){
//若元素无class,直接赋值
if (!elem.className) {
elem.className = val;
}else {
//否则通过添加空格新增一个class
var oVal = elem.className;
oVal += ' ';
oVal += val;
elem.className = val;
}
},
//获取元素索引
Index: function(cur, obj){
for (var i = 0; i < obj.length; i++) {
if (obj[i] == cur) {
return i;
}
}
}
}
//整个函数变量定义区
var dataLen = JSONData.length;
var iTimeSilde = iBase.Id(iTimeSlideId);
var date = iBase.Id(dateId);
var timeLine = iBase.Id(timeLineId);
var titletop = iBase.Id(titleTop);
var title = iBase.Id(titleId);
var iTimeSildeW = iTimeSilde.offsetWidth;//幻灯区实际宽度
var timePoint = document.createElement('ul');//用来存储时间点的ul
var timePointLeft = null;//时间点相对于父元素左边距离
var timePointLeftCur = null;//每两个时间点间距
var pointIndex = 0;//时间点在队列中的索引值
var defaultShow = defaultShow || 0;//默认显示的时间
var clearFun=null;//当用户无意识的划过时中止执行
var that=null;
//根据数据条数生成对应的时间点html
for (var i = 0; i < dataLen; i++) {
timePoint.innerHTML += '<li></li>';
}
//将时间点插入到时间线DIV中
timeLine.appendChild(timePoint)
var timePoints = timeLine.getElementsByTagName('li');
//时间点平滑显示
for (var i = 0; i < timePoints.length; i++) {
//每两个时间点间间距
timePointLeftCur = parseInt(iTimeSildeW / (dataLen + 1));
//计算对应时间点左边距
timePointLeft = (i + 1) * timePointLeftCur;
//时间点动画形式初始化
iBase.PointSlide(timePoints[i], timePointLeft);
//初始显示时间点
setTimeout(function(){
timePoints[defaultShow].onmouseover();
}, 1200);
//获取时间点默认class值,为鼠标事件做准备
timePoints[i].oldClassName = timePoints[i].className;
timePoints[i].onmouseover = function(){
that = this;//确保clearFun中的this是当前的this
//提升用户体验,当用户无意识地划过时不执行函数
clearFun=setTimeout(function(){
//计算出当前时间点索引值,为鼠标划出做准备
pointIndex = iBase.Index(that, timePoints);
//去除上一个时间点高亮样式
for (var m = 0; m < timePoints.length; m++) {
if (m != pointIndex) {
timePoints[m].className = timePoints[m].oldClassName
}
}
//为当前时间点加载高亮样式
iBase.AddClass(that, 'hover');
//切换日期及标题值
date.innerHTML = '<span>' + (JSONData[pointIndex]['date'] || '') + '</span>';
title.innerHTML = '<a href="' + (JSONData[pointIndex]['href'] || '') + '">' + (JSONData[pointIndex]['title'] || '') + '</a>';
//改变日期及标题的位置,此处减去的数字,可根据实际样式调整
date.style.left = ((pointIndex + 1) * timePointLeftCur - 25) + 'px';
titletop.style.left = ((pointIndex + 1) * timePointLeftCur + 6) + 'px';
//当标题框左边距与标题框宽度之和大于外围宽度时,以右边为绝对点
if ((title.offsetWidth + (pointIndex + 1) * timePointLeftCur) < iTimeSildeW) {
title.style.left = ((pointIndex + 1) * timePointLeftCur - timePointLeftCur) + 'px';
}else {
title.style.left = (iTimeSildeW - title.offsetWidth) + 'px';
}
//显示日期/时间点/标题
date.style.display = 'block';
titletop.style.display = 'block';
title.style.display = 'block';
},200);//200为认定无意识划过的时间,可自行调节
}
timePoints[i].onmouseout = function(){
//若停留时间低于200ms,认定为无意识划过,中止函数
clearTimeout(clearFun);
}
}
}
效果不错,继续支持一下~
[回复]
利害之前在找這效果1個星期多了,剛從51看到所以特來你的網站留言
JS我也不太熟悉但是你的注釋很清楚所以應該都了解
對呀怎麼不弄成juqery 也不錯的
總之謝謝你呀 哈 不錯的效果收下學習了
[回复]
Mr.Think 回复:
一月 3rd, 2011 at 08:34
@小毛, 抱歉, 我只是分享出我写这个效果的思路, 不希望沦为写效果的工具. 如果给你了原创Js的函数思路,你还写不出jQ效果,说明你需要学习jQ.
[回复]
小毛 回复:
一月 3rd, 2011 at 15:58
@Mr.Think大, 別誤會了,我不是說要您在幫我改成什麼
我只是特來謝謝你寫出這個好東西,我是正在學習JS的朋友沒有其他意思的^^ 謝謝
[回复]
Mr.Think 回复:
一月 3rd, 2011 at 19:47
@小毛, 哈~ 理解万岁…
小毛 回复:
十月 13th, 2011 at 09:30
@Mr.Think, 你好呀^^
這陣子又回來看看您的作品
自己摸索來摸索去發現為什麼
//当标题框左边距与标题框宽度之和大于外围宽度时,以右边为绝对点
好像以右边为绝对点
會造成反覆選到時間點後訊息框裡的內容會不斷移動
我改成
}else {
title.style.left = timePointLeftCur + ‘px’;
}
好像就不會有這現象您認為呢有更好的方式嗎
因為JS我實在是沒像您這麼熟
[回复]
小毛 回复:
十月 13th, 2011 at 10:08
@小毛, 唉我這寫法也不對
尤其第一個時間點直接跳到最後一個時間點的時候最明顯
框忽大忽小的
我看騰迅的好像就沒這問題不知道怎麼寫的
腦神經衰弱了
试了demo,没看代码,应该设定鼠标坐标位置监听域,弹出事件触发域位置平均分配
用户用依着那小点来查看事件,是很麻烦的吧
[回复]
Mr.Think 回复:
一月 2nd, 2011 at 19:12
@F, 哈~ 想法不错,你可以试试~
[回复]
博主收了,好东西
[回复]
请问您的博客主机选的是哪家的?
[回复]
Mr.Think 回复:
十二月 28th, 2010 at 19:16
@萝卜,中电数据,但到期后会换.速度不尽人意,再者天朝备案能把人烦死,还是找家国外的主机吧.
[回复]
不错,有时间看一下
[回复]
建议能否用Jquery做一个版本的
[回复]
Mr.Think 回复:
十二月 27th, 2010 at 17:29
@itsky, 哈,那你就按我的这个思路重写个JQ的吧. 用Js重写jQ效果可能要动点脑子, 用jQ重写Js效果岂不很容易~
[回复]
有点儿卡,可以提高下FPS
[回复]
Mr.Think 回复:
十二月 27th, 2010 at 09:13
@hellohtml5, 是指动画速度? PointSlide中i+=5的值改小点即可
[回复]